diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/char/tpm/tpm-dev-common.c | 6 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm-sysfs.c | 87 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm.h | 15 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 73 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm2-space.c | 4 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_crb.c | 59 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_tis.c | 5 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_tis_core.c | 6 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_tis_core.h | 4 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_tis_spi.c | 73 |
10 files changed, 161 insertions, 171 deletions
diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index 610638a80383..461bf0b8a094 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c | |||
| @@ -110,6 +110,12 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf, | |||
| 110 | return -EFAULT; | 110 | return -EFAULT; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | if (in_size < 6 || | ||
| 114 | in_size < be32_to_cpu(*((__be32 *) (priv->data_buffer + 2)))) { | ||
| 115 | mutex_unlock(&priv->buffer_mutex); | ||
| 116 | return -EINVAL; | ||
| 117 | } | ||
| 118 | |||
| 113 | /* atomic tpm command send and result receive. We only hold the ops | 119 | /* atomic tpm command send and result receive. We only hold the ops |
| 114 | * lock during this period so that the tpm can be unregistered even if | 120 | * lock during this period so that the tpm can be unregistered even if |
| 115 | * the char dev is held open. | 121 | * the char dev is held open. |
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index 86f38d239476..83a77a445538 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c | |||
| @@ -20,44 +20,48 @@ | |||
| 20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
| 21 | #include "tpm.h" | 21 | #include "tpm.h" |
| 22 | 22 | ||
| 23 | #define READ_PUBEK_RESULT_SIZE 314 | 23 | struct tpm_readpubek_out { |
| 24 | u8 algorithm[4]; | ||
| 25 | u8 encscheme[2]; | ||
| 26 | u8 sigscheme[2]; | ||
| 27 | __be32 paramsize; | ||
| 28 | u8 parameters[12]; | ||
| 29 | __be32 keysize; | ||
| 30 | u8 modulus[256]; | ||
| 31 | u8 checksum[20]; | ||
| 32 | } __packed; | ||
| 33 | |||
| 24 | #define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256) | 34 | #define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256) |
| 25 | #define TPM_ORD_READPUBEK 124 | 35 | #define TPM_ORD_READPUBEK 124 |
| 26 | static const struct tpm_input_header tpm_readpubek_header = { | 36 | |
| 27 | .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), | ||
| 28 | .length = cpu_to_be32(30), | ||
| 29 | .ordinal = cpu_to_be32(TPM_ORD_READPUBEK) | ||
| 30 | }; | ||
| 31 | static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, | 37 | static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, |
| 32 | char *buf) | 38 | char *buf) |
| 33 | { | 39 | { |
| 34 | u8 *data; | 40 | struct tpm_buf tpm_buf; |
| 35 | struct tpm_cmd_t tpm_cmd; | 41 | struct tpm_readpubek_out *out; |
| 36 | ssize_t err; | 42 | ssize_t rc; |
| 37 | int i, rc; | 43 | int i; |
| 38 | char *str = buf; | 44 | char *str = buf; |
| 39 | struct tpm_chip *chip = to_tpm_chip(dev); | 45 | struct tpm_chip *chip = to_tpm_chip(dev); |
| 46 | char anti_replay[20]; | ||
| 40 | 47 | ||
| 41 | memset(&tpm_cmd, 0, sizeof(tpm_cmd)); | 48 | memset(&anti_replay, 0, sizeof(anti_replay)); |
| 42 | 49 | ||
| 43 | tpm_cmd.header.in = tpm_readpubek_header; | 50 | rc = tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK); |
| 44 | err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE, | 51 | if (rc) |
| 45 | READ_PUBEK_RESULT_MIN_BODY_SIZE, 0, | 52 | return rc; |
| 46 | "attempting to read the PUBEK"); | 53 | |
| 47 | if (err) | 54 | tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay)); |
| 48 | goto out; | 55 | |
| 49 | 56 | rc = tpm_transmit_cmd(chip, NULL, tpm_buf.data, PAGE_SIZE, | |
| 50 | /* | 57 | READ_PUBEK_RESULT_MIN_BODY_SIZE, 0, |
| 51 | ignore header 10 bytes | 58 | "attempting to read the PUBEK"); |
| 52 | algorithm 32 bits (1 == RSA ) | 59 | if (rc) { |
| 53 | encscheme 16 bits | 60 | tpm_buf_destroy(&tpm_buf); |
| 54 | sigscheme 16 bits | 61 | return 0; |
| 55 | parameters (RSA 12->bytes: keybit, #primes, expbit) | 62 | } |
| 56 | keylenbytes 32 bits | 63 | |
| 57 | 256 byte modulus | 64 | out = (struct tpm_readpubek_out *)&tpm_buf.data[10]; |
| 58 | ignore checksum 20 bytes | ||
| 59 | */ | ||
| 60 | data = tpm_cmd.params.readpubek_out_buffer; | ||
| 61 | str += | 65 | str += |
| 62 | sprintf(str, | 66 | sprintf(str, |
| 63 | "Algorithm: %02X %02X %02X %02X\n" | 67 | "Algorithm: %02X %02X %02X %02X\n" |
| @@ -68,21 +72,26 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, | |||
| 68 | "%02X %02X %02X %02X\n" | 72 | "%02X %02X %02X %02X\n" |
| 69 | "Modulus length: %d\n" | 73 | "Modulus length: %d\n" |
| 70 | "Modulus:\n", | 74 | "Modulus:\n", |
| 71 | data[0], data[1], data[2], data[3], | 75 | out->algorithm[0], out->algorithm[1], out->algorithm[2], |
| 72 | data[4], data[5], | 76 | out->algorithm[3], |
| 73 | data[6], data[7], | 77 | out->encscheme[0], out->encscheme[1], |
| 74 | data[12], data[13], data[14], data[15], | 78 | out->sigscheme[0], out->sigscheme[1], |
| 75 | data[16], data[17], data[18], data[19], | 79 | out->parameters[0], out->parameters[1], |
| 76 | data[20], data[21], data[22], data[23], | 80 | out->parameters[2], out->parameters[3], |
| 77 | be32_to_cpu(*((__be32 *) (data + 24)))); | 81 | out->parameters[4], out->parameters[5], |
| 82 | out->parameters[6], out->parameters[7], | ||
| 83 | out->parameters[8], out->parameters[9], | ||
| 84 | out->parameters[10], out->parameters[11], | ||
| 85 | be32_to_cpu(out->keysize)); | ||
| 78 | 86 | ||
| 79 | for (i = 0; i < 256; i++) { | 87 | for (i = 0; i < 256; i++) { |
| 80 | str += sprintf(str, "%02X ", data[i + 28]); | 88 | str += sprintf(str, "%02X ", out->modulus[i]); |
| 81 | if ((i + 1) % 16 == 0) | 89 | if ((i + 1) % 16 == 0) |
| 82 | str += sprintf(str, "\n"); | 90 | str += sprintf(str, "\n"); |
| 83 | } | 91 | } |
| 84 | out: | 92 | |
| 85 | rc = str - buf; | 93 | rc = str - buf; |
| 94 | tpm_buf_destroy(&tpm_buf); | ||
| 86 | return rc; | 95 | return rc; |
| 87 | } | 96 | } |
| 88 | static DEVICE_ATTR_RO(pubek); | 97 | static DEVICE_ATTR_RO(pubek); |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 2d5466a72e40..528cffbd49d3 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
| @@ -345,17 +345,6 @@ enum tpm_sub_capabilities { | |||
| 345 | TPM_CAP_PROP_TIS_DURATION = 0x120, | 345 | TPM_CAP_PROP_TIS_DURATION = 0x120, |
| 346 | }; | 346 | }; |
| 347 | 347 | ||
| 348 | struct tpm_readpubek_params_out { | ||
| 349 | u8 algorithm[4]; | ||
| 350 | u8 encscheme[2]; | ||
| 351 | u8 sigscheme[2]; | ||
| 352 | __be32 paramsize; | ||
| 353 | u8 parameters[12]; /*assuming RSA*/ | ||
| 354 | __be32 keysize; | ||
| 355 | u8 modulus[256]; | ||
| 356 | u8 checksum[20]; | ||
| 357 | } __packed; | ||
| 358 | |||
| 359 | typedef union { | 348 | typedef union { |
| 360 | struct tpm_input_header in; | 349 | struct tpm_input_header in; |
| 361 | struct tpm_output_header out; | 350 | struct tpm_output_header out; |
| @@ -385,8 +374,6 @@ struct tpm_getrandom_in { | |||
| 385 | } __packed; | 374 | } __packed; |
| 386 | 375 | ||
| 387 | typedef union { | 376 | typedef union { |
| 388 | struct tpm_readpubek_params_out readpubek_out; | ||
| 389 | u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; | ||
| 390 | struct tpm_pcrread_in pcrread_in; | 377 | struct tpm_pcrread_in pcrread_in; |
| 391 | struct tpm_pcrread_out pcrread_out; | 378 | struct tpm_pcrread_out pcrread_out; |
| 392 | struct tpm_getrandom_in getrandom_in; | 379 | struct tpm_getrandom_in getrandom_in; |
| @@ -557,7 +544,7 @@ static inline void tpm_add_ppi(struct tpm_chip *chip) | |||
| 557 | } | 544 | } |
| 558 | #endif | 545 | #endif |
| 559 | 546 | ||
| 560 | static inline inline u32 tpm2_rc_value(u32 rc) | 547 | static inline u32 tpm2_rc_value(u32 rc) |
| 561 | { | 548 | { |
| 562 | return (rc & BIT(7)) ? rc & 0xff : rc; | 549 | return (rc & BIT(7)) ? rc & 0xff : rc; |
| 563 | } | 550 | } |
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index e1a41b788f08..f40d20671a78 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c | |||
| @@ -834,72 +834,43 @@ static const struct tpm_input_header tpm2_selftest_header = { | |||
| 834 | }; | 834 | }; |
| 835 | 835 | ||
| 836 | /** | 836 | /** |
| 837 | * tpm2_continue_selftest() - start a self test | 837 | * tpm2_do_selftest() - ensure that all self tests have passed |
| 838 | * | ||
| 839 | * @chip: TPM chip to use | ||
| 840 | * @full: test all commands instead of testing only those that were not | ||
| 841 | * previously tested. | ||
| 842 | * | ||
| 843 | * Return: Same as with tpm_transmit_cmd with exception of RC_TESTING. | ||
| 844 | */ | ||
| 845 | static int tpm2_start_selftest(struct tpm_chip *chip, bool full) | ||
| 846 | { | ||
| 847 | int rc; | ||
| 848 | struct tpm2_cmd cmd; | ||
| 849 | |||
| 850 | cmd.header.in = tpm2_selftest_header; | ||
| 851 | cmd.params.selftest_in.full_test = full; | ||
| 852 | |||
| 853 | rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0, | ||
| 854 | "continue selftest"); | ||
| 855 | |||
| 856 | /* At least some prototype chips seem to give RC_TESTING error | ||
| 857 | * immediately. This is a workaround for that. | ||
| 858 | */ | ||
| 859 | if (rc == TPM2_RC_TESTING) { | ||
| 860 | dev_warn(&chip->dev, "Got RC_TESTING, ignoring\n"); | ||
| 861 | rc = 0; | ||
| 862 | } | ||
| 863 | |||
| 864 | return rc; | ||
| 865 | } | ||
| 866 | |||
| 867 | /** | ||
| 868 | * tpm2_do_selftest() - run a full self test | ||
| 869 | * | 838 | * |
| 870 | * @chip: TPM chip to use | 839 | * @chip: TPM chip to use |
| 871 | * | 840 | * |
| 872 | * Return: Same as with tpm_transmit_cmd. | 841 | * Return: Same as with tpm_transmit_cmd. |
| 873 | * | 842 | * |
| 874 | * During the self test TPM2 commands return with the error code RC_TESTING. | 843 | * The TPM can either run all self tests synchronously and then return |
| 875 | * Waiting is done by issuing PCR read until it executes successfully. | 844 | * RC_SUCCESS once all tests were successful. Or it can choose to run the tests |
| 845 | * asynchronously and return RC_TESTING immediately while the self tests still | ||
| 846 | * execute in the background. This function handles both cases and waits until | ||
| 847 | * all tests have completed. | ||
| 876 | */ | 848 | */ |
| 877 | static int tpm2_do_selftest(struct tpm_chip *chip) | 849 | static int tpm2_do_selftest(struct tpm_chip *chip) |
| 878 | { | 850 | { |
| 879 | int rc; | 851 | int rc; |
| 880 | unsigned int loops; | 852 | unsigned int delay_msec = 20; |
| 881 | unsigned int delay_msec = 100; | 853 | long duration; |
| 882 | unsigned long duration; | 854 | struct tpm2_cmd cmd; |
| 883 | int i; | ||
| 884 | |||
| 885 | duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST); | ||
| 886 | 855 | ||
| 887 | loops = jiffies_to_msecs(duration) / delay_msec; | 856 | duration = jiffies_to_msecs( |
| 857 | tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST)); | ||
| 888 | 858 | ||
| 889 | rc = tpm2_start_selftest(chip, true); | 859 | while (duration > 0) { |
| 890 | if (rc) | 860 | cmd.header.in = tpm2_selftest_header; |
| 891 | return rc; | 861 | cmd.params.selftest_in.full_test = 0; |
| 892 | 862 | ||
| 893 | for (i = 0; i < loops; i++) { | 863 | rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, |
| 894 | /* Attempt to read a PCR value */ | 864 | 0, 0, "continue selftest"); |
| 895 | rc = tpm2_pcr_read(chip, 0, NULL); | ||
| 896 | if (rc < 0) | ||
| 897 | break; | ||
| 898 | 865 | ||
| 899 | if (rc != TPM2_RC_TESTING) | 866 | if (rc != TPM2_RC_TESTING) |
| 900 | break; | 867 | break; |
| 901 | 868 | ||
| 902 | tpm_msleep(delay_msec); | 869 | tpm_msleep(delay_msec); |
| 870 | duration -= delay_msec; | ||
| 871 | |||
| 872 | /* wait longer the next round */ | ||
| 873 | delay_msec *= 2; | ||
| 903 | } | 874 | } |
| 904 | 875 | ||
| 905 | return rc; | 876 | return rc; |
| @@ -1009,7 +980,7 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) | |||
| 1009 | { | 980 | { |
| 1010 | struct tpm_buf buf; | 981 | struct tpm_buf buf; |
| 1011 | u32 nr_commands; | 982 | u32 nr_commands; |
| 1012 | u32 *attrs; | 983 | __be32 *attrs; |
| 1013 | u32 cc; | 984 | u32 cc; |
| 1014 | int i; | 985 | int i; |
| 1015 | int rc; | 986 | int rc; |
| @@ -1049,7 +1020,7 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) | |||
| 1049 | 1020 | ||
| 1050 | chip->nr_commands = nr_commands; | 1021 | chip->nr_commands = nr_commands; |
| 1051 | 1022 | ||
| 1052 | attrs = (u32 *)&buf.data[TPM_HEADER_SIZE + 9]; | 1023 | attrs = (__be32 *)&buf.data[TPM_HEADER_SIZE + 9]; |
| 1053 | for (i = 0; i < nr_commands; i++, attrs++) { | 1024 | for (i = 0; i < nr_commands; i++, attrs++) { |
| 1054 | chip->cc_attrs_tbl[i] = be32_to_cpup(attrs); | 1025 | chip->cc_attrs_tbl[i] = be32_to_cpup(attrs); |
| 1055 | cc = chip->cc_attrs_tbl[i] & 0xFFFF; | 1026 | cc = chip->cc_attrs_tbl[i] & 0xFFFF; |
diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index e2e059d8ffec..4e4014eabdb9 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c | |||
| @@ -242,7 +242,7 @@ static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd) | |||
| 242 | struct tpm_space *space = &chip->work_space; | 242 | struct tpm_space *space = &chip->work_space; |
| 243 | unsigned int nr_handles; | 243 | unsigned int nr_handles; |
| 244 | u32 attrs; | 244 | u32 attrs; |
| 245 | u32 *handle; | 245 | __be32 *handle; |
| 246 | int i; | 246 | int i; |
| 247 | 247 | ||
| 248 | i = tpm2_find_cc(chip, cc); | 248 | i = tpm2_find_cc(chip, cc); |
| @@ -252,7 +252,7 @@ static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd) | |||
| 252 | attrs = chip->cc_attrs_tbl[i]; | 252 | attrs = chip->cc_attrs_tbl[i]; |
| 253 | nr_handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0); | 253 | nr_handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0); |
| 254 | 254 | ||
| 255 | handle = (u32 *)&cmd[TPM_HEADER_SIZE]; | 255 | handle = (__be32 *)&cmd[TPM_HEADER_SIZE]; |
| 256 | for (i = 0; i < nr_handles; i++, handle++) { | 256 | for (i = 0; i < nr_handles; i++, handle++) { |
| 257 | if ((be32_to_cpu(*handle) & 0xFF000000) == TPM2_HT_TRANSIENT) { | 257 | if ((be32_to_cpu(*handle) & 0xFF000000) == TPM2_HT_TRANSIENT) { |
| 258 | if (!tpm2_map_to_phandle(space, handle)) | 258 | if (!tpm2_map_to_phandle(space, handle)) |
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 8f0a98dea327..7b3c2a8aa9de 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c | |||
| @@ -92,14 +92,9 @@ enum crb_status { | |||
| 92 | CRB_DRV_STS_COMPLETE = BIT(0), | 92 | CRB_DRV_STS_COMPLETE = BIT(0), |
| 93 | }; | 93 | }; |
| 94 | 94 | ||
| 95 | enum crb_flags { | ||
| 96 | CRB_FL_ACPI_START = BIT(0), | ||
| 97 | CRB_FL_CRB_START = BIT(1), | ||
| 98 | CRB_FL_CRB_SMC_START = BIT(2), | ||
| 99 | }; | ||
| 100 | |||
| 101 | struct crb_priv { | 95 | struct crb_priv { |
| 102 | unsigned int flags; | 96 | u32 sm; |
| 97 | const char *hid; | ||
| 103 | void __iomem *iobase; | 98 | void __iomem *iobase; |
| 104 | struct crb_regs_head __iomem *regs_h; | 99 | struct crb_regs_head __iomem *regs_h; |
| 105 | struct crb_regs_tail __iomem *regs_t; | 100 | struct crb_regs_tail __iomem *regs_t; |
| @@ -128,14 +123,16 @@ struct tpm2_crb_smc { | |||
| 128 | * Anyhow, we do not wait here as a consequent CMD_READY request | 123 | * Anyhow, we do not wait here as a consequent CMD_READY request |
| 129 | * will be handled correctly even if idle was not completed. | 124 | * will be handled correctly even if idle was not completed. |
| 130 | * | 125 | * |
| 131 | * The function does nothing for devices with ACPI-start method. | 126 | * The function does nothing for devices with ACPI-start method |
| 127 | * or SMC-start method. | ||
| 132 | * | 128 | * |
| 133 | * Return: 0 always | 129 | * Return: 0 always |
| 134 | */ | 130 | */ |
| 135 | static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) | 131 | static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) |
| 136 | { | 132 | { |
| 137 | if ((priv->flags & CRB_FL_ACPI_START) || | 133 | if ((priv->sm == ACPI_TPM2_START_METHOD) || |
| 138 | (priv->flags & CRB_FL_CRB_SMC_START)) | 134 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || |
| 135 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC)) | ||
| 139 | return 0; | 136 | return 0; |
| 140 | 137 | ||
| 141 | iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); | 138 | iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); |
| @@ -174,14 +171,16 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, | |||
| 174 | * The device should respond within TIMEOUT_C. | 171 | * The device should respond within TIMEOUT_C. |
| 175 | * | 172 | * |
| 176 | * The function does nothing for devices with ACPI-start method | 173 | * The function does nothing for devices with ACPI-start method |
| 174 | * or SMC-start method. | ||
| 177 | * | 175 | * |
| 178 | * Return: 0 on success -ETIME on timeout; | 176 | * Return: 0 on success -ETIME on timeout; |
| 179 | */ | 177 | */ |
| 180 | static int __maybe_unused crb_cmd_ready(struct device *dev, | 178 | static int __maybe_unused crb_cmd_ready(struct device *dev, |
| 181 | struct crb_priv *priv) | 179 | struct crb_priv *priv) |
| 182 | { | 180 | { |
| 183 | if ((priv->flags & CRB_FL_ACPI_START) || | 181 | if ((priv->sm == ACPI_TPM2_START_METHOD) || |
| 184 | (priv->flags & CRB_FL_CRB_SMC_START)) | 182 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || |
| 183 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC)) | ||
| 185 | return 0; | 184 | return 0; |
| 186 | 185 | ||
| 187 | iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req); | 186 | iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req); |
| @@ -325,13 +324,20 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
| 325 | /* Make sure that cmd is populated before issuing start. */ | 324 | /* Make sure that cmd is populated before issuing start. */ |
| 326 | wmb(); | 325 | wmb(); |
| 327 | 326 | ||
| 328 | if (priv->flags & CRB_FL_CRB_START) | 327 | /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs |
| 328 | * report only ACPI start but in practice seems to require both | ||
| 329 | * CRB start, hence invoking CRB start method if hid == MSFT0101. | ||
| 330 | */ | ||
| 331 | if ((priv->sm == ACPI_TPM2_COMMAND_BUFFER) || | ||
| 332 | (priv->sm == ACPI_TPM2_MEMORY_MAPPED) || | ||
| 333 | (!strcmp(priv->hid, "MSFT0101"))) | ||
| 329 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); | 334 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); |
| 330 | 335 | ||
| 331 | if (priv->flags & CRB_FL_ACPI_START) | 336 | if ((priv->sm == ACPI_TPM2_START_METHOD) || |
| 337 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD)) | ||
| 332 | rc = crb_do_acpi_start(chip); | 338 | rc = crb_do_acpi_start(chip); |
| 333 | 339 | ||
| 334 | if (priv->flags & CRB_FL_CRB_SMC_START) { | 340 | if (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) { |
| 335 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); | 341 | iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); |
| 336 | rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id); | 342 | rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id); |
| 337 | } | 343 | } |
| @@ -345,7 +351,9 @@ static void crb_cancel(struct tpm_chip *chip) | |||
| 345 | 351 | ||
| 346 | iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel); | 352 | iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel); |
| 347 | 353 | ||
| 348 | if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip)) | 354 | if (((priv->sm == ACPI_TPM2_START_METHOD) || |
| 355 | (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD)) && | ||
| 356 | crb_do_acpi_start(chip)) | ||
| 349 | dev_err(&chip->dev, "ACPI Start failed\n"); | 357 | dev_err(&chip->dev, "ACPI Start failed\n"); |
| 350 | } | 358 | } |
| 351 | 359 | ||
| @@ -458,7 +466,8 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, | |||
| 458 | * the control area, as one nice sane region except for some older | 466 | * the control area, as one nice sane region except for some older |
| 459 | * stuff that puts the control area outside the ACPI IO region. | 467 | * stuff that puts the control area outside the ACPI IO region. |
| 460 | */ | 468 | */ |
| 461 | if (!(priv->flags & CRB_FL_ACPI_START)) { | 469 | if ((priv->sm == ACPI_TPM2_COMMAND_BUFFER) || |
| 470 | (priv->sm == ACPI_TPM2_MEMORY_MAPPED)) { | ||
| 462 | if (buf->control_address == io_res.start + | 471 | if (buf->control_address == io_res.start + |
| 463 | sizeof(*priv->regs_h)) | 472 | sizeof(*priv->regs_h)) |
| 464 | priv->regs_h = priv->iobase; | 473 | priv->regs_h = priv->iobase; |
| @@ -552,18 +561,6 @@ static int crb_acpi_add(struct acpi_device *device) | |||
| 552 | if (!priv) | 561 | if (!priv) |
| 553 | return -ENOMEM; | 562 | return -ENOMEM; |
| 554 | 563 | ||
| 555 | /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs | ||
| 556 | * report only ACPI start but in practice seems to require both | ||
| 557 | * ACPI start and CRB start. | ||
| 558 | */ | ||
| 559 | if (sm == ACPI_TPM2_COMMAND_BUFFER || sm == ACPI_TPM2_MEMORY_MAPPED || | ||
| 560 | !strcmp(acpi_device_hid(device), "MSFT0101")) | ||
| 561 | priv->flags |= CRB_FL_CRB_START; | ||
| 562 | |||
| 563 | if (sm == ACPI_TPM2_START_METHOD || | ||
| 564 | sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) | ||
| 565 | priv->flags |= CRB_FL_ACPI_START; | ||
| 566 | |||
| 567 | if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) { | 564 | if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) { |
| 568 | if (buf->header.length < (sizeof(*buf) + sizeof(*crb_smc))) { | 565 | if (buf->header.length < (sizeof(*buf) + sizeof(*crb_smc))) { |
| 569 | dev_err(dev, | 566 | dev_err(dev, |
| @@ -574,9 +571,11 @@ static int crb_acpi_add(struct acpi_device *device) | |||
| 574 | } | 571 | } |
| 575 | crb_smc = ACPI_ADD_PTR(struct tpm2_crb_smc, buf, sizeof(*buf)); | 572 | crb_smc = ACPI_ADD_PTR(struct tpm2_crb_smc, buf, sizeof(*buf)); |
| 576 | priv->smc_func_id = crb_smc->smc_func_id; | 573 | priv->smc_func_id = crb_smc->smc_func_id; |
| 577 | priv->flags |= CRB_FL_CRB_SMC_START; | ||
| 578 | } | 574 | } |
| 579 | 575 | ||
| 576 | priv->sm = sm; | ||
| 577 | priv->hid = acpi_device_hid(device); | ||
| 578 | |||
| 580 | rc = crb_map_io(device, priv, buf); | 579 | rc = crb_map_io(device, priv, buf); |
| 581 | if (rc) | 580 | if (rc) |
| 582 | return rc; | 581 | return rc; |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 7e55aa9ce680..e2d1055fb814 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/freezer.h> | 30 | #include <linux/freezer.h> |
| 31 | #include <linux/of.h> | 31 | #include <linux/of.h> |
| 32 | #include <linux/of_device.h> | 32 | #include <linux/of_device.h> |
| 33 | #include <linux/kernel.h> | ||
| 33 | #include "tpm.h" | 34 | #include "tpm.h" |
| 34 | #include "tpm_tis_core.h" | 35 | #include "tpm_tis_core.h" |
| 35 | 36 | ||
| @@ -223,7 +224,7 @@ static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, | |||
| 223 | } | 224 | } |
| 224 | 225 | ||
| 225 | static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, | 226 | static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, |
| 226 | u8 *value) | 227 | const u8 *value) |
| 227 | { | 228 | { |
| 228 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); | 229 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
| 229 | 230 | ||
| @@ -365,7 +366,7 @@ static struct pnp_driver tis_pnp_driver = { | |||
| 365 | }, | 366 | }, |
| 366 | }; | 367 | }; |
| 367 | 368 | ||
| 368 | #define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2 | 369 | #define TIS_HID_USR_IDX (ARRAY_SIZE(tpm_pnp_tbl) - 2) |
| 369 | module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, | 370 | module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, |
| 370 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); | 371 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); |
| 371 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); | 372 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); |
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 63bc6c3b949e..fdde971bc810 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c | |||
| @@ -252,7 +252,7 @@ out: | |||
| 252 | * tpm.c can skip polling for the data to be available as the interrupt is | 252 | * tpm.c can skip polling for the data to be available as the interrupt is |
| 253 | * waited for here | 253 | * waited for here |
| 254 | */ | 254 | */ |
| 255 | static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | 255 | static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) |
| 256 | { | 256 | { |
| 257 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | 257 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
| 258 | int rc, status, burstcnt; | 258 | int rc, status, burstcnt; |
| @@ -343,7 +343,7 @@ static void disable_interrupts(struct tpm_chip *chip) | |||
| 343 | * tpm.c can skip polling for the data to be available as the interrupt is | 343 | * tpm.c can skip polling for the data to be available as the interrupt is |
| 344 | * waited for here | 344 | * waited for here |
| 345 | */ | 345 | */ |
| 346 | static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) | 346 | static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) |
| 347 | { | 347 | { |
| 348 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | 348 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
| 349 | int rc; | 349 | int rc; |
| @@ -445,7 +445,7 @@ static int probe_itpm(struct tpm_chip *chip) | |||
| 445 | { | 445 | { |
| 446 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | 446 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
| 447 | int rc = 0; | 447 | int rc = 0; |
| 448 | u8 cmd_getticks[] = { | 448 | static const u8 cmd_getticks[] = { |
| 449 | 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, | 449 | 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, |
| 450 | 0x00, 0x00, 0x00, 0xf1 | 450 | 0x00, 0x00, 0x00, 0xf1 |
| 451 | }; | 451 | }; |
diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h index e2212f021a02..6bbac319ff3b 100644 --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h | |||
| @@ -98,7 +98,7 @@ struct tpm_tis_phy_ops { | |||
| 98 | int (*read_bytes)(struct tpm_tis_data *data, u32 addr, u16 len, | 98 | int (*read_bytes)(struct tpm_tis_data *data, u32 addr, u16 len, |
| 99 | u8 *result); | 99 | u8 *result); |
| 100 | int (*write_bytes)(struct tpm_tis_data *data, u32 addr, u16 len, | 100 | int (*write_bytes)(struct tpm_tis_data *data, u32 addr, u16 len, |
| 101 | u8 *value); | 101 | const u8 *value); |
| 102 | int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result); | 102 | int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result); |
| 103 | int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result); | 103 | int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result); |
| 104 | int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src); | 104 | int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src); |
| @@ -128,7 +128,7 @@ static inline int tpm_tis_read32(struct tpm_tis_data *data, u32 addr, | |||
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | static inline int tpm_tis_write_bytes(struct tpm_tis_data *data, u32 addr, | 130 | static inline int tpm_tis_write_bytes(struct tpm_tis_data *data, u32 addr, |
| 131 | u16 len, u8 *value) | 131 | u16 len, const u8 *value) |
| 132 | { | 132 | { |
| 133 | return data->phy_ops->write_bytes(data, addr, len, value); | 133 | return data->phy_ops->write_bytes(data, addr, len, value); |
| 134 | } | 134 | } |
diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index 88fe72ae967f..424ff2fde1f2 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c | |||
| @@ -46,9 +46,7 @@ | |||
| 46 | struct tpm_tis_spi_phy { | 46 | struct tpm_tis_spi_phy { |
| 47 | struct tpm_tis_data priv; | 47 | struct tpm_tis_data priv; |
| 48 | struct spi_device *spi_device; | 48 | struct spi_device *spi_device; |
| 49 | 49 | u8 *iobuf; | |
| 50 | u8 tx_buf[4]; | ||
| 51 | u8 rx_buf[4]; | ||
| 52 | }; | 50 | }; |
| 53 | 51 | ||
| 54 | static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data) | 52 | static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data) |
| @@ -57,7 +55,7 @@ static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *da | |||
| 57 | } | 55 | } |
| 58 | 56 | ||
| 59 | static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, | 57 | static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, |
| 60 | u8 *buffer, u8 direction) | 58 | u8 *in, const u8 *out) |
| 61 | { | 59 | { |
| 62 | struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); | 60 | struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); |
| 63 | int ret = 0; | 61 | int ret = 0; |
| @@ -71,14 +69,14 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, | |||
| 71 | while (len) { | 69 | while (len) { |
| 72 | transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE); | 70 | transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE); |
| 73 | 71 | ||
| 74 | phy->tx_buf[0] = direction | (transfer_len - 1); | 72 | phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1); |
| 75 | phy->tx_buf[1] = 0xd4; | 73 | phy->iobuf[1] = 0xd4; |
| 76 | phy->tx_buf[2] = addr >> 8; | 74 | phy->iobuf[2] = addr >> 8; |
| 77 | phy->tx_buf[3] = addr; | 75 | phy->iobuf[3] = addr; |
| 78 | 76 | ||
| 79 | memset(&spi_xfer, 0, sizeof(spi_xfer)); | 77 | memset(&spi_xfer, 0, sizeof(spi_xfer)); |
| 80 | spi_xfer.tx_buf = phy->tx_buf; | 78 | spi_xfer.tx_buf = phy->iobuf; |
| 81 | spi_xfer.rx_buf = phy->rx_buf; | 79 | spi_xfer.rx_buf = phy->iobuf; |
| 82 | spi_xfer.len = 4; | 80 | spi_xfer.len = 4; |
| 83 | spi_xfer.cs_change = 1; | 81 | spi_xfer.cs_change = 1; |
| 84 | 82 | ||
| @@ -88,9 +86,9 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, | |||
| 88 | if (ret < 0) | 86 | if (ret < 0) |
| 89 | goto exit; | 87 | goto exit; |
| 90 | 88 | ||
| 91 | if ((phy->rx_buf[3] & 0x01) == 0) { | 89 | if ((phy->iobuf[3] & 0x01) == 0) { |
| 92 | // handle SPI wait states | 90 | // handle SPI wait states |
| 93 | phy->tx_buf[0] = 0; | 91 | phy->iobuf[0] = 0; |
| 94 | 92 | ||
| 95 | for (i = 0; i < TPM_RETRY; i++) { | 93 | for (i = 0; i < TPM_RETRY; i++) { |
| 96 | spi_xfer.len = 1; | 94 | spi_xfer.len = 1; |
| @@ -99,7 +97,7 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, | |||
| 99 | ret = spi_sync_locked(phy->spi_device, &m); | 97 | ret = spi_sync_locked(phy->spi_device, &m); |
| 100 | if (ret < 0) | 98 | if (ret < 0) |
| 101 | goto exit; | 99 | goto exit; |
| 102 | if (phy->rx_buf[0] & 0x01) | 100 | if (phy->iobuf[0] & 0x01) |
| 103 | break; | 101 | break; |
| 104 | } | 102 | } |
| 105 | 103 | ||
| @@ -113,12 +111,12 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, | |||
| 113 | spi_xfer.len = transfer_len; | 111 | spi_xfer.len = transfer_len; |
| 114 | spi_xfer.delay_usecs = 5; | 112 | spi_xfer.delay_usecs = 5; |
| 115 | 113 | ||
| 116 | if (direction) { | 114 | if (in) { |
| 117 | spi_xfer.tx_buf = NULL; | 115 | spi_xfer.tx_buf = NULL; |
| 118 | spi_xfer.rx_buf = buffer; | 116 | } else if (out) { |
| 119 | } else { | ||
| 120 | spi_xfer.tx_buf = buffer; | ||
| 121 | spi_xfer.rx_buf = NULL; | 117 | spi_xfer.rx_buf = NULL; |
| 118 | memcpy(phy->iobuf, out, transfer_len); | ||
| 119 | out += transfer_len; | ||
| 122 | } | 120 | } |
| 123 | 121 | ||
| 124 | spi_message_init(&m); | 122 | spi_message_init(&m); |
| @@ -127,8 +125,12 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, | |||
| 127 | if (ret < 0) | 125 | if (ret < 0) |
| 128 | goto exit; | 126 | goto exit; |
| 129 | 127 | ||
| 128 | if (in) { | ||
| 129 | memcpy(in, phy->iobuf, transfer_len); | ||
| 130 | in += transfer_len; | ||
| 131 | } | ||
| 132 | |||
| 130 | len -= transfer_len; | 133 | len -= transfer_len; |
| 131 | buffer += transfer_len; | ||
| 132 | } | 134 | } |
| 133 | 135 | ||
| 134 | exit: | 136 | exit: |
| @@ -139,40 +141,51 @@ exit: | |||
| 139 | static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, | 141 | static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, |
| 140 | u16 len, u8 *result) | 142 | u16 len, u8 *result) |
| 141 | { | 143 | { |
| 142 | return tpm_tis_spi_transfer(data, addr, len, result, 0x80); | 144 | return tpm_tis_spi_transfer(data, addr, len, result, NULL); |
| 143 | } | 145 | } |
| 144 | 146 | ||
| 145 | static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr, | 147 | static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr, |
| 146 | u16 len, u8 *value) | 148 | u16 len, const u8 *value) |
| 147 | { | 149 | { |
| 148 | return tpm_tis_spi_transfer(data, addr, len, value, 0); | 150 | return tpm_tis_spi_transfer(data, addr, len, NULL, value); |
| 149 | } | 151 | } |
| 150 | 152 | ||
| 151 | static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) | 153 | static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) |
| 152 | { | 154 | { |
| 155 | __le16 result_le; | ||
| 153 | int rc; | 156 | int rc; |
| 154 | 157 | ||
| 155 | rc = data->phy_ops->read_bytes(data, addr, sizeof(u16), (u8 *)result); | 158 | rc = data->phy_ops->read_bytes(data, addr, sizeof(u16), |
| 159 | (u8 *)&result_le); | ||
| 156 | if (!rc) | 160 | if (!rc) |
| 157 | *result = le16_to_cpu(*result); | 161 | *result = le16_to_cpu(result_le); |
| 162 | |||
| 158 | return rc; | 163 | return rc; |
| 159 | } | 164 | } |
| 160 | 165 | ||
| 161 | static int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result) | 166 | static int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result) |
| 162 | { | 167 | { |
| 168 | __le32 result_le; | ||
| 163 | int rc; | 169 | int rc; |
| 164 | 170 | ||
| 165 | rc = data->phy_ops->read_bytes(data, addr, sizeof(u32), (u8 *)result); | 171 | rc = data->phy_ops->read_bytes(data, addr, sizeof(u32), |
| 172 | (u8 *)&result_le); | ||
| 166 | if (!rc) | 173 | if (!rc) |
| 167 | *result = le32_to_cpu(*result); | 174 | *result = le32_to_cpu(result_le); |
| 175 | |||
| 168 | return rc; | 176 | return rc; |
| 169 | } | 177 | } |
| 170 | 178 | ||
| 171 | static int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value) | 179 | static int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value) |
| 172 | { | 180 | { |
| 173 | value = cpu_to_le32(value); | 181 | __le32 value_le; |
| 174 | return data->phy_ops->write_bytes(data, addr, sizeof(u32), | 182 | int rc; |
| 175 | (u8 *)&value); | 183 | |
| 184 | value_le = cpu_to_le32(value); | ||
| 185 | rc = data->phy_ops->write_bytes(data, addr, sizeof(u32), | ||
| 186 | (u8 *)&value_le); | ||
| 187 | |||
| 188 | return rc; | ||
| 176 | } | 189 | } |
| 177 | 190 | ||
| 178 | static const struct tpm_tis_phy_ops tpm_spi_phy_ops = { | 191 | static const struct tpm_tis_phy_ops tpm_spi_phy_ops = { |
| @@ -194,6 +207,10 @@ static int tpm_tis_spi_probe(struct spi_device *dev) | |||
| 194 | 207 | ||
| 195 | phy->spi_device = dev; | 208 | phy->spi_device = dev; |
| 196 | 209 | ||
| 210 | phy->iobuf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL); | ||
| 211 | if (!phy->iobuf) | ||
| 212 | return -ENOMEM; | ||
| 213 | |||
| 197 | return tpm_tis_core_init(&dev->dev, &phy->priv, -1, &tpm_spi_phy_ops, | 214 | return tpm_tis_core_init(&dev->dev, &phy->priv, -1, &tpm_spi_phy_ops, |
| 198 | NULL); | 215 | NULL); |
| 199 | } | 216 | } |
