1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright 2022 IBM Corp. 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <fdtdec.h> 9 #include <i2c.h> 10 #include <log.h> 11 #include <tpm-v2.h> 12 #include <linux/bitops.h> 13 #include <linux/delay.h> 14 #include <linux/errno.h> 15 #include <linux/compiler.h> 16 #include <linux/types.h> 17 #include <linux/unaligned/be_byteshift.h> 18 #include <asm-generic/gpio.h> 19 20 #include "tpm_tis.h" 21 #include "tpm_internal.h" 22 23 struct tpm_tis_chip_data { 24 unsigned int pcr_count; 25 unsigned int pcr_select_min; 26 }; 27 28 static uint tpm_tis_i2c_address_to_register(u32 addr) 29 { 30 addr &= 0xFFF; 31 32 /* 33 * Adapt register addresses that have changed compared to older TIS 34 * version. 35 */ 36 switch (addr) { 37 case TPM_ACCESS(0): 38 return 0x04; 39 case TPM_DID_VID(0): 40 return 0x48; 41 case TPM_RID(0): 42 return 0x4C; 43 default: 44 return addr; 45 } 46 } 47 48 static int tpm_tis_i2c_read(struct udevice *dev, u32 addr, u16 len, u8 *in) 49 { 50 int rc; 51 int count = 0; 52 uint reg = tpm_tis_i2c_address_to_register(addr); 53 54 do { 55 rc = dm_i2c_read(dev, reg, in, len); 56 udelay(SLEEP_DURATION_US); 57 } while (rc && count++ < MAX_COUNT); 58 59 return rc; 60 } 61 62 static int tpm_tis_i2c_write(struct udevice *dev, u32 addr, u16 len, 63 const u8 *out) 64 { 65 int rc; 66 int count = 0; 67 uint reg = tpm_tis_i2c_address_to_register(addr); 68 69 do { 70 rc = dm_i2c_write(dev, reg, out, len); 71 udelay(SLEEP_DURATION_US); 72 } while (rc && count++ < MAX_COUNT); 73 74 return rc; 75 } 76 77 static int tpm_tis_i2c_read32(struct udevice *dev, u32 addr, u32 *result) 78 { 79 __le32 result_le; 80 int rc; 81 82 rc = tpm_tis_i2c_read(dev, addr, sizeof(u32), (u8 *)&result_le); 83 if (!rc) 84 *result = le32_to_cpu(result_le); 85 86 return rc; 87 } 88 89 static int tpm_tis_i2c_write32(struct udevice *dev, u32 addr, u32 value) 90 { 91 __le32 value_le = cpu_to_le32(value); 92 93 return tpm_tis_i2c_write(dev, addr, sizeof(value), (u8 *)&value_le); 94 } 95 96 static struct tpm_tis_phy_ops phy_ops = { 97 .read_bytes = tpm_tis_i2c_read, 98 .write_bytes = tpm_tis_i2c_write, 99 .read32 = tpm_tis_i2c_read32, 100 .write32 = tpm_tis_i2c_write32, 101 }; 102 103 static int tpm_tis_i2c_probe(struct udevice *udev) 104 { 105 struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(udev); 106 struct tpm_chip_priv *priv = dev_get_uclass_priv(udev); 107 int rc; 108 u8 loc = 0; 109 110 tpm_tis_ops_register(udev, &phy_ops); 111 112 /* 113 * Force locality 0. The core driver doesn't actually write the 114 * locality register and instead just reads/writes various access 115 * bits of the selected locality. 116 */ 117 rc = dm_i2c_write(udev, 0, &loc, 1); 118 if (rc) 119 return rc; 120 121 rc = tpm_tis_init(udev); 122 if (rc) 123 return rc; 124 125 priv->pcr_count = drv_data->pcr_count; 126 priv->pcr_select_min = drv_data->pcr_select_min; 127 priv->version = TPM_V2; 128 129 return 0; 130 } 131 132 static int tpm_tis_i2c_remove(struct udevice *udev) 133 { 134 return tpm_tis_cleanup(udev); 135 } 136 137 static const struct tpm_ops tpm_tis_i2c_ops = { 138 .open = tpm_tis_open, 139 .close = tpm_tis_close, 140 .get_desc = tpm_tis_get_desc, 141 .send = tpm_tis_send, 142 .recv = tpm_tis_recv, 143 .cleanup = tpm_tis_cleanup, 144 }; 145 146 static const struct tpm_tis_chip_data tpm_tis_std_chip_data = { 147 .pcr_count = 24, 148 .pcr_select_min = 3, 149 }; 150 151 static const struct udevice_id tpm_tis_i2c_ids[] = { 152 { 153 .compatible = "nuvoton,npct75x", 154 .data = (ulong)&tpm_tis_std_chip_data, 155 }, 156 { 157 .compatible = "tcg,tpm-tis-i2c", 158 .data = (ulong)&tpm_tis_std_chip_data, 159 }, 160 { } 161 }; 162 163 U_BOOT_DRIVER(tpm_tis_i2c) = { 164 .name = "tpm_tis_i2c", 165 .id = UCLASS_TPM, 166 .of_match = tpm_tis_i2c_ids, 167 .ops = &tpm_tis_i2c_ops, 168 .probe = tpm_tis_i2c_probe, 169 .remove = tpm_tis_i2c_remove, 170 .priv_auto_alloc_size = sizeof(struct tpm_chip), 171 }; 172