static int tpmfront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { struct tpm_private *priv; int rv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { xenbus_dev_fatal(dev, -ENOMEM, "allocating priv structure"); return -ENOMEM; } rv = setup_chip(&dev->dev, priv); if (rv) { kfree(priv); return rv; } rv = setup_ring(dev, priv); if (rv) { ring_free(priv); return rv; } tpm_get_timeouts(priv->chip); return tpm_chip_register(priv->chip); }
static int i2c_atmel_probe(struct i2c_client *client, const struct i2c_device_id *id) { int rc; struct tpm_chip *chip; struct device *dev = &client->dev; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; chip = tpm_register_hardware(dev, &i2c_atmel); if (!chip) { dev_err(dev, "%s() error in tpm_register_hardware\n", __func__); return -ENODEV; } chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); if (!chip->vendor.priv) { rc = -ENOMEM; goto out_err; } /* Default timeouts */ chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); chip->vendor.timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT); chip->vendor.timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); chip->vendor.timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); chip->vendor.irq = 0; /* There is no known way to probe for this device, and all version * information seems to be read via TPM commands. Thus we rely on the * TPM startup process in the common code to detect the device. */ if (tpm_get_timeouts(chip)) { rc = -ENODEV; goto out_err; } if (tpm_do_selftest(chip)) { rc = -ENODEV; goto out_err; } return 0; out_err: tpm_dev_vendor_release(chip); tpm_remove_hardware(chip->dev); return rc; }
/** * tpm1_auto_startup - Perform the standard automatic TPM initialization * sequence * @chip: TPM chip to use * * Returns 0 on success, < 0 in case of fatal error. */ int tpm1_auto_startup(struct tpm_chip *chip) { int rc; rc = tpm_get_timeouts(chip); if (rc) goto out; rc = tpm_do_selftest(chip); if (rc) { dev_err(&chip->dev, "TPM self test failed\n"); goto out; } return rc; out: if (rc > 0) rc = -ENODEV; return rc; }
static int i2c_atmel_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tpm_chip *chip; struct device *dev = &client->dev; struct priv_data *priv; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; chip = tpmm_chip_alloc(dev, &i2c_atmel); if (IS_ERR(chip)) return PTR_ERR(chip); priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); if (!priv) return -ENOMEM; /* Default timeouts */ chip->timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); chip->timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT); chip->timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); chip->timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); dev_set_drvdata(&chip->dev, priv); /* There is no known way to probe for this device, and all version * information seems to be read via TPM commands. Thus we rely on the * TPM startup process in the common code to detect the device. */ if (tpm_get_timeouts(chip)) return -ENODEV; if (tpm_do_selftest(chip)) return -ENODEV; return tpm_chip_register(chip); }
static int __devinit tpm_tis_i2c_init(struct device *dev) { u32 vendor; int rc = 0; struct tpm_chip *chip; chip = tpm_register_hardware(dev, &tpm_tis_i2c); if (!chip) { rc = -ENODEV; goto out_err; } /* Disable interrupts */ chip->vendor.irq = 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); if (request_locality(chip, 0) != 0) { rc = -ENODEV; goto out_vendor; } /* read four bytes from DID_VID register */ if (iic_tpm_read(TPM_DID_VID(0), (u8 *)&vendor, 4) < 0) { rc = -EIO; goto out_release; } /* create DID_VID register value, after swapping to little-endian */ vendor = be32_to_cpu((__be32) vendor); if (vendor != TPM_TIS_I2C_DID_VID) { rc = -ENODEV; goto out_release; } dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16); INIT_LIST_HEAD(&chip->vendor.list); tpm_dev.chip = chip; tpm_get_timeouts(chip); tpm_do_selftest(chip); return 0; out_release: release_locality(chip, chip->vendor.locality, 1); out_vendor: /* close file handles */ tpm_dev_vendor_release(chip); /* remove hardware */ tpm_remove_hardware(chip->dev); /* reset these pointers, otherwise we oops */ chip->dev->release = NULL; chip->release = NULL; tpm_dev.client = NULL; dev_set_drvdata(chip->dev, chip); out_err: return rc; }
/* * tpm_st33_i2c_probe initialize the TPM device * @param: client, the i2c_client drescription (TPM I2C description). * @param: id, the i2c_device_id struct. * @return: 0 in case of success. * -1 in other case. */ static int tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int err; u8 intmask; struct tpm_chip *chip; struct st33zp24_platform_data *platform_data; if (client == NULL) { pr_info("%s: i2c client is NULL. Device not accessible.\n", __func__); err = -ENODEV; goto end; } if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_info(&client->dev, "client not i2c capable\n"); err = -ENODEV; goto end; } chip = tpm_register_hardware(&client->dev, &st_i2c_tpm); if (!chip) { dev_info(&client->dev, "fail chip\n"); err = -ENODEV; goto end; } platform_data = client->dev.platform_data; if (!platform_data) { dev_info(&client->dev, "chip not available\n"); err = -ENODEV; goto _tpm_clean_answer; } platform_data->tpm_i2c_buffer[0] = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); if (platform_data->tpm_i2c_buffer[0] == NULL) { err = -ENOMEM; goto _tpm_clean_answer; } platform_data->tpm_i2c_buffer[1] = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); if (platform_data->tpm_i2c_buffer[1] == NULL) { err = -ENOMEM; goto _tpm_clean_response1; } TPM_VPRIV(chip) = client; 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); chip->vendor.locality = LOCALITY0; if (power_mgt) { err = gpio_request(platform_data->io_lpcpd, "TPM IO_LPCPD"); if (err) goto _gpio_init1; gpio_set_value(platform_data->io_lpcpd, 1); } if (interrupts) { init_completion(&platform_data->irq_detection); if (request_locality(chip) != LOCALITY0) { err = -ENODEV; goto _tpm_clean_response2; } err = gpio_request(platform_data->io_serirq, "TPM IO_SERIRQ"); if (err) goto _gpio_init2; clear_interruption(client); err = request_irq(gpio_to_irq(platform_data->io_serirq), &tpm_ioserirq_handler, IRQF_TRIGGER_HIGH, "TPM SERIRQ management", chip); if (err < 0) { dev_err(chip->dev , "TPM SERIRQ signals %d not available\n", gpio_to_irq(platform_data->io_serirq)); goto _irq_set; } err = I2C_READ_DATA(client, TPM_INT_ENABLE, &intmask, 1); if (err < 0) goto _irq_set; intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_FIFO_AVALAIBLE_INT | TPM_INTF_WAKE_UP_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT | TPM_INTF_DATA_AVAIL_INT; err = I2C_WRITE_DATA(client, TPM_INT_ENABLE, &intmask, 1); if (err < 0) goto _irq_set; intmask = TPM_GLOBAL_INT_ENABLE; err = I2C_WRITE_DATA(client, (TPM_INT_ENABLE + 3), &intmask, 1); if (err < 0) goto _irq_set; err = I2C_READ_DATA(client, TPM_INT_STATUS, &intmask, 1); if (err < 0) goto _irq_set; chip->vendor.irq = interrupts; tpm_gen_interrupt(chip); } tpm_get_timeouts(chip); i2c_set_clientdata(client, chip); dev_info(chip->dev, "TPM I2C Initialized\n"); return 0; _irq_set: free_irq(gpio_to_irq(platform_data->io_serirq), (void *) chip); _gpio_init2: if (interrupts) gpio_free(platform_data->io_serirq); _gpio_init1: if (power_mgt) gpio_free(platform_data->io_lpcpd); _tpm_clean_response2: kzfree(platform_data->tpm_i2c_buffer[1]); platform_data->tpm_i2c_buffer[1] = NULL; _tpm_clean_response1: kzfree(platform_data->tpm_i2c_buffer[0]); platform_data->tpm_i2c_buffer[0] = NULL; _tpm_clean_answer: tpm_remove_hardware(chip->dev); end: pr_info("TPM I2C initialisation fail\n"); return err; }
struct tpm_chip* init_tpm_tis(unsigned long baseaddr, int localities, unsigned int irq) { int i; unsigned long addr; struct tpm_chip* tpm = NULL; uint32_t didvid; uint32_t intfcaps; uint32_t intmask; printk("============= Init TPM TIS Driver ==============\n"); /*Sanity check the localities input */ if(localities & ~TPM_TIS_EN_LOCLALL) { printk("init_tpm_tis() Invalid locality specification! %X\n", localities); goto abort_egress; } printk("IOMEM Machine Base Address: %lX\n", baseaddr); /* Create the tpm data structure */ tpm = malloc(sizeof(struct tpm_chip)); __init_tpm_chip(tpm); /* Set the enabled localities - if 0 we leave default as all enabled */ if(localities != 0) { tpm->enabled_localities = localities; } printk("Enabled Localities: "); for(i = 0; i < 5; ++i) { if(locality_enabled(tpm, i)) { printk("%d ", i); } } printk("\n"); /* Set the base machine address */ tpm->baseaddr = baseaddr; /* Set default timeouts */ tpm->timeout_a = MILLISECS(TIS_SHORT_TIMEOUT); tpm->timeout_b = MILLISECS(TIS_LONG_TIMEOUT); tpm->timeout_c = MILLISECS(TIS_SHORT_TIMEOUT); tpm->timeout_d = MILLISECS(TIS_SHORT_TIMEOUT); /*Map the mmio pages */ addr = tpm->baseaddr; for(i = 0; i < 5; ++i) { if(locality_enabled(tpm, i)) { /* Map the page in now */ if((tpm->pages[i] = ioremap_nocache(addr, PAGE_SIZE)) == NULL) { printk("Unable to map iomem page a address %p\n", addr); goto abort_egress; } /* Set default locality to the first enabled one */ if (tpm->locality < 0) { if(tpm_tis_request_locality(tpm, i) < 0) { printk("Unable to request locality %d??\n", i); goto abort_egress; } } } addr += PAGE_SIZE; } /* Get the vendor and device ids */ didvid = ioread32(TPM_DID_VID(tpm, tpm->locality)); tpm->did = didvid >> 16; tpm->vid = didvid & 0xFFFF; /* Get the revision id */ tpm->rid = ioread8(TPM_RID(tpm, tpm->locality)); printk("1.2 TPM (device-id=0x%X vendor-id = %X rev-id = %X)\n", tpm->did, tpm->vid, tpm->rid); intfcaps = ioread32(TPM_INTF_CAPS(tpm, tpm->locality)); printk("TPM interface capabilities (0x%x):\n", intfcaps); if (intfcaps & TPM_INTF_BURST_COUNT_STATIC) printk("\tBurst Count Static\n"); if (intfcaps & TPM_INTF_CMD_READY_INT) printk("\tCommand Ready Int Support\n"); if (intfcaps & TPM_INTF_INT_EDGE_FALLING) printk("\tInterrupt Edge Falling\n"); if (intfcaps & TPM_INTF_INT_EDGE_RISING) printk("\tInterrupt Edge Rising\n"); if (intfcaps & TPM_INTF_INT_LEVEL_LOW) printk("\tInterrupt Level Low\n"); if (intfcaps & TPM_INTF_INT_LEVEL_HIGH) printk("\tInterrupt Level High\n"); if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) printk("\tLocality Change Int Support\n"); if (intfcaps & TPM_INTF_STS_VALID_INT) printk("\tSts Valid Int Support\n"); if (intfcaps & TPM_INTF_DATA_AVAIL_INT) printk("\tData Avail Int Support\n"); /*Interupt setup */ intmask = ioread32(TPM_INT_ENABLE(tpm, tpm->locality)); intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT; iowrite32(TPM_INT_ENABLE(tpm, tpm->locality), intmask); /*If interupts are enabled, handle it */ if(irq) { if(irq != TPM_PROBE_IRQ) { tpm->irq = irq; } else { /*FIXME add irq probing feature later */ printk("IRQ probing not implemented\n"); } } if(tpm->irq) { iowrite8(TPM_INT_VECTOR(tpm, tpm->locality), tpm->irq); if(bind_pirq(tpm->irq, 1, tpm_tis_irq_handler, tpm) != 0) { printk("Unabled to request irq: %u for use\n", tpm->irq); printk("Will use polling mode\n"); tpm->irq = 0; } else { /* Clear all existing */ iowrite32(TPM_INT_STATUS(tpm, tpm->locality), ioread32(TPM_INT_STATUS(tpm, tpm->locality))); /* Turn on interrupts */ iowrite32(TPM_INT_ENABLE(tpm, tpm->locality), intmask | TPM_GLOBAL_INT_ENABLE); } } if(tpm_get_timeouts(tpm)) { printk("Could not get TPM timeouts and durations\n"); goto abort_egress; } tpm_continue_selftest(tpm); return tpm; abort_egress: if(tpm != NULL) { shutdown_tpm_tis(tpm); } return NULL; }
/* * tpm_stm_i2c_probe initialize the TPM device * @param: client, the i2c_client drescription (TPM I2C description). * @param: id, the i2c_device_id struct. * @return: 0 in case of success. * -1 in other case. */ static int tpm_stm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret; u8 intmask = 0; struct tpm_chip *chip; struct st33zp24_platform_data *platform_data; struct tpm_stm_dev *tpm_dev; if (!client) { pr_info("%s: i2c client is NULL. Device not accessible.\n", __func__); return -ENODEV; } if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_info(&client->dev, "client not i2c capable\n"); return -ENODEV; } tpm_dev = devm_kzalloc(&client->dev, sizeof(struct tpm_stm_dev), GFP_KERNEL); if (!tpm_dev) return -ENOMEM; chip = tpmm_chip_alloc(&client->dev, &st_i2c_tpm); if (IS_ERR(chip)) return PTR_ERR(chip); TPM_VPRIV(chip) = tpm_dev; tpm_dev->client = client; platform_data = client->dev.platform_data; if (!platform_data && client->dev.of_node) { ret = tpm_stm_i2c_of_request_resources(chip); if (ret) goto _tpm_clean_answer; } else if (platform_data) { ret = tpm_stm_i2c_request_resources(client, chip); if (ret) goto _tpm_clean_answer; } 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); chip->vendor.locality = LOCALITY0; if (client->irq) { /* INTERRUPT Setup */ init_waitqueue_head(&chip->vendor.read_queue); tpm_dev->intrs = 0; if (request_locality(chip) != LOCALITY0) { ret = -ENODEV; goto _tpm_clean_answer; } clear_interruption(tpm_dev); ret = devm_request_irq(&client->dev, client->irq, tpm_ioserirq_handler, IRQF_TRIGGER_HIGH, "TPM SERIRQ management", chip); if (ret < 0) { dev_err(chip->pdev, "TPM SERIRQ signals %d not available\n", client->irq); goto _tpm_clean_answer; } intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_STS_VALID_INT | TPM_INTF_DATA_AVAIL_INT; ret = I2C_WRITE_DATA(tpm_dev, TPM_INT_ENABLE, &intmask, 1); if (ret < 0) goto _tpm_clean_answer; intmask = TPM_GLOBAL_INT_ENABLE; ret = I2C_WRITE_DATA(tpm_dev, (TPM_INT_ENABLE + 3), &intmask, 1); if (ret < 0) goto _tpm_clean_answer; chip->vendor.irq = client->irq; disable_irq_nosync(chip->vendor.irq); tpm_gen_interrupt(chip); } tpm_get_timeouts(chip); tpm_do_selftest(chip); return tpm_chip_register(chip); _tpm_clean_answer: dev_info(chip->pdev, "TPM I2C initialisation fail\n"); return ret; }