Skip to content

Commit

Permalink
Merge pull request #7 from tesors/IXR-27-TPM
Browse files Browse the repository at this point in the history
Ixr 27 tpm
  • Loading branch information
pksg authored Aug 11, 2023
2 parents 8b75623 + 04e8e6c commit 2ad705a
Show file tree
Hide file tree
Showing 12 changed files with 570 additions and 68 deletions.
2 changes: 1 addition & 1 deletion arch/arm64/boot/dts/rockchip/rk3568-firefly-port.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@
pinctrl-0 = <&spi1m1_pins>;
pinctrl-1 = <&spi1m1_pins_hs>;

spi_wk2xxx: spi_wk2xxx@00{
spi_wk2xxx: spi_wk2xxx@0{
status = "disabled";
compatible = "firefly,spi-wk2xxx";
reg = <0x00>;
Expand Down
17 changes: 17 additions & 0 deletions arch/arm64/boot/dts/rockchip/rk3568-ixon-3568q.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@
reg = <0x2e>;
};

slb9673@2e{
compatible = "infineon,slb9673","tcg,tpm-tis-i2c" ;
reg = <0x2e>;
#address-cells = <2>;
#size-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&slb9673_gpio>;
status = "okay";
};

/delete-node/ xc6130@23;
};

Expand Down Expand Up @@ -419,6 +429,13 @@

&pinctrl {

slb9673 {
slb9673_gpio: slb9673-gpio{
rockchip,pins =
/*TPM_RST*/
<3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>;
};
};
gmac0 {
gmac0_gpio: gmac0-gpio {
rockchip,pins =
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/boot/dts/rockchip/rk356x-firefly-demo.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

/* Firefly SPI demo */
&spi1 {
spi_demo: spi-demo@00{
spi_demo: spi-demo@0{
status = "disabled";
compatible = "firefly,rk356x-spi";
reg = <0x00>;
Expand Down
9 changes: 9 additions & 0 deletions arch/arm64/configs/ixon_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,15 @@ CONFIG_BATTERY_RK818=y
CONFIG_CHARGER_RK818=y
CONFIG_CHARGER_SGM41542=y
CONFIG_SENSORS_PWM_FAN=y
CONFIG_TCG_TPM=y
CONFIG_HW_RANDOM_TPM=y
CONFIG_TCG_TIS_CORE=y
CONFIG_TCG_TIS=y
CONFIG_TCG_TIS_SPI=y
CONFIG_TCG_TIS_I2C_INFINEON=y
CONFIG_TCG_CRB=y
CONFIG_TCG_INFINEON=y
CONFIG_TCG_TIS_I2C=y
CONFIG_THERMAL=y
CONFIG_THERMAL_WRITABLE_TRIPS=y
CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR=y
Expand Down
12 changes: 12 additions & 0 deletions drivers/char/tpm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,18 @@ config TCG_TIS_SYNQUACER
To compile this driver as a module, choose M here;
the module will be called tpm_tis_synquacer.

config TCG_TIS_I2C
tristate "TPM Interface Specification 1.3 Interface / TPM 2.0 FIFO Interface - (I2C - generic)"
depends on I2C
select CRC_CCITT
select TCG_TIS_CORE
help
If you have a TPM security chip, compliant with the TCG TPM PTP
(I2C interface) specification and connected to an I2C bus master,
say Yes and it will be accessible from within Linux.
To compile this driver as a module, choose M here;
the module will be called tpm_tis_i2c.

config TCG_TIS_I2C_ATMEL
tristate "TPM Interface Specification 1.2 Interface (I2C - Atmel)"
depends on I2C
Expand Down
1 change: 1 addition & 0 deletions drivers/char/tpm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o
tpm_tis_spi-y := tpm_tis_spi_main.o
tpm_tis_spi-$(CONFIG_TCG_TIS_SPI_CR50) += tpm_tis_spi_cr50.o

obj-$(CONFIG_TCG_TIS_I2C) += tpm_tis_i2c.o
obj-$(CONFIG_TCG_TIS_I2C_ATMEL) += tpm_i2c_atmel.o
obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o
obj-$(CONFIG_TCG_TIS_I2C_NUVOTON) += tpm_i2c_nuvoton.o
Expand Down
78 changes: 70 additions & 8 deletions drivers/char/tpm/tpm_tis.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,45 @@ static inline struct tpm_tis_tcg_phy *to_tpm_tis_tcg_phy(struct tpm_tis_data *da
return container_of(data, struct tpm_tis_tcg_phy, priv);
}

#ifdef CONFIG_PREEMPT_RT
/*
* Flush previous write operations with a dummy read operation to the
* TPM MMIO base address.
*/
static inline void tpm_tis_flush(void __iomem *iobase)
{
ioread8(iobase + TPM_ACCESS(0));
}
#else
#define tpm_tis_flush(iobase) do { } while (0)
#endif

/*
* Write a byte word to the TPM MMIO address, and flush the write queue.
* The flush ensures that the data is sent immediately over the bus and not
* aggregated with further requests and transferred later in a batch. The large
* write requests can lead to unwanted latency spikes by blocking the CPU until
* the complete batch has been transferred.
*/
static inline void tpm_tis_iowrite8(u8 b, void __iomem *iobase, u32 addr)
{
iowrite8(b, iobase + addr);
tpm_tis_flush(iobase);
}

/*
* Write a 32-bit word to the TPM MMIO address, and flush the write queue.
* The flush ensures that the data is sent immediately over the bus and not
* aggregated with further requests and transferred later in a batch. The large
* write requests can lead to unwanted latency spikes by blocking the CPU until
* the complete batch has been transferred.
*/
static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr)
{
iowrite32(b, iobase + addr);
tpm_tis_flush(iobase);
}

static int interrupts = -1;
module_param(interrupts, int, 0444);
MODULE_PARM_DESC(interrupts, "Enable interrupts");
Expand Down Expand Up @@ -153,23 +192,46 @@ static int check_acpi_tpm2(struct device *dev)
#endif

static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
u8 *result)
u8 *result, enum tpm_tis_io_mode io_mode)
{
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);

while (len--)
*result++ = ioread8(phy->iobase + addr);
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
__le16 result_le16;
__le32 result_le32;

switch (io_mode) {
case TPM_TIS_PHYS_8:
while (len--)
*result++ = ioread8(phy->iobase + addr);
break;
case TPM_TIS_PHYS_16:
result_le16 = cpu_to_le16(ioread16(phy->iobase + addr));
memcpy(result, &result_le16, sizeof(u16));
break;
case TPM_TIS_PHYS_32:
result_le32 = cpu_to_le32(ioread32(phy->iobase + addr));
memcpy(result, &result_le32, sizeof(u32));
break;
}

return 0;
}

static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
const u8 *value)
const u8 *value, enum tpm_tis_io_mode io_mode)
{
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);

while (len--)
iowrite8(*value++, phy->iobase + addr);
switch (io_mode) {
case TPM_TIS_PHYS_8:
while (len--)
tpm_tis_iowrite8(*value++, phy->iobase, addr);
break;
case TPM_TIS_PHYS_16:
return -EINVAL;
case TPM_TIS_PHYS_32:
tpm_tis_iowrite32(le32_to_cpu(*((__le32 *)value)), phy->iobase, addr);
break;
}

return 0;
}
Expand Down
14 changes: 14 additions & 0 deletions drivers/char/tpm/tpm_tis_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,12 +289,20 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
int size = 0;
int status;
u32 expected;
int rc;

if (count < TPM_HEADER_SIZE) {
size = -EIO;
goto out;
}

rc = tpm_tis_verify_crc(priv, (size_t)size, buf);
if (rc < 0) {
dev_err(&chip->dev, "CRC mismatch for response.\n");
size = rc;
goto out;
}

size = recv_data(chip, buf, TPM_HEADER_SIZE);
/* read first 10 bytes, including tag, paramsize, and result */
if (size < TPM_HEADER_SIZE) {
Expand Down Expand Up @@ -443,6 +451,12 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
if (rc < 0)
return rc;

rc = tpm_tis_verify_crc(priv, len, buf);
if (rc < 0) {
dev_err(&chip->dev, "CRC mismatch for command.\n");
return rc;
}

/* go and do it */
rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO);
if (rc < 0)
Expand Down
65 changes: 55 additions & 10 deletions drivers/char/tpm/tpm_tis_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ enum tis_defaults {
#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000
#define ILB_REMAP_SIZE 0x100

/*
* IO modes to indicate how many bytes should be read/written at once in the
* tpm_tis_phy_ops read_bytes/write_bytes calls. Use TPM_TIS_PHYS_8 to
* receive/transmit byte-wise, TPM_TIS_PHYS_16 for two bytes etc.
*/
enum tpm_tis_io_mode {
TPM_TIS_PHYS_8,
TPM_TIS_PHYS_16,
TPM_TIS_PHYS_32,
};

enum tpm_tis_flags {
TPM_TIS_ITPM_WORKAROUND = BIT(0),
TPM_TIS_INVALID_STATUS = BIT(1),
Expand All @@ -105,10 +116,13 @@ struct tpm_tis_data {
};

struct tpm_tis_phy_ops {
/* data is passed in little endian */
int (*read_bytes)(struct tpm_tis_data *data, u32 addr, u16 len,
u8 *result);
u8 *result, enum tpm_tis_io_mode mode);
int (*write_bytes)(struct tpm_tis_data *data, u32 addr, u16 len,
const u8 *value);
const u8 *value, enum tpm_tis_io_mode mode);
int (*verify_crc)(struct tpm_tis_data *data, size_t len,
const u8 *value);
int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result);
int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result);
int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src);
Expand All @@ -117,43 +131,74 @@ struct tpm_tis_phy_ops {
static inline int tpm_tis_read_bytes(struct tpm_tis_data *data, u32 addr,
u16 len, u8 *result)
{
return data->phy_ops->read_bytes(data, addr, len, result);
return data->phy_ops->read_bytes(data, addr, len, result,
TPM_TIS_PHYS_8);
}

static inline int tpm_tis_read8(struct tpm_tis_data *data, u32 addr, u8 *result)
{
return data->phy_ops->read_bytes(data, addr, 1, result);
return data->phy_ops->read_bytes(data, addr, 1, result, TPM_TIS_PHYS_8);
}

static inline int tpm_tis_read16(struct tpm_tis_data *data, u32 addr,
u16 *result)
{
return data->phy_ops->read16(data, addr, result);
__le16 result_le;
int rc;

rc = data->phy_ops->read_bytes(data, addr, sizeof(u16),
(u8 *)&result_le, TPM_TIS_PHYS_16);
if (!rc)
*result = le16_to_cpu(result_le);

return rc;
}

static inline int tpm_tis_read32(struct tpm_tis_data *data, u32 addr,
u32 *result)
{
return data->phy_ops->read32(data, addr, result);
__le32 result_le;
int rc;

rc = data->phy_ops->read_bytes(data, addr, sizeof(u32),
(u8 *)&result_le, TPM_TIS_PHYS_32);
if (!rc)
*result = le32_to_cpu(result_le);

return rc;
}

static inline int tpm_tis_write_bytes(struct tpm_tis_data *data, u32 addr,
u16 len, const u8 *value)
{
return data->phy_ops->write_bytes(data, addr, len, value);
return data->phy_ops->write_bytes(data, addr, len, value,
TPM_TIS_PHYS_8);
}

static inline int tpm_tis_write8(struct tpm_tis_data *data, u32 addr, u8 value)
{
return data->phy_ops->write_bytes(data, addr, 1, &value);
return data->phy_ops->write_bytes(data, addr, 1, &value,
TPM_TIS_PHYS_8);
}

static inline int tpm_tis_write32(struct tpm_tis_data *data, u32 addr,
u32 value)
{
return data->phy_ops->write32(data, addr, value);
}
__le32 value_le;
int rc;

value_le = cpu_to_le32(value);
rc = data->phy_ops->write_bytes(data, addr, sizeof(u32),
(u8 *)&value_le, TPM_TIS_PHYS_32);
return rc;
}
static inline int tpm_tis_verify_crc(struct tpm_tis_data *data, size_t len,
const u8 *value)
{
if (!data->phy_ops->verify_crc)
return 0;
return data->phy_ops->verify_crc(data, len, value);
}
static inline bool is_bsw(void)
{
#ifdef CONFIG_X86
Expand Down
Loading

0 comments on commit 2ad705a

Please sign in to comment.