From bcbe3d157904d3dd4d6b18a81859db45a5da2678 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 28 Sep 2015 23:32:01 -0600 Subject: dm: Rename dev_get_parentdata() to dev_get_parent_priv() The current name is inconsistent with other driver model data access functions. Rename it and fix up all users. Signed-off-by: Simon Glass Reviewed-by: Joe Hershberger --- common/cmd_usb.c | 10 +++++----- common/usb_hub.c | 4 ++-- common/usb_storage.c | 2 +- doc/driver-model/usb-info.txt | 4 ++-- drivers/core/device.c | 2 +- drivers/misc/cros_ec_spi.c | 4 ++-- drivers/mtd/spi/sf_dataflash.c | 2 +- drivers/mtd/spi/sf_probe.c | 2 +- drivers/spi/fsl_qspi.c | 2 +- drivers/spi/ich.c | 2 +- drivers/spi/soft_spi.c | 2 +- drivers/spi/spi-uclass.c | 8 ++++---- drivers/usb/eth/smsc95xx.c | 4 ++-- drivers/usb/eth/usb_ether.c | 2 +- drivers/usb/host/ehci-hcd.c | 6 +++--- drivers/usb/host/usb-uclass.c | 8 ++++---- drivers/usb/host/xhci.c | 4 ++-- drivers/usb/musb-new/usb-compat.h | 10 +++++----- include/dm/device.h | 10 +++++----- include/pci.h | 2 +- include/spi.h | 2 +- include/usb.h | 2 +- test/dm/bus.c | 26 +++++++++++++------------- 23 files changed, 60 insertions(+), 60 deletions(-) diff --git a/common/cmd_usb.c b/common/cmd_usb.c index 6bdbbc5c05..1ef55dcd1c 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -281,7 +281,7 @@ static struct usb_device *usb_find_device(int devnum) if (!device_active(hub)) continue; - udev = dev_get_parentdata(hub); + udev = dev_get_parent_priv(hub); if (udev->devnum == devnum) return udev; @@ -291,7 +291,7 @@ static struct usb_device *usb_find_device(int devnum) if (!device_active(hub)) continue; - udev = dev_get_parentdata(dev); + udev = dev_get_parent_priv(dev); if (udev->devnum == devnum) return udev; } @@ -407,7 +407,7 @@ static void usb_show_tree_graph(struct usb_device *dev, char *pre) if (!device_active(child)) continue; - udev = dev_get_parentdata(child); + udev = dev_get_parent_priv(child); /* Ignore emulators, we only want real devices */ if (device_get_uclass_id(child) != UCLASS_USB_EMUL) { @@ -553,7 +553,7 @@ static void show_info(struct udevice *dev) struct udevice *child; struct usb_device *udev; - udev = dev_get_parentdata(dev); + udev = dev_get_parent_priv(dev); usb_display_desc(udev); usb_display_config(udev); for (device_find_first_child(dev, &child); @@ -641,7 +641,7 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) device_find_first_child(bus, &dev); if (dev && device_active(dev)) { - udev = dev_get_parentdata(dev); + udev = dev_get_parent_priv(dev); usb_show_tree(udev); } } diff --git a/common/usb_hub.c b/common/usb_hub.c index 415b45c1f1..a92c9fb73d 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -230,7 +230,7 @@ int legacy_hub_port_reset(struct usb_device *dev, int port, #ifdef CONFIG_DM_USB int hub_port_reset(struct udevice *dev, int port, unsigned short *portstat) { - struct usb_device *udev = dev_get_parentdata(dev); + struct usb_device *udev = dev_get_parent_priv(dev); return legacy_hub_port_reset(udev, port, portstat); } @@ -610,7 +610,7 @@ int usb_hub_probe(struct usb_device *dev, int ifnum) #ifdef CONFIG_DM_USB int usb_hub_scan(struct udevice *hub) { - struct usb_device *udev = dev_get_parentdata(hub); + struct usb_device *udev = dev_get_parent_priv(hub); return usb_hub_configure(udev); } diff --git a/common/usb_storage.c b/common/usb_storage.c index b390310ee3..0ccaeb4a14 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -1408,7 +1408,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, static int usb_mass_storage_probe(struct udevice *dev) { - struct usb_device *udev = dev_get_parentdata(dev); + struct usb_device *udev = dev_get_parent_priv(dev); int ret; usb_disable_asynch(1); /* asynch transfer not allowed */ diff --git a/doc/driver-model/usb-info.txt b/doc/driver-model/usb-info.txt index 66f2daec7c..e07e5ba261 100644 --- a/doc/driver-model/usb-info.txt +++ b/doc/driver-model/usb-info.txt @@ -84,7 +84,7 @@ The following primary data structures are in use: This holds information about a device on the bus. All devices have this structure, even the root hub. The controller itself does not have this structure. You can access it for a device 'dev' with - dev_get_parentdata(dev). It matches the old structure except that the + dev_get_parent_priv(dev). It matches the old structure except that the parent and child information is not present (since driver model handles that). Once the device is set up, you can find the device descriptor and current configuration descriptor in this structure. @@ -279,7 +279,7 @@ USB hubs are scanned as in the section above. While hubs have their own uclass, they share some common elements with controllers: - they both attach private data to their children (struct usb_device, -accessible for a child with dev_get_parentdata(child)) +accessible for a child with dev_get_parent_priv(child)) - they both use usb_child_pre_probe() to set up their children as proper USB devices diff --git a/drivers/core/device.c b/drivers/core/device.c index a3dc2ca679..758f39064c 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -395,7 +395,7 @@ void *dev_get_uclass_priv(struct udevice *dev) return dev->uclass_priv; } -void *dev_get_parentdata(struct udevice *dev) +void *dev_get_parent_priv(struct udevice *dev) { if (!dev) { dm_warn("%s: null device\n", __func__); diff --git a/drivers/misc/cros_ec_spi.c b/drivers/misc/cros_ec_spi.c index 0686925aaf..253d91a553 100644 --- a/drivers/misc/cros_ec_spi.c +++ b/drivers/misc/cros_ec_spi.c @@ -24,7 +24,7 @@ DECLARE_GLOBAL_DATA_PTR; int cros_ec_spi_packet(struct udevice *udev, int out_bytes, int in_bytes) { struct cros_ec_dev *dev = dev_get_uclass_priv(udev); - struct spi_slave *slave = dev_get_parentdata(dev->dev); + struct spi_slave *slave = dev_get_parent_priv(dev->dev); ulong start; uint8_t byte; int rv; @@ -84,7 +84,7 @@ int cros_ec_spi_command(struct udevice *udev, uint8_t cmd, int cmd_version, uint8_t **dinp, int din_len) { struct cros_ec_dev *dev = dev_get_uclass_priv(udev); - struct spi_slave *slave = dev_get_parentdata(dev->dev); + struct spi_slave *slave = dev_get_parent_priv(dev->dev); int in_bytes = din_len + 4; /* status, length, checksum, trailer */ uint8_t *out; uint8_t *p; diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/sf_dataflash.c index 3111f4fd12..b2a56da7ca 100644 --- a/drivers/mtd/spi/sf_dataflash.c +++ b/drivers/mtd/spi/sf_dataflash.c @@ -577,7 +577,7 @@ static struct flash_info *jedec_probe(struct spi_slave *spi, u8 *id) */ static int spi_dataflash_probe(struct udevice *dev) { - struct spi_slave *spi = dev_get_parentdata(dev); + struct spi_slave *spi = dev_get_parent_priv(dev); struct spi_flash *spi_flash; struct flash_info *info; u8 idcode[5]; diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 954376de15..3bf03f7a0a 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -471,7 +471,7 @@ int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) int spi_flash_std_probe(struct udevice *dev) { - struct spi_slave *slave = dev_get_parentdata(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); struct spi_flash *flash; diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index 868df5f121..02b557f0d9 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -913,7 +913,7 @@ void spi_init(void) #else static int fsl_qspi_child_pre_probe(struct udevice *dev) { - struct spi_slave *slave = dev_get_parentdata(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); slave->max_write_size = TX_BUFFER_SIZE; diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c index be4c0a3353..b974e8432c 100644 --- a/drivers/spi/ich.c +++ b/drivers/spi/ich.c @@ -740,7 +740,7 @@ static int ich_spi_child_pre_probe(struct udevice *dev) struct udevice *bus = dev_get_parent(dev); struct ich_spi_platdata *plat = dev_get_platdata(bus); struct ich_spi_priv *priv = dev_get_priv(bus); - struct spi_slave *slave = dev_get_parentdata(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); /* * Yes this controller can only write a small number of bytes at diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c index 6ae45f5377..aa4abcc3d2 100644 --- a/drivers/spi/soft_spi.c +++ b/drivers/spi/soft_spi.c @@ -200,7 +200,7 @@ static int soft_spi_ofdata_to_platdata(struct udevice *dev) static int soft_spi_probe(struct udevice *dev) { - struct spi_slave *slave = dev_get_parentdata(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); struct soft_spi_platdata *plat = dev->platdata; int cs_flags, clk_flags; diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index d666272e39..58388efbc3 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -124,7 +124,7 @@ static int spi_post_probe(struct udevice *bus) static int spi_child_pre_probe(struct udevice *dev) { struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); - struct spi_slave *slave = dev_get_parentdata(dev); + struct spi_slave *slave = dev_get_parent_priv(dev); /* * This is needed because we pass struct spi_slave around the place @@ -282,7 +282,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode, ret = device_probe(dev); if (ret) goto err; - slave = dev_get_parentdata(dev); + slave = dev_get_parent_priv(dev); slave->dev = dev; } @@ -291,7 +291,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode, goto err; *busp = bus; - *devp = dev_get_parentdata(dev); + *devp = dev_get_parent_priv(dev); debug("%s: bus=%p, slave=%p\n", __func__, bus, *devp); return 0; @@ -320,7 +320,7 @@ struct spi_slave *spi_setup_slave_fdt(const void *blob, int node, ret = device_get_child_by_of_offset(bus, node, &dev); if (ret) return NULL; - return dev_get_parentdata(dev); + return dev_get_parent_priv(dev); } /* Compatibility function - to be removed */ diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c index dc8fa8891b..d4b5ff465a 100644 --- a/drivers/usb/eth/smsc95xx.c +++ b/drivers/usb/eth/smsc95xx.c @@ -945,7 +945,7 @@ int smsc95xx_eth_get_info(struct usb_device *dev, struct ueth_data *ss, #ifdef CONFIG_DM_ETH static int smsc95xx_eth_start(struct udevice *dev) { - struct usb_device *udev = dev_get_parentdata(dev); + struct usb_device *udev = dev_get_parent_priv(dev); struct smsc95xx_private *priv = dev_get_priv(dev); struct eth_pdata *pdata = dev_get_platdata(dev); @@ -1029,7 +1029,7 @@ static int smsc95xx_free_pkt(struct udevice *dev, uchar *packet, int packet_len) int smsc95xx_write_hwaddr(struct udevice *dev) { - struct usb_device *udev = dev_get_parentdata(dev); + struct usb_device *udev = dev_get_parent_priv(dev); struct eth_pdata *pdata = dev_get_platdata(dev); struct smsc95xx_private *priv = dev_get_priv(dev); diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c index 3c3e082b27..62d20f0db9 100644 --- a/drivers/usb/eth/usb_ether.c +++ b/drivers/usb/eth/usb_ether.c @@ -19,7 +19,7 @@ int usb_ether_register(struct udevice *dev, struct ueth_data *ueth, int rxsize) { - struct usb_device *udev = dev_get_parentdata(dev); + struct usb_device *udev = dev_get_parent_priv(dev); struct usb_interface_descriptor *iface_desc; bool ep_in_found = false, ep_out_found = false; struct usb_interface *iface; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 135ef72622..c85dbcecfa 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -303,7 +303,7 @@ static void ehci_update_endpt2_dev_n_port(struct usb_device *udev, ttdev = udev; parent = udev->dev; - uparent = dev_get_parentdata(parent); + uparent = dev_get_parent_priv(parent); while (uparent->speed != USB_SPEED_HIGH) { struct udevice *dev = parent; @@ -313,9 +313,9 @@ static void ehci_update_endpt2_dev_n_port(struct usb_device *udev, return; } - ttdev = dev_get_parentdata(dev); + ttdev = dev_get_parent_priv(dev); parent = dev->parent; - uparent = dev_get_parentdata(parent); + uparent = dev_get_parent_priv(parent); } parent_devnum = uparent->devnum; #else diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index c66ebb6678..7f6a9a6d05 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -289,7 +289,7 @@ static struct usb_device *find_child_devnum(struct udevice *parent, int devnum) if (!device_active(parent)) return NULL; - udev = dev_get_parentdata(parent); + udev = dev_get_parent_priv(parent); if (udev->devnum == devnum) return udev; @@ -575,7 +575,7 @@ int usb_scan_device(struct udevice *parent, int port, udev->portnr = port; debug("Calling usb_setup_device(), portnr=%d\n", udev->portnr); parent_udev = device_get_uclass_id(parent) == UCLASS_USB_HUB ? - dev_get_parentdata(parent) : NULL; + dev_get_parent_priv(parent) : NULL; ret = usb_setup_device(udev, priv->desc_before_addr, parent_udev); debug("read_descriptor for '%s': ret=%d\n", parent->name, ret); if (ret) @@ -638,7 +638,7 @@ int usb_detect_change(void) if (!device_active(dev)) continue; - udev = dev_get_parentdata(dev); + udev = dev_get_parent_priv(dev); if (usb_get_port_status(udev, udev->portnr, &status) < 0) /* USB request failed */ @@ -694,7 +694,7 @@ struct udevice *usb_get_bus(struct udevice *dev) int usb_child_pre_probe(struct udevice *dev) { - struct usb_device *udev = dev_get_parentdata(dev); + struct usb_device *udev = dev_get_parent_priv(dev); struct usb_dev_platdata *plat = dev_get_parent_platdata(dev); int ret; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 307e1a6f61..ca598aa5e6 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1119,7 +1119,7 @@ static struct usb_device *get_usb_device(struct udevice *dev) if (device_get_uclass_id(dev) == UCLASS_USB) udev = dev_get_uclass_priv(dev); else - udev = dev_get_parentdata(dev); + udev = dev_get_parent_priv(dev); return udev; } @@ -1150,7 +1150,7 @@ static int xhci_submit_control_msg(struct udevice *dev, struct usb_device *udev, } else { while (!is_root_hub(hub->parent)) hub = hub->parent; - uhop = dev_get_parentdata(hub); + uhop = dev_get_parent_priv(hub); root_portnr = uhop->portnr; } } diff --git a/drivers/usb/musb-new/usb-compat.h b/drivers/usb/musb-new/usb-compat.h index 53fe4ff3c4..1c41e2aade 100644 --- a/drivers/usb/musb-new/usb-compat.h +++ b/drivers/usb/musb-new/usb-compat.h @@ -82,7 +82,7 @@ static inline u16 find_tt(struct usb_device *udev) */ ttdev = udev; parent = udev->dev; - uparent = dev_get_parentdata(parent); + uparent = dev_get_parent_priv(parent); while (uparent->speed != USB_SPEED_HIGH) { struct udevice *dev = parent; @@ -92,9 +92,9 @@ static inline u16 find_tt(struct usb_device *udev) return 0; } - ttdev = dev_get_parentdata(dev); + ttdev = dev_get_parent_priv(dev); parent = dev->parent; - uparent = dev_get_parentdata(parent); + uparent = dev_get_parent_priv(parent); } return (uparent->devnum << 8) | (ttdev->portnr - 1); @@ -119,12 +119,12 @@ static inline struct usb_device *usb_dev_get_parent(struct usb_device *udev) * If these 2 are not the same we are being called from * usb_scan_device() and udev itself is the parent. */ - if (dev_get_parentdata(udev->dev) != udev) + if (dev_get_parent_priv(udev->dev) != udev) return udev; /* We are being called normally, use the parent pointer */ if (device_get_uclass_id(parent) == UCLASS_USB_HUB) - return dev_get_parentdata(parent); + return dev_get_parent_priv(parent); return NULL; } diff --git a/include/dm/device.h b/include/dm/device.h index 85196124b4..f152008ae7 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -233,18 +233,18 @@ void *dev_get_parent_platdata(struct udevice *dev); void *dev_get_uclass_platdata(struct udevice *dev); /** - * dev_get_parentdata() - Get the parent data for a device + * dev_get_parent_priv() - Get the parent private data for a device * - * The parent data is data stored in the device but owned by the parent. - * For example, a USB device may have parent data which contains information - * about how to talk to the device over USB. + * The parent private data is data stored in the device but owned by the + * parent. For example, a USB device may have parent data which contains + * information about how to talk to the device over USB. * * This checks that dev is not NULL, but no other checks for now * * @dev Device to check * @return parent data, or NULL if none */ -void *dev_get_parentdata(struct udevice *dev); +void *dev_get_parent_priv(struct udevice *dev); /** * dev_get_priv() - Get the private data for a device diff --git a/include/pci.h b/include/pci.h index e24c970130..ed135a5122 100644 --- a/include/pci.h +++ b/include/pci.h @@ -797,7 +797,7 @@ struct udevice; * * Every device on a PCI bus has this per-child data. * - * It can be accessed using dev_get_parentdata(dev) if dev->parent is a + * It can be accessed using dev_get_parent_priv(dev) if dev->parent is a * PCI bus (i.e. UCLASS_PCI) * * @devfn: Encoded device and function index - see PCI_DEVFN() diff --git a/include/spi.h b/include/spi.h index 51fdfd6d73..b4d27232ec 100644 --- a/include/spi.h +++ b/include/spi.h @@ -88,7 +88,7 @@ struct dm_spi_slave_platdata { * struct spi_slave - Representation of a SPI slave * * For driver model this is the per-child data used by the SPI bus. It can - * be accessed using dev_get_parentdata() on the slave device. The SPI uclass + * be accessed using dev_get_parent_priv() on the slave device. The SPI uclass * sets uip per_child_auto_alloc_size to sizeof(struct spi_slave), and the * driver should not override it. Two platform data fields (max_hz and mode) * are copied into this structure to provide an initial value. This allows diff --git a/include/usb.h b/include/usb.h index 88ebbe6e3f..3d0facbed9 100644 --- a/include/usb.h +++ b/include/usb.h @@ -96,7 +96,7 @@ enum { * (the hubs) have this as parent data. Hubs are children of controllers or * other hubs and there is always a single root hub for each controller. * Therefore struct usb_device can always be accessed with - * dev_get_parentdata(dev), where dev is a USB device. + * dev_get_parent_priv(dev), where dev is a USB device. * * Pointers exist for obtaining both the device (could be any uclass) and * controller (UCLASS_USB) from this structure. The controller does not have diff --git a/test/dm/bus.c b/test/dm/bus.c index a215905add..3b5a23b934 100644 --- a/test/dm/bus.c +++ b/test/dm/bus.c @@ -46,7 +46,7 @@ static int testbus_child_post_bind(struct udevice *dev) static int testbus_child_pre_probe(struct udevice *dev) { - struct dm_test_parent_data *parent_data = dev_get_parentdata(dev); + struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev); parent_data->flag += FLAG_CHILD_PROBED; @@ -64,7 +64,7 @@ static int testbus_child_pre_probe_uclass(struct udevice *dev) static int testbus_child_post_remove(struct udevice *dev) { - struct dm_test_parent_data *parent_data = dev_get_parentdata(dev); + struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev); struct dm_test_state *dms = test_state; parent_data->flag += FLAG_CHILD_REMOVED; @@ -215,20 +215,20 @@ static int test_bus_parent_data(struct unit_test_state *uts) /* Check that parent data is allocated */ ut_assertok(device_find_child_by_seq(bus, 0, true, &dev)); - ut_asserteq_ptr(NULL, dev_get_parentdata(dev)); + ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); ut_assertok(device_get_child_by_seq(bus, 0, &dev)); - parent_data = dev_get_parentdata(dev); + parent_data = dev_get_parent_priv(dev); ut_assert(NULL != parent_data); /* Check that it starts at 0 and goes away when device is removed */ parent_data->sum += 5; ut_asserteq(5, parent_data->sum); device_remove(dev); - ut_asserteq_ptr(NULL, dev_get_parentdata(dev)); + ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); /* Check that we can do this twice */ ut_assertok(device_get_child_by_seq(bus, 0, &dev)); - parent_data = dev_get_parentdata(dev); + parent_data = dev_get_parent_priv(dev); ut_assert(NULL != parent_data); parent_data->sum += 5; ut_asserteq(5, parent_data->sum); @@ -239,11 +239,11 @@ static int test_bus_parent_data(struct unit_test_state *uts) uclass_foreach_dev(dev, uc) { /* Ignore these if they are not on this bus */ if (dev->parent != bus) { - ut_asserteq_ptr(NULL, dev_get_parentdata(dev)); + ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); continue; } ut_assertok(device_probe(dev)); - parent_data = dev_get_parentdata(dev); + parent_data = dev_get_parent_priv(dev); parent_data->sum = value; value += 5; @@ -255,7 +255,7 @@ static int test_bus_parent_data(struct unit_test_state *uts) /* Ignore these if they are not on this bus */ if (dev->parent != bus) continue; - parent_data = dev_get_parentdata(dev); + parent_data = dev_get_parent_priv(dev); ut_asserteq(value, parent_data->sum); value += 5; @@ -311,10 +311,10 @@ static int dm_test_bus_parent_ops(struct unit_test_state *uts) /* Ignore these if they are not on this bus */ if (dev->parent != bus) continue; - ut_asserteq_ptr(NULL, dev_get_parentdata(dev)); + ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); ut_assertok(device_probe(dev)); - parent_data = dev_get_parentdata(dev); + parent_data = dev_get_parent_priv(dev); ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); } @@ -322,10 +322,10 @@ static int dm_test_bus_parent_ops(struct unit_test_state *uts) /* Ignore these if they are not on this bus */ if (dev->parent != bus) continue; - parent_data = dev_get_parentdata(dev); + parent_data = dev_get_parent_priv(dev); ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); ut_assertok(device_remove(dev)); - ut_asserteq_ptr(NULL, dev_get_parentdata(dev)); + ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); ut_asserteq_ptr(dms->removed, dev); } test_state = NULL; -- cgit v1.2.1 From 9a79f6e6d51f35eca9fff34dd5e4689dfd2c59a8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 28 Sep 2015 23:32:02 -0600 Subject: dm: core: Adjust device.h header file order Move a few functions around so that the ordering is consistent. Signed-off-by: Simon Glass --- include/dm/device.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/include/dm/device.h b/include/dm/device.h index f152008ae7..e09f897882 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -232,6 +232,16 @@ void *dev_get_parent_platdata(struct udevice *dev); */ void *dev_get_uclass_platdata(struct udevice *dev); +/** + * dev_get_priv() - Get the private data for a device + * + * This checks that dev is not NULL, but no other checks for now + * + * @dev Device to check + * @return private data, or NULL if none + */ +void *dev_get_priv(struct udevice *dev); + /** * dev_get_parent_priv() - Get the parent private data for a device * @@ -247,14 +257,14 @@ void *dev_get_uclass_platdata(struct udevice *dev); void *dev_get_parent_priv(struct udevice *dev); /** - * dev_get_priv() - Get the private data for a device + * dev_get_uclass_priv() - Get the private uclass data for a device * * This checks that dev is not NULL, but no other checks for now * * @dev Device to check - * @return private data, or NULL if none + * @return private uclass data for this device, or NULL if none */ -void *dev_get_priv(struct udevice *dev); +void *dev_get_uclass_priv(struct udevice *dev); /** * struct dev_get_parent() - Get the parent of a device @@ -264,16 +274,6 @@ void *dev_get_priv(struct udevice *dev); */ struct udevice *dev_get_parent(struct udevice *child); -/** - * dev_get_uclass_priv() - Get the private uclass data for a device - * - * This checks that dev is not NULL, but no other checks for now - * - * @dev Device to check - * @return private uclass data for this device, or NULL if none - */ -void *dev_get_uclass_priv(struct udevice *dev); - /** * dev_get_driver_data() - get the driver data used to bind a device * -- cgit v1.2.1 From fb04c9d7b80c5f22e79788b9345d4ee551a4fc0b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 28 Sep 2015 23:32:03 -0600 Subject: dm: core: Fix device flag whitespace Line up the flag values in the code for easier readability. Signed-off-by: Simon Glass --- include/dm/device.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/dm/device.h b/include/dm/device.h index e09f897882..286a702efd 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -21,13 +21,13 @@ struct driver_info; /* Driver is active (probed). Cleared when it is removed */ -#define DM_FLAG_ACTIVATED (1 << 0) +#define DM_FLAG_ACTIVATED (1 << 0) /* DM is responsible for allocating and freeing platdata */ -#define DM_FLAG_ALLOC_PDATA (1 << 1) +#define DM_FLAG_ALLOC_PDATA (1 << 1) /* DM should init this device prior to relocation */ -#define DM_FLAG_PRE_RELOC (1 << 2) +#define DM_FLAG_PRE_RELOC (1 << 2) /* DM is responsible for allocating and freeing parent_platdata */ #define DM_FLAG_ALLOC_PARENT_PDATA (1 << 3) @@ -36,10 +36,10 @@ struct driver_info; #define DM_FLAG_ALLOC_UCLASS_PDATA (1 << 4) /* Allocate driver private data on a DMA boundary */ -#define DM_FLAG_ALLOC_PRIV_DMA (1 << 5) +#define DM_FLAG_ALLOC_PRIV_DMA (1 << 5) /* Device is bound */ -#define DM_FLAG_BOUND (1 << 6) +#define DM_FLAG_BOUND (1 << 6) /** * struct udevice - An instance of a driver -- cgit v1.2.1 From 93c7fe4a0c2d16ebd44f9740f770a776f63fbaa9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 28 Sep 2015 23:32:04 -0600 Subject: dm: core: Tidy up devres comments Adjust the devres comments to be consistent with the rest of the file, and add one for the struct udevice member. Also rename the 'p' parameter to 'ptr' to avoid single-character names. Signed-off-by: Simon Glass --- include/dm/device.h | 50 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/include/dm/device.h b/include/dm/device.h index 286a702efd..f60d153295 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -78,6 +78,10 @@ struct driver_info; * @req_seq: Requested sequence number for this device (-1 = any) * @seq: Allocated sequence number for this device (-1 = none). This is set up * when the device is probed and will be unique within the device's uclass. + * @devres_head: List of memory allocations associated with this device. + * When CONFIG_DEVRES is enabled, devm_kmalloc() and friends will + * add to this list. Memory so-allocated will be freed + * automatically when the device is removed / unbound */ struct udevice { const struct driver *driver; @@ -512,7 +516,7 @@ void *_devres_alloc(dr_release_t release, size_t size, gfp_t gfp); #endif /** - * devres_alloc - Allocate device resource data + * devres_alloc() - Allocate device resource data * @release: Release function devres will be associated with * @size: Allocation size * @gfp: Allocation flags @@ -528,7 +532,7 @@ void *_devres_alloc(dr_release_t release, size_t size, gfp_t gfp); _devres_alloc(release, size, gfp | __GFP_ZERO) /** - * devres_free - Free device resource data + * devres_free() - Free device resource data * @res: Pointer to devres data to free * * Free devres created with devres_alloc(). @@ -536,7 +540,7 @@ void *_devres_alloc(dr_release_t release, size_t size, gfp_t gfp); void devres_free(void *res); /** - * devres_add - Register device resource + * devres_add() - Register device resource * @dev: Device to add resource to * @res: Resource to register * @@ -547,7 +551,7 @@ void devres_free(void *res); void devres_add(struct udevice *dev, void *res); /** - * devres_find - Find device resource + * devres_find() - Find device resource * @dev: Device to lookup resource from * @release: Look for resources associated with this release function * @match: Match function (optional) @@ -557,14 +561,13 @@ void devres_add(struct udevice *dev, void *res); * and for which @match returns 1. If @match is NULL, it's considered * to match all. * - * RETURNS: - * Pointer to found devres, NULL if not found. + * @return pointer to found devres, NULL if not found. */ void *devres_find(struct udevice *dev, dr_release_t release, dr_match_t match, void *match_data); /** - * devres_get - Find devres, if non-existent, add one atomically + * devres_get() - Find devres, if non-existent, add one atomically * @dev: Device to lookup or add devres for * @new_res: Pointer to new initialized devres to add if not found * @match: Match function (optional) @@ -574,14 +577,13 @@ void *devres_find(struct udevice *dev, dr_release_t release, * as @new_res and for which @match return 1. If found, @new_res is * freed; otherwise, @new_res is added atomically. * - * RETURNS: - * Pointer to found or added devres. + * @return ointer to found or added devres. */ void *devres_get(struct udevice *dev, void *new_res, dr_match_t match, void *match_data); /** - * devres_remove - Find a device resource and remove it + * devres_remove() - Find a device resource and remove it * @dev: Device to find resource from * @release: Look for resources associated with this release function * @match: Match function (optional) @@ -592,14 +594,13 @@ void *devres_get(struct udevice *dev, void *new_res, * match all. If found, the resource is removed atomically and * returned. * - * RETURNS: - * Pointer to removed devres on success, NULL if not found. + * @return ointer to removed devres on success, NULL if not found. */ void *devres_remove(struct udevice *dev, dr_release_t release, dr_match_t match, void *match_data); /** - * devres_destroy - Find a device resource and destroy it + * devres_destroy() - Find a device resource and destroy it * @dev: Device to find resource from * @release: Look for resources associated with this release function * @match: Match function (optional) @@ -613,14 +614,13 @@ void *devres_remove(struct udevice *dev, dr_release_t release, * only the devres-allocated data will be freed. The caller becomes * responsible for freeing any other data. * - * RETURNS: - * 0 if devres is found and freed, -ENOENT if not found. + * @return 0 if devres is found and freed, -ENOENT if not found. */ int devres_destroy(struct udevice *dev, dr_release_t release, dr_match_t match, void *match_data); /** - * devres_release - Find a device resource and destroy it, calling release + * devres_release() - Find a device resource and destroy it, calling release * @dev: Device to find resource from * @release: Look for resources associated with this release function * @match: Match function (optional) @@ -631,15 +631,14 @@ int devres_destroy(struct udevice *dev, dr_release_t release, * match all. If found, the resource is removed atomically, the * release function called and the resource freed. * - * RETURNS: - * 0 if devres is found and freed, -ENOENT if not found. + * @return 0 if devres is found and freed, -ENOENT if not found. */ int devres_release(struct udevice *dev, dr_release_t release, dr_match_t match, void *match_data); /* managed devm_k.alloc/kfree for device drivers */ /** - * devm_kmalloc - Resource-managed kmalloc + * devm_kmalloc() - Resource-managed kmalloc * @dev: Device to allocate memory for * @size: Allocation size * @gfp: Allocation gfp flags @@ -648,8 +647,7 @@ int devres_release(struct udevice *dev, dr_release_t release, * automatically freed on driver detach. Like all other devres * resources, guaranteed alignment is unsigned long long. * - * RETURNS: - * Pointer to allocated memory on success, NULL on failure. + * @return pointer to allocated memory on success, NULL on failure. */ void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp); static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp) @@ -670,13 +668,13 @@ static inline void *devm_kcalloc(struct udevice *dev, } /** - * devm_kfree - Resource-managed kfree + * devm_kfree() - Resource-managed kfree * @dev: Device this memory belongs to - * @p: Memory to free + * @ptr: Memory to free * * Free memory allocated with devm_kmalloc(). */ -void devm_kfree(struct udevice *dev, void *p); +void devm_kfree(struct udevice *dev, void *ptr); #else /* ! CONFIG_DEVRES */ @@ -750,9 +748,9 @@ static inline void *devm_kcalloc(struct udevice *dev, return kmalloc(n * size, flags | __GFP_ZERO); } -static inline void devm_kfree(struct udevice *dev, void *p) +static inline void devm_kfree(struct udevice *dev, void *ptr) { - kfree(p); + kfree(ptr); } #endif /* ! CONFIG_DEVRES */ -- cgit v1.2.1 From 99b81a4d862cdf6bb5aea283886f17c12bac8019 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 28 Sep 2015 23:32:05 -0600 Subject: dm: core: Remove a comment about dropping per_child_auto_alloc_size This has proven useful and we no-longer intend to remove it. Drop the comment. Signed-off-by: Simon Glass --- include/dm/device.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/dm/device.h b/include/dm/device.h index f60d153295..0e40aaf80b 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -170,10 +170,6 @@ struct udevice_id { * @per_child_auto_alloc_size: Each device can hold private data owned by * its parent. If required this will be automatically allocated if this * value is non-zero. - * TODO(sjg@chromium.org): I'm considering dropping this, and just having - * device_probe_child() pass it in. So far the use case for allocating it - * is SPI, but I found that unsatisfactory. Since it is here I will leave it - * until things are clearer. * @per_child_platdata_auto_alloc_size: A bus likes to store information about * its children. If non-zero this is the size of this data, to be allocated * in the child's parent_platdata pointer. -- cgit v1.2.1 From 8d1f3a9daf65baf756fe5ada1567710b476341e6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 28 Sep 2015 23:32:06 -0600 Subject: dm: core: Tidy up comments in device.h Correct a few nits found in a recent review. Expand the comments in dev_get_driver_data() to make it clearer. Signed-off-by: Simon Glass --- include/dm/device.h | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/include/dm/device.h b/include/dm/device.h index 0e40aaf80b..28ba4ca404 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -278,13 +278,26 @@ struct udevice *dev_get_parent(struct udevice *child); * dev_get_driver_data() - get the driver data used to bind a device * * When a device is bound using a device tree node, it matches a - * particular compatible string as in struct udevice_id. This function + * particular compatible string in struct udevice_id. This function * returns the associated data value for that compatible string. This is * the 'data' field in struct udevice_id. * + * As an example, consider this structure: + * static const struct udevice_id tegra_i2c_ids[] = { + * { .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 }, + * { .compatible = "nvidia,tegra20-i2c", .data = TYPE_STD }, + * { .compatible = "nvidia,tegra20-i2c-dvc", .data = TYPE_DVC }, + * { } + * }; + * + * When driver model finds a driver for this it will store the 'data' value + * corresponding to the compatible string it matches. This function returns + * that value. This allows the driver to handle several variants of a device. + * * For USB devices, this is the driver_info field in struct usb_device_id. * * @dev: Device to check + * @return driver data (0 if none is provided) */ ulong dev_get_driver_data(struct udevice *dev); @@ -299,7 +312,7 @@ ulong dev_get_driver_data(struct udevice *dev); */ const void *dev_get_driver_ops(struct udevice *dev); -/* +/** * device_get_uclass_id() - return the uclass ID of a device * * @dev: Device to check @@ -307,7 +320,7 @@ const void *dev_get_driver_ops(struct udevice *dev); */ enum uclass_id device_get_uclass_id(struct udevice *dev); -/* +/** * dev_get_uclass_name() - return the uclass name of a device * * This checks that dev is not NULL. -- cgit v1.2.1 From 0766ad2f7fdae6d7482b8e1e3f5a49b3d9a3810b Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Tue, 6 Oct 2015 22:54:41 +0200 Subject: dm: tpm: Move tpm_tis_i2c to tpm_i2c_infineon As there is no TCG specification or recommendation for i2c TPM 1.2, move tpm_tis_i2c driver to tpm_i2c_infineon. Other tpm vendors like Atmel or STMicroelectronics may have a different transport protocol for i2c. Signed-off-by: Christophe Ricard Reviewed-by: Tom Rini Acked-by: Simon Glass --- README | 4 +- configs/nyan-big_defconfig | 2 +- configs/peach-pi_defconfig | 2 +- configs/peach-pit_defconfig | 2 +- configs/snow_defconfig | 2 +- configs/spring_defconfig | 2 +- drivers/tpm/Kconfig | 4 +- drivers/tpm/Makefile | 2 +- drivers/tpm/tpm_tis_i2c.c | 623 ----------------------------------------- drivers/tpm/tpm_tis_i2c.h | 146 ---------- drivers/tpm/tpm_tis_infineon.c | 623 +++++++++++++++++++++++++++++++++++++++++ drivers/tpm/tpm_tis_infineon.h | 146 ++++++++++ 12 files changed, 779 insertions(+), 779 deletions(-) delete mode 100644 drivers/tpm/tpm_tis_i2c.c delete mode 100644 drivers/tpm/tpm_tis_i2c.h create mode 100644 drivers/tpm/tpm_tis_infineon.c create mode 100644 drivers/tpm/tpm_tis_infineon.h diff --git a/README b/README index d18df54ec9..63bdeb9930 100644 --- a/README +++ b/README @@ -1472,8 +1472,8 @@ The following options need to be configured: CONFIG_TPM Support TPM devices. - CONFIG_TPM_TIS_I2C - Support for i2c bus TPM devices. Only one device + CONFIG_TPM_TIS_INFINEON + Support for Infineon i2c bus TPM devices. Only one device per system is supported at this time. CONFIG_TPM_TIS_I2C_BURST_LIMITATION diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig index 2dd293007b..4f31c1c220 100644 --- a/configs/nyan-big_defconfig +++ b/configs/nyan-big_defconfig @@ -20,7 +20,7 @@ CONFIG_CROS_EC_SPI=y CONFIG_SPI_FLASH=y CONFIG_TEGRA114_SPI=y CONFIG_DM_TPM=y -CONFIG_TPM_TIS_I2C=y +CONFIG_TPM_TIS_INFINEON=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_DISPLAY_PORT=y diff --git a/configs/peach-pi_defconfig b/configs/peach-pi_defconfig index dfdf61b072..6eff072a13 100644 --- a/configs/peach-pi_defconfig +++ b/configs/peach-pi_defconfig @@ -30,7 +30,7 @@ CONFIG_I2S_SAMSUNG=y CONFIG_SOUND_MAX98095=y CONFIG_SOUND_WM8994=y CONFIG_DM_TPM=y -CONFIG_TPM_TIS_I2C=y +CONFIG_TPM_TIS_INFINEON=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_VIDEO_BRIDGE=y diff --git a/configs/peach-pit_defconfig b/configs/peach-pit_defconfig index 01c4f37b09..24bc161374 100644 --- a/configs/peach-pit_defconfig +++ b/configs/peach-pit_defconfig @@ -30,7 +30,7 @@ CONFIG_I2S_SAMSUNG=y CONFIG_SOUND_MAX98095=y CONFIG_SOUND_WM8994=y CONFIG_DM_TPM=y -CONFIG_TPM_TIS_I2C=y +CONFIG_TPM_TIS_INFINEON=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_VIDEO_BRIDGE=y diff --git a/configs/snow_defconfig b/configs/snow_defconfig index c4e2f61e28..0c9ca8b5a4 100644 --- a/configs/snow_defconfig +++ b/configs/snow_defconfig @@ -39,7 +39,7 @@ CONFIG_I2S_SAMSUNG=y CONFIG_SOUND_MAX98095=y CONFIG_SOUND_WM8994=y CONFIG_DM_TPM=y -CONFIG_TPM_TIS_I2C=y +CONFIG_TPM_TIS_INFINEON=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_VIDEO_BRIDGE=y diff --git a/configs/spring_defconfig b/configs/spring_defconfig index 4acadf34ef..47bc6438da 100644 --- a/configs/spring_defconfig +++ b/configs/spring_defconfig @@ -39,7 +39,7 @@ CONFIG_I2S_SAMSUNG=y CONFIG_SOUND_MAX98095=y CONFIG_SOUND_WM8994=y CONFIG_DM_TPM=y -CONFIG_TPM_TIS_I2C=y +CONFIG_TPM_TIS_INFINEON=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_VIDEO_BRIDGE=y diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig index 6bc8fddbd1..dacb847bdc 100644 --- a/drivers/tpm/Kconfig +++ b/drivers/tpm/Kconfig @@ -31,7 +31,7 @@ config TPM_ATMEL_TWI to the device using the standard TPM Interface Specification (TIS) protocol -config TPM_TIS_I2C +config TPM_TIS_INFINEON bool "Enable support for Infineon SLB9635/45 TPMs on I2C" depends on TPM && DM_I2C help @@ -42,7 +42,7 @@ config TPM_TIS_I2C config TPM_TIS_I2C_BURST_LIMITATION bool "Enable I2C burst length limitation" - depends on TPM_TIS_I2C + depends on TPM_TIS_INFINEON help Some broken TPMs have a limitation on the number of bytes they can receive in one message. Enable this option to allow you to set this diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile index 0d328f8d9d..5748145ad5 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -6,6 +6,6 @@ obj-$(CONFIG_DM_TPM) += tpm-uclass.o obj-$(CONFIG_TPM_ATMEL_TWI) += tpm_atmel_twi.o -obj-$(CONFIG_TPM_TIS_I2C) += tpm_tis_i2c.o +obj-$(CONFIG_TPM_TIS_INFINEON) += tpm_tis_infineon.o obj-$(CONFIG_TPM_TIS_LPC) += tpm_tis_lpc.o obj-$(CONFIG_TPM_TIS_SANDBOX) += tpm_tis_sandbox.o diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c deleted file mode 100644 index 9afe46c1e9..0000000000 --- a/drivers/tpm/tpm_tis_i2c.c +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Copyright (C) 2011 Infineon Technologies - * - * Authors: - * Peter Huewe - * - * Description: - * Device driver for TCG/TCPA TPM (trusted platform module). - * Specifications at www.trustedcomputinggroup.org - * - * This device driver implements the TPM interface as defined in - * the TCG TPM Interface Spec version 1.2, revision 1.0 and the - * Infineon I2C Protocol Stack Specification v0.20. - * - * It is based on the Linux kernel driver tpm.c from Leendert van - * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall. - * - * Version: 2.1.1 - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tpm_tis_i2c.h" -#include "tpm_internal.h" - -DECLARE_GLOBAL_DATA_PTR; - -static const char * const chip_name[] = { - [SLB9635] = "slb9635tt", - [SLB9645] = "slb9645tt", - [UNKNOWN] = "unknown/fallback to slb9635", -}; - -/* - * tpm_tis_i2c_read() - read from TPM register - * @addr: register address to read from - * @buffer: provided by caller - * @len: number of bytes to read - * - * Read len bytes from TPM register and put them into - * buffer (little-endian format, i.e. first byte is put into buffer[0]). - * - * NOTE: TPM is big-endian for multi-byte values. Multi-byte - * values have to be swapped. - * - * Return -EIO on error, 0 on success. - */ -static int tpm_tis_i2c_read(struct udevice *dev, u8 addr, u8 *buffer, - size_t len) -{ - struct tpm_chip *chip = dev_get_priv(dev); - int rc; - int count; - uint32_t addrbuf = addr; - - if ((chip->chip_type == SLB9635) || (chip->chip_type == UNKNOWN)) { - /* slb9635 protocol should work in both cases */ - for (count = 0; count < MAX_COUNT; count++) { - rc = dm_i2c_write(dev, 0, (uchar *)&addrbuf, 1); - if (rc == 0) - break; /* Success, break to skip sleep */ - udelay(SLEEP_DURATION_US); - } - if (rc) - return rc; - - /* After the TPM has successfully received the register address - * it needs some time, thus we're sleeping here again, before - * retrieving the data - */ - for (count = 0; count < MAX_COUNT; count++) { - udelay(SLEEP_DURATION_US); - rc = dm_i2c_read(dev, 0, buffer, len); - if (rc == 0) - break; /* success, break to skip sleep */ - } - } else { - /* - * Use a combined read for newer chips. - * Unfortunately the smbus functions are not suitable due to - * the 32 byte limit of the smbus. - * Retries should usually not be needed, but are kept just to - * be safe on the safe side. - */ - for (count = 0; count < MAX_COUNT; count++) { - rc = dm_i2c_read(dev, addr, buffer, len); - if (rc == 0) - break; /* break here to skip sleep */ - udelay(SLEEP_DURATION_US); - } - } - - /* Take care of 'guard time' */ - udelay(SLEEP_DURATION_US); - if (rc) - return rc; - - return 0; -} - -static int tpm_tis_i2c_write_generic(struct udevice *dev, u8 addr, - const u8 *buffer, size_t len, - unsigned int sleep_time_us, u8 max_count) -{ - struct tpm_chip_priv *priv = dev_get_uclass_priv(dev); - struct tpm_chip *chip = dev_get_priv(dev); - int rc = 0; - int count; - - if (chip->chip_type == SLB9635) { - /* Prepare send buffer to include the address */ - priv->buf[0] = addr; - memcpy(&(priv->buf[1]), buffer, len); - buffer = priv->buf; - len++; - addr = 0; - } - - for (count = 0; count < max_count; count++) { - rc = dm_i2c_write(dev, addr, buffer, len); - if (rc == 0) - break; /* Success, break to skip sleep */ - udelay(sleep_time_us); - } - - /* take care of 'guard time' */ - udelay(sleep_time_us); - if (rc) - return rc; - - return 0; -} - -/* - * tpm_tis_i2c_write() - write to TPM register - * @addr: register address to write to - * @buffer: containing data to be written - * @len: number of bytes to write - * - * Write len bytes from provided buffer to TPM register (little - * endian format, i.e. buffer[0] is written as first byte). - * - * NOTE: TPM is big-endian for multi-byte values. Multi-byte - * values have to be swapped. - * - * NOTE: use this function instead of the tpm_tis_i2c_write_generic function. - * - * Return -EIO on error, 0 on success - */ -static int tpm_tis_i2c_write(struct udevice *dev, u8 addr, const u8 *buffer, - size_t len) -{ - return tpm_tis_i2c_write_generic(dev, addr, buffer, len, - SLEEP_DURATION_US, MAX_COUNT); -} - -/* - * This function is needed especially for the cleanup situation after - * sending TPM_READY - */ -static int tpm_tis_i2c_write_long(struct udevice *dev, u8 addr, u8 *buffer, - size_t len) -{ - return tpm_tis_i2c_write_generic(dev, addr, buffer, len, - SLEEP_DURATION_LONG_US, - MAX_COUNT_LONG); -} - -static int tpm_tis_i2c_check_locality(struct udevice *dev, int loc) -{ - const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID; - struct tpm_chip *chip = dev_get_priv(dev); - u8 buf; - int rc; - - rc = tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1); - if (rc < 0) - return rc; - - if ((buf & mask) == mask) { - chip->locality = loc; - return loc; - } - - return -ENOENT; -} - -static void tpm_tis_i2c_release_locality(struct udevice *dev, int loc, - int force) -{ - const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID; - u8 buf; - - if (tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1) < 0) - return; - - if (force || (buf & mask) == mask) { - buf = TPM_ACCESS_ACTIVE_LOCALITY; - tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1); - } -} - -static int tpm_tis_i2c_request_locality(struct udevice *dev, int loc) -{ - struct tpm_chip *chip = dev_get_priv(dev); - unsigned long start, stop; - u8 buf = TPM_ACCESS_REQUEST_USE; - int rc; - - rc = tpm_tis_i2c_check_locality(dev, loc); - if (rc >= 0) { - debug("%s: Already have locality\n", __func__); - return loc; /* We already have the locality */ - } else if (rc != -ENOENT) { - debug("%s: Failed to get locality: %d\n", __func__, rc); - return rc; - } - - rc = tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1); - if (rc) { - debug("%s: Failed to write to TPM: %d\n", __func__, rc); - return rc; - } - - /* Wait for burstcount */ - start = get_timer(0); - stop = chip->timeout_a; - do { - rc = tpm_tis_i2c_check_locality(dev, loc); - if (rc >= 0) { - debug("%s: Have locality\n", __func__); - return loc; - } else if (rc != -ENOENT) { - debug("%s: Failed to get locality: %d\n", __func__, rc); - return rc; - } - mdelay(TPM_TIMEOUT_MS); - } while (get_timer(start) < stop); - debug("%s: Timeout getting locality: %d\n", __func__, rc); - - return rc; -} - -static u8 tpm_tis_i2c_status(struct udevice *dev) -{ - struct tpm_chip *chip = dev_get_priv(dev); - /* NOTE: Since i2c read may fail, return 0 in this case --> time-out */ - u8 buf; - - if (tpm_tis_i2c_read(dev, TPM_STS(chip->locality), &buf, 1) < 0) - return 0; - else - return buf; -} - -static int tpm_tis_i2c_ready(struct udevice *dev) -{ - struct tpm_chip *chip = dev_get_priv(dev); - int rc; - - /* This causes the current command to be aborted */ - u8 buf = TPM_STS_COMMAND_READY; - - debug("%s\n", __func__); - rc = tpm_tis_i2c_write_long(dev, TPM_STS(chip->locality), &buf, 1); - if (rc) - debug("%s: rc=%d\n", __func__, rc); - - return rc; -} - -static ssize_t tpm_tis_i2c_get_burstcount(struct udevice *dev) -{ - struct tpm_chip *chip = dev_get_priv(dev); - unsigned long start, stop; - ssize_t burstcnt; - u8 addr, buf[3]; - - /* Wait for burstcount */ - /* XXX: Which timeout value? Spec has 2 answers (c & d) */ - start = get_timer(0); - stop = chip->timeout_d; - do { - /* Note: STS is little endian */ - addr = TPM_STS(chip->locality) + 1; - if (tpm_tis_i2c_read(dev, addr, buf, 3) < 0) - burstcnt = 0; - else - burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0]; - - if (burstcnt) - return burstcnt; - mdelay(TPM_TIMEOUT_MS); - } while (get_timer(start) < stop); - - return -EBUSY; -} - -static int tpm_tis_i2c_wait_for_stat(struct udevice *dev, u8 mask, - unsigned long timeout, int *status) -{ - unsigned long start, stop; - - /* Check current status */ - *status = tpm_tis_i2c_status(dev); - if ((*status & mask) == mask) - return 0; - - start = get_timer(0); - stop = timeout; - do { - mdelay(TPM_TIMEOUT_MS); - *status = tpm_tis_i2c_status(dev); - if ((*status & mask) == mask) - return 0; - } while (get_timer(start) < stop); - - return -ETIMEDOUT; -} - -static int tpm_tis_i2c_recv_data(struct udevice *dev, u8 *buf, size_t count) -{ - struct tpm_chip *chip = dev_get_priv(dev); - size_t size = 0; - ssize_t burstcnt; - int rc; - - while (size < count) { - burstcnt = tpm_tis_i2c_get_burstcount(dev); - - /* burstcount < 0 -> tpm is busy */ - if (burstcnt < 0) - return burstcnt; - - /* Limit received data to max left */ - if (burstcnt > (count - size)) - burstcnt = count - size; - - rc = tpm_tis_i2c_read(dev, TPM_DATA_FIFO(chip->locality), - &(buf[size]), burstcnt); - if (rc == 0) - size += burstcnt; - } - - return size; -} - -static int tpm_tis_i2c_recv(struct udevice *dev, u8 *buf, size_t count) -{ - struct tpm_chip *chip = dev_get_priv(dev); - int size = 0; - int expected, status; - int rc; - - status = tpm_tis_i2c_status(dev); - if (status == TPM_STS_COMMAND_READY) - return -EINTR; - if ((status & (TPM_STS_DATA_AVAIL | TPM_STS_VALID)) != - (TPM_STS_DATA_AVAIL | TPM_STS_VALID)) - return -EAGAIN; - - debug("...got it;\n"); - - /* Read first 10 bytes, including tag, paramsize, and result */ - size = tpm_tis_i2c_recv_data(dev, buf, TPM_HEADER_SIZE); - if (size < TPM_HEADER_SIZE) { - debug("Unable to read header\n"); - return size < 0 ? size : -EIO; - } - - expected = get_unaligned_be32(buf + TPM_RSP_SIZE_BYTE); - if ((size_t)expected > count) { - debug("Error size=%x, expected=%x, count=%x\n", size, expected, - count); - return -ENOSPC; - } - - size += tpm_tis_i2c_recv_data(dev, &buf[TPM_HEADER_SIZE], - expected - TPM_HEADER_SIZE); - if (size < expected) { - debug("Unable to read remainder of result\n"); - return -ETIMEDOUT; - } - - rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_VALID, chip->timeout_c, - &status); - if (rc) - return rc; - if (status & TPM_STS_DATA_AVAIL) { /* Retry? */ - debug("Error left over data\n"); - return -EIO; - } - - return size; -} - -static int tpm_tis_i2c_send(struct udevice *dev, const u8 *buf, size_t len) -{ - struct tpm_chip *chip = dev_get_priv(dev); - int rc, status; - size_t burstcnt; - size_t count = 0; - int retry = 0; - u8 sts = TPM_STS_GO; - - debug("%s: len=%d\n", __func__, len); - if (len > TPM_DEV_BUFSIZE) - return -E2BIG; /* Command is too long for our tpm, sorry */ - - if (tpm_tis_i2c_request_locality(dev, 0) < 0) - return -EBUSY; - - status = tpm_tis_i2c_status(dev); - if ((status & TPM_STS_COMMAND_READY) == 0) { - rc = tpm_tis_i2c_ready(dev); - if (rc) - return rc; - rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_COMMAND_READY, - chip->timeout_b, &status); - if (rc) - return rc; - } - - burstcnt = tpm_tis_i2c_get_burstcount(dev); - - /* burstcount < 0 -> tpm is busy */ - if (burstcnt < 0) - return burstcnt; - - while (count < len) { - udelay(300); - if (burstcnt > len - count) - burstcnt = len - count; - -#ifdef CONFIG_TPM_TIS_I2C_BURST_LIMITATION - if (retry && burstcnt > CONFIG_TPM_TIS_I2C_BURST_LIMITATION_LEN) - burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION_LEN; -#endif /* CONFIG_TPM_TIS_I2C_BURST_LIMITATION */ - - rc = tpm_tis_i2c_write(dev, TPM_DATA_FIFO(chip->locality), - &(buf[count]), burstcnt); - if (rc == 0) - count += burstcnt; - else { - debug("%s: error\n", __func__); - if (retry++ > 10) - return -EIO; - rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_VALID, - chip->timeout_c, - &status); - if (rc) - return rc; - - if ((status & TPM_STS_DATA_EXPECT) == 0) - return -EIO; - } - } - - /* Go and do it */ - rc = tpm_tis_i2c_write(dev, TPM_STS(chip->locality), &sts, 1); - if (rc < 0) - return rc; - debug("%s: done, rc=%d\n", __func__, rc); - - return len; -} - -static int tpm_tis_i2c_cleanup(struct udevice *dev) -{ - struct tpm_chip *chip = dev_get_priv(dev); - - tpm_tis_i2c_ready(dev); - /* - * The TPM needs some time to clean up here, - * so we sleep rather than keeping the bus busy - */ - mdelay(2); - tpm_tis_i2c_release_locality(dev, chip->locality, 0); - - return 0; -} - -static int tpm_tis_i2c_init(struct udevice *dev) -{ - struct tpm_chip *chip = dev_get_priv(dev); - u32 vendor; - u32 expected_did_vid; - int rc; - - chip->is_open = 1; - - /* Default timeouts - these could move to the device tree */ - chip->timeout_a = TIS_SHORT_TIMEOUT_MS; - chip->timeout_b = TIS_LONG_TIMEOUT_MS; - chip->timeout_c = TIS_SHORT_TIMEOUT_MS; - chip->timeout_d = TIS_SHORT_TIMEOUT_MS; - - rc = tpm_tis_i2c_request_locality(dev, 0); - if (rc < 0) - return rc; - - /* Read four bytes from DID_VID register */ - if (tpm_tis_i2c_read(dev, TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) { - tpm_tis_i2c_release_locality(dev, 0, 1); - return -EIO; - } - - if (chip->chip_type == SLB9635) { - vendor = be32_to_cpu(vendor); - expected_did_vid = TPM_TIS_I2C_DID_VID_9635; - } else { - /* device id and byte order has changed for newer i2c tpms */ - expected_did_vid = TPM_TIS_I2C_DID_VID_9645; - } - - if (chip->chip_type != UNKNOWN && vendor != expected_did_vid) { - error("Vendor id did not match! ID was %08x\n", vendor); - return -ENODEV; - } - - chip->vend_dev = vendor; - debug("1.2 TPM (chip type %s device-id 0x%X)\n", - chip_name[chip->chip_type], vendor >> 16); - - /* - * A timeout query to TPM can be placed here. - * Standard timeout values are used so far - */ - - return 0; -} - -static int tpm_tis_i2c_open(struct udevice *dev) -{ - struct tpm_chip *chip = dev_get_priv(dev); - int rc; - - debug("%s: start\n", __func__); - if (chip->is_open) - return -EBUSY; - rc = tpm_tis_i2c_init(dev); - if (rc < 0) - chip->is_open = 0; - - return rc; -} - -static int tpm_tis_i2c_close(struct udevice *dev) -{ - struct tpm_chip *chip = dev_get_priv(dev); - - if (chip->is_open) { - tpm_tis_i2c_release_locality(dev, chip->locality, 1); - chip->is_open = 0; - chip->vend_dev = 0; - } - - return 0; -} - -static int tpm_tis_get_desc(struct udevice *dev, char *buf, int size) -{ - struct tpm_chip *chip = dev_get_priv(dev); - - if (size < 50) - return -ENOSPC; - - return snprintf(buf, size, "1.2 TPM (%s, chip type %s device-id 0x%x)", - chip->is_open ? "open" : "closed", - chip_name[chip->chip_type], - chip->vend_dev >> 16); -} - -static int tpm_tis_i2c_probe(struct udevice *dev) -{ - struct tpm_chip_priv *uc_priv = dev_get_uclass_priv(dev); - struct tpm_chip *chip = dev_get_priv(dev); - - chip->chip_type = dev_get_driver_data(dev); - - /* TODO: These need to be checked and tuned */ - uc_priv->duration_ms[TPM_SHORT] = TIS_SHORT_TIMEOUT_MS; - uc_priv->duration_ms[TPM_MEDIUM] = TIS_LONG_TIMEOUT_MS; - uc_priv->duration_ms[TPM_LONG] = TIS_LONG_TIMEOUT_MS; - uc_priv->retry_time_ms = TPM_TIMEOUT_MS; - - return 0; -} - -static const struct tpm_ops tpm_tis_i2c_ops = { - .open = tpm_tis_i2c_open, - .close = tpm_tis_i2c_close, - .get_desc = tpm_tis_get_desc, - .send = tpm_tis_i2c_send, - .recv = tpm_tis_i2c_recv, - .cleanup = tpm_tis_i2c_cleanup, -}; - -static const struct udevice_id tpm_tis_i2c_ids[] = { - { .compatible = "infineon,slb9635tt", .data = SLB9635 }, - { .compatible = "infineon,slb9645tt", .data = SLB9645 }, - { } -}; - -U_BOOT_DRIVER(tpm_tis_i2c) = { - .name = "tpm_tis_i2c", - .id = UCLASS_TPM, - .of_match = tpm_tis_i2c_ids, - .ops = &tpm_tis_i2c_ops, - .probe = tpm_tis_i2c_probe, - .priv_auto_alloc_size = sizeof(struct tpm_chip), -}; diff --git a/drivers/tpm/tpm_tis_i2c.h b/drivers/tpm/tpm_tis_i2c.h deleted file mode 100644 index 3b510d101e..0000000000 --- a/drivers/tpm/tpm_tis_i2c.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2011 Infineon Technologies - * - * Authors: - * Peter Huewe - * - * Version: 2.1.1 - * - * Description: - * Device driver for TCG/TCPA TPM (trusted platform module). - * Specifications at www.trustedcomputinggroup.org - * - * It is based on the Linux kernel driver tpm.c from Leendert van - * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall. - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#ifndef _TPM_TIS_I2C_H -#define _TPM_TIS_I2C_H - -#include -#include - -enum tpm_timeout { - TPM_TIMEOUT_MS = 5, - TIS_SHORT_TIMEOUT_MS = 750, - TIS_LONG_TIMEOUT_MS = 2000, - SLEEP_DURATION_US = 60, - SLEEP_DURATION_LONG_US = 210, -}; - -/* Size of external transmit buffer (used in tpm_transmit)*/ -#define TPM_BUFSIZE 4096 - -/* Index of Count field in TPM response buffer */ -#define TPM_RSP_SIZE_BYTE 2 -#define TPM_RSP_RC_BYTE 6 - -enum i2c_chip_type { - SLB9635, - SLB9645, - UNKNOWN, -}; - -struct tpm_chip { - int is_open; - int locality; - u32 vend_dev; - unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */ - enum i2c_chip_type chip_type; -}; - -struct tpm_input_header { - __be16 tag; - __be32 length; - __be32 ordinal; -} __packed; - -struct tpm_output_header { - __be16 tag; - __be32 length; - __be32 return_code; -} __packed; - -struct timeout_t { - __be32 a; - __be32 b; - __be32 c; - __be32 d; -} __packed; - -struct duration_t { - __be32 tpm_short; - __be32 tpm_medium; - __be32 tpm_long; -} __packed; - -union cap_t { - struct timeout_t timeout; - struct duration_t duration; -}; - -struct tpm_getcap_params_in { - __be32 cap; - __be32 subcap_size; - __be32 subcap; -} __packed; - -struct tpm_getcap_params_out { - __be32 cap_size; - union cap_t cap; -} __packed; - -union tpm_cmd_header { - struct tpm_input_header in; - struct tpm_output_header out; -}; - -union tpm_cmd_params { - struct tpm_getcap_params_out getcap_out; - struct tpm_getcap_params_in getcap_in; -}; - -struct tpm_cmd_t { - union tpm_cmd_header header; - union tpm_cmd_params params; -} __packed; - -/* Max number of iterations after i2c NAK */ -#define MAX_COUNT 3 - -/* - * Max number of iterations after i2c NAK for 'long' commands - * - * We need this especially for sending TPM_READY, since the cleanup after the - * transtion to the ready state may take some time, but it is unpredictable - * how long it will take. - */ -#define MAX_COUNT_LONG 50 - -enum tis_access { - TPM_ACCESS_VALID = 0x80, - TPM_ACCESS_ACTIVE_LOCALITY = 0x20, - TPM_ACCESS_REQUEST_PENDING = 0x04, - TPM_ACCESS_REQUEST_USE = 0x02, -}; - -enum tis_status { - TPM_STS_VALID = 0x80, - TPM_STS_COMMAND_READY = 0x40, - TPM_STS_GO = 0x20, - TPM_STS_DATA_AVAIL = 0x10, - TPM_STS_DATA_EXPECT = 0x08, -}; - -/* expected value for DIDVID register */ -#define TPM_TIS_I2C_DID_VID_9635 0x000b15d1L -#define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L - -#define TPM_ACCESS(l) (0x0000 | ((l) << 4)) -#define TPM_STS(l) (0x0001 | ((l) << 4)) -#define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) -#define TPM_DID_VID(l) (0x0006 | ((l) << 4)) - -#endif diff --git a/drivers/tpm/tpm_tis_infineon.c b/drivers/tpm/tpm_tis_infineon.c new file mode 100644 index 0000000000..88eb7869bc --- /dev/null +++ b/drivers/tpm/tpm_tis_infineon.c @@ -0,0 +1,623 @@ +/* + * Copyright (C) 2011 Infineon Technologies + * + * Authors: + * Peter Huewe + * + * Description: + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + * + * This device driver implements the TPM interface as defined in + * the TCG TPM Interface Spec version 1.2, revision 1.0 and the + * Infineon I2C Protocol Stack Specification v0.20. + * + * It is based on the Linux kernel driver tpm.c from Leendert van + * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall. + * + * Version: 2.1.1 + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tpm_tis_infineon.h" +#include "tpm_internal.h" + +DECLARE_GLOBAL_DATA_PTR; + +static const char * const chip_name[] = { + [SLB9635] = "slb9635tt", + [SLB9645] = "slb9645tt", + [UNKNOWN] = "unknown/fallback to slb9635", +}; + +/* + * tpm_tis_i2c_read() - read from TPM register + * @addr: register address to read from + * @buffer: provided by caller + * @len: number of bytes to read + * + * Read len bytes from TPM register and put them into + * buffer (little-endian format, i.e. first byte is put into buffer[0]). + * + * NOTE: TPM is big-endian for multi-byte values. Multi-byte + * values have to be swapped. + * + * Return -EIO on error, 0 on success. + */ +static int tpm_tis_i2c_read(struct udevice *dev, u8 addr, u8 *buffer, + size_t len) +{ + struct tpm_chip *chip = dev_get_priv(dev); + int rc; + int count; + uint32_t addrbuf = addr; + + if ((chip->chip_type == SLB9635) || (chip->chip_type == UNKNOWN)) { + /* slb9635 protocol should work in both cases */ + for (count = 0; count < MAX_COUNT; count++) { + rc = dm_i2c_write(dev, 0, (uchar *)&addrbuf, 1); + if (rc == 0) + break; /* Success, break to skip sleep */ + udelay(SLEEP_DURATION_US); + } + if (rc) + return rc; + + /* After the TPM has successfully received the register address + * it needs some time, thus we're sleeping here again, before + * retrieving the data + */ + for (count = 0; count < MAX_COUNT; count++) { + udelay(SLEEP_DURATION_US); + rc = dm_i2c_read(dev, 0, buffer, len); + if (rc == 0) + break; /* success, break to skip sleep */ + } + } else { + /* + * Use a combined read for newer chips. + * Unfortunately the smbus functions are not suitable due to + * the 32 byte limit of the smbus. + * Retries should usually not be needed, but are kept just to + * be safe on the safe side. + */ + for (count = 0; count < MAX_COUNT; count++) { + rc = dm_i2c_read(dev, addr, buffer, len); + if (rc == 0) + break; /* break here to skip sleep */ + udelay(SLEEP_DURATION_US); + } + } + + /* Take care of 'guard time' */ + udelay(SLEEP_DURATION_US); + if (rc) + return rc; + + return 0; +} + +static int tpm_tis_i2c_write_generic(struct udevice *dev, u8 addr, + const u8 *buffer, size_t len, + unsigned int sleep_time_us, u8 max_count) +{ + struct tpm_chip_priv *priv = dev_get_uclass_priv(dev); + struct tpm_chip *chip = dev_get_priv(dev); + int rc = 0; + int count; + + if (chip->chip_type == SLB9635) { + /* Prepare send buffer to include the address */ + priv->buf[0] = addr; + memcpy(&(priv->buf[1]), buffer, len); + buffer = priv->buf; + len++; + addr = 0; + } + + for (count = 0; count < max_count; count++) { + rc = dm_i2c_write(dev, addr, buffer, len); + if (rc == 0) + break; /* Success, break to skip sleep */ + udelay(sleep_time_us); + } + + /* take care of 'guard time' */ + udelay(sleep_time_us); + if (rc) + return rc; + + return 0; +} + +/* + * tpm_tis_i2c_write() - write to TPM register + * @addr: register address to write to + * @buffer: containing data to be written + * @len: number of bytes to write + * + * Write len bytes from provided buffer to TPM register (little + * endian format, i.e. buffer[0] is written as first byte). + * + * NOTE: TPM is big-endian for multi-byte values. Multi-byte + * values have to be swapped. + * + * NOTE: use this function instead of the tpm_tis_i2c_write_generic function. + * + * Return -EIO on error, 0 on success + */ +static int tpm_tis_i2c_write(struct udevice *dev, u8 addr, const u8 *buffer, + size_t len) +{ + return tpm_tis_i2c_write_generic(dev, addr, buffer, len, + SLEEP_DURATION_US, MAX_COUNT); +} + +/* + * This function is needed especially for the cleanup situation after + * sending TPM_READY + */ +static int tpm_tis_i2c_write_long(struct udevice *dev, u8 addr, u8 *buffer, + size_t len) +{ + return tpm_tis_i2c_write_generic(dev, addr, buffer, len, + SLEEP_DURATION_LONG_US, + MAX_COUNT_LONG); +} + +static int tpm_tis_i2c_check_locality(struct udevice *dev, int loc) +{ + const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID; + struct tpm_chip *chip = dev_get_priv(dev); + u8 buf; + int rc; + + rc = tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1); + if (rc < 0) + return rc; + + if ((buf & mask) == mask) { + chip->locality = loc; + return loc; + } + + return -ENOENT; +} + +static void tpm_tis_i2c_release_locality(struct udevice *dev, int loc, + int force) +{ + const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID; + u8 buf; + + if (tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1) < 0) + return; + + if (force || (buf & mask) == mask) { + buf = TPM_ACCESS_ACTIVE_LOCALITY; + tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1); + } +} + +static int tpm_tis_i2c_request_locality(struct udevice *dev, int loc) +{ + struct tpm_chip *chip = dev_get_priv(dev); + unsigned long start, stop; + u8 buf = TPM_ACCESS_REQUEST_USE; + int rc; + + rc = tpm_tis_i2c_check_locality(dev, loc); + if (rc >= 0) { + debug("%s: Already have locality\n", __func__); + return loc; /* We already have the locality */ + } else if (rc != -ENOENT) { + debug("%s: Failed to get locality: %d\n", __func__, rc); + return rc; + } + + rc = tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1); + if (rc) { + debug("%s: Failed to write to TPM: %d\n", __func__, rc); + return rc; + } + + /* Wait for burstcount */ + start = get_timer(0); + stop = chip->timeout_a; + do { + rc = tpm_tis_i2c_check_locality(dev, loc); + if (rc >= 0) { + debug("%s: Have locality\n", __func__); + return loc; + } else if (rc != -ENOENT) { + debug("%s: Failed to get locality: %d\n", __func__, rc); + return rc; + } + mdelay(TPM_TIMEOUT_MS); + } while (get_timer(start) < stop); + debug("%s: Timeout getting locality: %d\n", __func__, rc); + + return rc; +} + +static u8 tpm_tis_i2c_status(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev); + /* NOTE: Since i2c read may fail, return 0 in this case --> time-out */ + u8 buf; + + if (tpm_tis_i2c_read(dev, TPM_STS(chip->locality), &buf, 1) < 0) + return 0; + else + return buf; +} + +static int tpm_tis_i2c_ready(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev); + int rc; + + /* This causes the current command to be aborted */ + u8 buf = TPM_STS_COMMAND_READY; + + debug("%s\n", __func__); + rc = tpm_tis_i2c_write_long(dev, TPM_STS(chip->locality), &buf, 1); + if (rc) + debug("%s: rc=%d\n", __func__, rc); + + return rc; +} + +static ssize_t tpm_tis_i2c_get_burstcount(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev); + unsigned long start, stop; + ssize_t burstcnt; + u8 addr, buf[3]; + + /* Wait for burstcount */ + /* XXX: Which timeout value? Spec has 2 answers (c & d) */ + start = get_timer(0); + stop = chip->timeout_d; + do { + /* Note: STS is little endian */ + addr = TPM_STS(chip->locality) + 1; + if (tpm_tis_i2c_read(dev, addr, buf, 3) < 0) + burstcnt = 0; + else + burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0]; + + if (burstcnt) + return burstcnt; + mdelay(TPM_TIMEOUT_MS); + } while (get_timer(start) < stop); + + return -EBUSY; +} + +static int tpm_tis_i2c_wait_for_stat(struct udevice *dev, u8 mask, + unsigned long timeout, int *status) +{ + unsigned long start, stop; + + /* Check current status */ + *status = tpm_tis_i2c_status(dev); + if ((*status & mask) == mask) + return 0; + + start = get_timer(0); + stop = timeout; + do { + mdelay(TPM_TIMEOUT_MS); + *status = tpm_tis_i2c_status(dev); + if ((*status & mask) == mask) + return 0; + } while (get_timer(start) < stop); + + return -ETIMEDOUT; +} + +static int tpm_tis_i2c_recv_data(struct udevice *dev, u8 *buf, size_t count) +{ + struct tpm_chip *chip = dev_get_priv(dev); + size_t size = 0; + ssize_t burstcnt; + int rc; + + while (size < count) { + burstcnt = tpm_tis_i2c_get_burstcount(dev); + + /* burstcount < 0 -> tpm is busy */ + if (burstcnt < 0) + return burstcnt; + + /* Limit received data to max left */ + if (burstcnt > (count - size)) + burstcnt = count - size; + + rc = tpm_tis_i2c_read(dev, TPM_DATA_FIFO(chip->locality), + &(buf[size]), burstcnt); + if (rc == 0) + size += burstcnt; + } + + return size; +} + +static int tpm_tis_i2c_recv(struct udevice *dev, u8 *buf, size_t count) +{ + struct tpm_chip *chip = dev_get_priv(dev); + int size = 0; + int expected, status; + int rc; + + status = tpm_tis_i2c_status(dev); + if (status == TPM_STS_COMMAND_READY) + return -EINTR; + if ((status & (TPM_STS_DATA_AVAIL | TPM_STS_VALID)) != + (TPM_STS_DATA_AVAIL | TPM_STS_VALID)) + return -EAGAIN; + + debug("...got it;\n"); + + /* Read first 10 bytes, including tag, paramsize, and result */ + size = tpm_tis_i2c_recv_data(dev, buf, TPM_HEADER_SIZE); + if (size < TPM_HEADER_SIZE) { + debug("Unable to read header\n"); + return size < 0 ? size : -EIO; + } + + expected = get_unaligned_be32(buf + TPM_RSP_SIZE_BYTE); + if ((size_t)expected > count) { + debug("Error size=%x, expected=%x, count=%x\n", size, expected, + count); + return -ENOSPC; + } + + size += tpm_tis_i2c_recv_data(dev, &buf[TPM_HEADER_SIZE], + expected - TPM_HEADER_SIZE); + if (size < expected) { + debug("Unable to read remainder of result\n"); + return -ETIMEDOUT; + } + + rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_VALID, chip->timeout_c, + &status); + if (rc) + return rc; + if (status & TPM_STS_DATA_AVAIL) { /* Retry? */ + debug("Error left over data\n"); + return -EIO; + } + + return size; +} + +static int tpm_tis_i2c_send(struct udevice *dev, const u8 *buf, size_t len) +{ + struct tpm_chip *chip = dev_get_priv(dev); + int rc, status; + size_t burstcnt; + size_t count = 0; + int retry = 0; + u8 sts = TPM_STS_GO; + + debug("%s: len=%d\n", __func__, len); + if (len > TPM_DEV_BUFSIZE) + return -E2BIG; /* Command is too long for our tpm, sorry */ + + if (tpm_tis_i2c_request_locality(dev, 0) < 0) + return -EBUSY; + + status = tpm_tis_i2c_status(dev); + if ((status & TPM_STS_COMMAND_READY) == 0) { + rc = tpm_tis_i2c_ready(dev); + if (rc) + return rc; + rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_COMMAND_READY, + chip->timeout_b, &status); + if (rc) + return rc; + } + + burstcnt = tpm_tis_i2c_get_burstcount(dev); + + /* burstcount < 0 -> tpm is busy */ + if (burstcnt < 0) + return burstcnt; + + while (count < len) { + udelay(300); + if (burstcnt > len - count) + burstcnt = len - count; + +#ifdef CONFIG_TPM_TIS_I2C_BURST_LIMITATION + if (retry && burstcnt > CONFIG_TPM_TIS_I2C_BURST_LIMITATION_LEN) + burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION_LEN; +#endif /* CONFIG_TPM_TIS_I2C_BURST_LIMITATION */ + + rc = tpm_tis_i2c_write(dev, TPM_DATA_FIFO(chip->locality), + &(buf[count]), burstcnt); + if (rc == 0) + count += burstcnt; + else { + debug("%s: error\n", __func__); + if (retry++ > 10) + return -EIO; + rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_VALID, + chip->timeout_c, + &status); + if (rc) + return rc; + + if ((status & TPM_STS_DATA_EXPECT) == 0) + return -EIO; + } + } + + /* Go and do it */ + rc = tpm_tis_i2c_write(dev, TPM_STS(chip->locality), &sts, 1); + if (rc < 0) + return rc; + debug("%s: done, rc=%d\n", __func__, rc); + + return len; +} + +static int tpm_tis_i2c_cleanup(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev); + + tpm_tis_i2c_ready(dev); + /* + * The TPM needs some time to clean up here, + * so we sleep rather than keeping the bus busy + */ + mdelay(2); + tpm_tis_i2c_release_locality(dev, chip->locality, 0); + + return 0; +} + +static int tpm_tis_i2c_init(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev); + u32 vendor; + u32 expected_did_vid; + int rc; + + chip->is_open = 1; + + /* Default timeouts - these could move to the device tree */ + chip->timeout_a = TIS_SHORT_TIMEOUT_MS; + chip->timeout_b = TIS_LONG_TIMEOUT_MS; + chip->timeout_c = TIS_SHORT_TIMEOUT_MS; + chip->timeout_d = TIS_SHORT_TIMEOUT_MS; + + rc = tpm_tis_i2c_request_locality(dev, 0); + if (rc < 0) + return rc; + + /* Read four bytes from DID_VID register */ + if (tpm_tis_i2c_read(dev, TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) { + tpm_tis_i2c_release_locality(dev, 0, 1); + return -EIO; + } + + if (chip->chip_type == SLB9635) { + vendor = be32_to_cpu(vendor); + expected_did_vid = TPM_TIS_I2C_DID_VID_9635; + } else { + /* device id and byte order has changed for newer i2c tpms */ + expected_did_vid = TPM_TIS_I2C_DID_VID_9645; + } + + if (chip->chip_type != UNKNOWN && vendor != expected_did_vid) { + error("Vendor id did not match! ID was %08x\n", vendor); + return -ENODEV; + } + + chip->vend_dev = vendor; + debug("1.2 TPM (chip type %s device-id 0x%X)\n", + chip_name[chip->chip_type], vendor >> 16); + + /* + * A timeout query to TPM can be placed here. + * Standard timeout values are used so far + */ + + return 0; +} + +static int tpm_tis_i2c_open(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev); + int rc; + + debug("%s: start\n", __func__); + if (chip->is_open) + return -EBUSY; + rc = tpm_tis_i2c_init(dev); + if (rc < 0) + chip->is_open = 0; + + return rc; +} + +static int tpm_tis_i2c_close(struct udevice *dev) +{ + struct tpm_chip *chip = dev_get_priv(dev); + + if (chip->is_open) { + tpm_tis_i2c_release_locality(dev, chip->locality, 1); + chip->is_open = 0; + chip->vend_dev = 0; + } + + return 0; +} + +static int tpm_tis_get_desc(struct udevice *dev, char *buf, int size) +{ + struct tpm_chip *chip = dev_get_priv(dev); + + if (size < 50) + return -ENOSPC; + + return snprintf(buf, size, "1.2 TPM (%s, chip type %s device-id 0x%x)", + chip->is_open ? "open" : "closed", + chip_name[chip->chip_type], + chip->vend_dev >> 16); +} + +static int tpm_tis_i2c_probe(struct udevice *dev) +{ + struct tpm_chip_priv *uc_priv = dev_get_uclass_priv(dev); + struct tpm_chip *chip = dev_get_priv(dev); + + chip->chip_type = dev_get_driver_data(dev); + + /* TODO: These need to be checked and tuned */ + uc_priv->duration_ms[TPM_SHORT] = TIS_SHORT_TIMEOUT_MS; + uc_priv->duration_ms[TPM_MEDIUM] = TIS_LONG_TIMEOUT_MS; + uc_priv->duration_ms[TPM_LONG] = TIS_LONG_TIMEOUT_MS; + uc_priv->retry_time_ms = TPM_TIMEOUT_MS; + + return 0; +} + +static const struct tpm_ops tpm_tis_i2c_ops = { + .open = tpm_tis_i2c_open, + .close = tpm_tis_i2c_close, + .get_desc = tpm_tis_get_desc, + .send = tpm_tis_i2c_send, + .recv = tpm_tis_i2c_recv, + .cleanup = tpm_tis_i2c_cleanup, +}; + +static const struct udevice_id tpm_tis_i2c_ids[] = { + { .compatible = "infineon,slb9635tt", .data = SLB9635 }, + { .compatible = "infineon,slb9645tt", .data = SLB9645 }, + { } +}; + +U_BOOT_DRIVER(tpm_tis_i2c) = { + .name = "tpm_tis_infineon", + .id = UCLASS_TPM, + .of_match = tpm_tis_i2c_ids, + .ops = &tpm_tis_i2c_ops, + .probe = tpm_tis_i2c_probe, + .priv_auto_alloc_size = sizeof(struct tpm_chip), +}; diff --git a/drivers/tpm/tpm_tis_infineon.h b/drivers/tpm/tpm_tis_infineon.h new file mode 100644 index 0000000000..3b510d101e --- /dev/null +++ b/drivers/tpm/tpm_tis_infineon.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2011 Infineon Technologies + * + * Authors: + * Peter Huewe + * + * Version: 2.1.1 + * + * Description: + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + * + * It is based on the Linux kernel driver tpm.c from Leendert van + * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _TPM_TIS_I2C_H +#define _TPM_TIS_I2C_H + +#include +#include + +enum tpm_timeout { + TPM_TIMEOUT_MS = 5, + TIS_SHORT_TIMEOUT_MS = 750, + TIS_LONG_TIMEOUT_MS = 2000, + SLEEP_DURATION_US = 60, + SLEEP_DURATION_LONG_US = 210, +}; + +/* Size of external transmit buffer (used in tpm_transmit)*/ +#define TPM_BUFSIZE 4096 + +/* Index of Count field in TPM response buffer */ +#define TPM_RSP_SIZE_BYTE 2 +#define TPM_RSP_RC_BYTE 6 + +enum i2c_chip_type { + SLB9635, + SLB9645, + UNKNOWN, +}; + +struct tpm_chip { + int is_open; + int locality; + u32 vend_dev; + unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */ + enum i2c_chip_type chip_type; +}; + +struct tpm_input_header { + __be16 tag; + __be32 length; + __be32 ordinal; +} __packed; + +struct tpm_output_header { + __be16 tag; + __be32 length; + __be32 return_code; +} __packed; + +struct timeout_t { + __be32 a; + __be32 b; + __be32 c; + __be32 d; +} __packed; + +struct duration_t { + __be32 tpm_short; + __be32 tpm_medium; + __be32 tpm_long; +} __packed; + +union cap_t { + struct timeout_t timeout; + struct duration_t duration; +}; + +struct tpm_getcap_params_in { + __be32 cap; + __be32 subcap_size; + __be32 subcap; +} __packed; + +struct tpm_getcap_params_out { + __be32 cap_size; + union cap_t cap; +} __packed; + +union tpm_cmd_header { + struct tpm_input_header in; + struct tpm_output_header out; +}; + +union tpm_cmd_params { + struct tpm_getcap_params_out getcap_out; + struct tpm_getcap_params_in getcap_in; +}; + +struct tpm_cmd_t { + union tpm_cmd_header header; + union tpm_cmd_params params; +} __packed; + +/* Max number of iterations after i2c NAK */ +#define MAX_COUNT 3 + +/* + * Max number of iterations after i2c NAK for 'long' commands + * + * We need this especially for sending TPM_READY, since the cleanup after the + * transtion to the ready state may take some time, but it is unpredictable + * how long it will take. + */ +#define MAX_COUNT_LONG 50 + +enum tis_access { + TPM_ACCESS_VALID = 0x80, + TPM_ACCESS_ACTIVE_LOCALITY = 0x20, + TPM_ACCESS_REQUEST_PENDING = 0x04, + TPM_ACCESS_REQUEST_USE = 0x02, +}; + +enum tis_status { + TPM_STS_VALID = 0x80, + TPM_STS_COMMAND_READY = 0x40, + TPM_STS_GO = 0x20, + TPM_STS_DATA_AVAIL = 0x10, + TPM_STS_DATA_EXPECT = 0x08, +}; + +/* expected value for DIDVID register */ +#define TPM_TIS_I2C_DID_VID_9635 0x000b15d1L +#define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L + +#define TPM_ACCESS(l) (0x0000 | ((l) << 4)) +#define TPM_STS(l) (0x0001 | ((l) << 4)) +#define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) +#define TPM_DID_VID(l) (0x0006 | ((l) << 4)) + +#endif -- cgit v1.2.1 From 302c5dba0a6eeb5846b628d3d59978dc0751def9 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Tue, 6 Oct 2015 22:54:42 +0200 Subject: dm: tpm: Add Driver Model support for tpm_atmel_twi driver tpm_atmel_twi can fit perfectly to the new UCLASS_TPM class. Signed-off-by: Christophe Ricard Reviewed-by: Tom Rini Acked-by: Simon Glass --- .../controlcenterd_36BIT_SDCARD_DEVELOP_defconfig | 2 + configs/controlcenterd_36BIT_SDCARD_defconfig | 2 + .../controlcenterd_TRAILBLAZER_DEVELOP_defconfig | 2 + configs/controlcenterd_TRAILBLAZER_defconfig | 2 + drivers/tpm/Kconfig | 2 +- drivers/tpm/tpm_atmel_twi.c | 68 ++++++++++++++++------ 6 files changed, 59 insertions(+), 19 deletions(-) diff --git a/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig b/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig index c8ab862edc..58566c1690 100644 --- a/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig +++ b/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig @@ -6,6 +6,8 @@ CONFIG_SYS_EXTRA_OPTIONS="36BIT,SDCARD,DEVELOP" # CONFIG_CMD_FLASH is not set CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y +CONFIG_DM=y +CONFIG_DM_TPM=y CONFIG_TPM_ATMEL_TWI=y CONFIG_TPM_AUTH_SESSIONS=y CONFIG_TPM=y diff --git a/configs/controlcenterd_36BIT_SDCARD_defconfig b/configs/controlcenterd_36BIT_SDCARD_defconfig index 21c0eab53d..56a4910158 100644 --- a/configs/controlcenterd_36BIT_SDCARD_defconfig +++ b/configs/controlcenterd_36BIT_SDCARD_defconfig @@ -6,6 +6,8 @@ CONFIG_SYS_EXTRA_OPTIONS="36BIT,SDCARD" # CONFIG_CMD_FLASH is not set CONFIG_CMD_TPM=y CONFIG_SPI_FLASH=y +CONFIG_DM=y +CONFIG_DM_TPM=y CONFIG_TPM_ATMEL_TWI=y CONFIG_TPM_AUTH_SESSIONS=y CONFIG_TPM=y diff --git a/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig b/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig index c3a0920d7c..cbf43efd85 100644 --- a/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig +++ b/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig @@ -7,6 +7,8 @@ CONFIG_SYS_EXTRA_OPTIONS="TRAILBLAZER,SPIFLASH,DEVELOP" # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TPM=y +CONFIG_DM=y +CONFIG_DM_TPM=y CONFIG_TPM_ATMEL_TWI=y CONFIG_TPM_AUTH_SESSIONS=y CONFIG_TPM=y diff --git a/configs/controlcenterd_TRAILBLAZER_defconfig b/configs/controlcenterd_TRAILBLAZER_defconfig index 08aae9ae2d..e897422fbd 100644 --- a/configs/controlcenterd_TRAILBLAZER_defconfig +++ b/configs/controlcenterd_TRAILBLAZER_defconfig @@ -7,6 +7,8 @@ CONFIG_SYS_EXTRA_OPTIONS="TRAILBLAZER,SPIFLASH" # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TPM=y +CONFIG_DM=y +CONFIG_DM_TPM=y CONFIG_TPM_ATMEL_TWI=y CONFIG_TPM_AUTH_SESSIONS=y CONFIG_TPM=y diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig index dacb847bdc..ff2cdbec33 100644 --- a/drivers/tpm/Kconfig +++ b/drivers/tpm/Kconfig @@ -24,7 +24,7 @@ config TPM_TIS_SANDBOX config TPM_ATMEL_TWI bool "Enable Atmel TWI TPM device driver" - depends on TPM + depends on TPM && DM_I2C help This driver supports an Atmel TPM device connected on the I2C bus. The usual tpm operations and the 'tpm' command can be used to talk diff --git a/drivers/tpm/tpm_atmel_twi.c b/drivers/tpm/tpm_atmel_twi.c index 205d7a5d97..2aa9381b11 100644 --- a/drivers/tpm/tpm_atmel_twi.c +++ b/drivers/tpm/tpm_atmel_twi.c @@ -7,51 +7,56 @@ */ #include +#include #include #include #include +#include "tpm_internal.h" + #define ATMEL_TPM_TIMEOUT_MS 5000 /* sufficient for anything but generating/exporting keys */ /* - * tis_init() - * - * Initialize the TPM device. Returns 0 on success or -1 on - * failure (in case device probing did not succeed). - */ -int tis_init(void) -{ - return 0; -} - -/* - * tis_open() + * tpm_atmel_twi_open() * * Requests access to locality 0 for the caller. After all commands have been * completed the caller is supposed to call tis_close(). * * Returns 0 on success, -1 on failure. */ -int tis_open(void) +static int tpm_atmel_twi_open(struct udevice *dev) { return 0; } /* - * tis_close() + * tpm_atmel_twi_close() * * terminate the currect session with the TPM by releasing the locked * locality. Returns 0 on success of -1 on failure (in case lock * removal did not succeed). */ -int tis_close(void) +static int tpm_atmel_twi_close(struct udevice *dev) +{ + return 0; +} + +/* + * tpm_atmel_twi_get_desc() + * + * @dev: Device to check + * @buf: Buffer to put the string + * @size: Maximum size of buffer + * @return length of string, or -ENOSPC it no space + */ +static int tpm_atmel_twi_get_desc(struct udevice *dev, char *buf, int size) { return 0; } /* - * tis_sendrecv() + * tpm_atmel_twi_xfer() * * Send the requested data to the TPM and then try to get its response * @@ -63,8 +68,9 @@ int tis_close(void) * Returns 0 on success (and places the number of response bytes at recv_len) * or -1 on failure. */ -int tis_sendrecv(const uint8_t *sendbuf, size_t send_size, uint8_t *recvbuf, - size_t *recv_len) +static int tpm_atmel_twi_xfer(struct udevice *dev, + const uint8_t *sendbuf, size_t send_size, + uint8_t *recvbuf, size_t *recv_len) { int res; unsigned long start; @@ -83,6 +89,7 @@ int tis_sendrecv(const uint8_t *sendbuf, size_t send_size, uint8_t *recvbuf, start = get_timer(0); while ((res = i2c_read(0x29, 0, 0, recvbuf, 10))) { + /* TODO Use TIS_TIMEOUT from tpm_tis_infineon.h */ if (get_timer(start) > ATMEL_TPM_TIMEOUT_MS) { puts("tpm timed out\n"); return -1; @@ -110,3 +117,28 @@ int tis_sendrecv(const uint8_t *sendbuf, size_t send_size, uint8_t *recvbuf, return res; } + +static int tpm_atmel_twi_probe(struct udevice *dev) +{ + return 0; +} + +static const struct udevice_id tpm_atmel_twi_ids[] = { + { .compatible = "atmel,at97sc3204t"}, + { } +}; + +static const struct tpm_ops tpm_atmel_twi_ops = { + .open = tpm_atmel_twi_open, + .close = tpm_atmel_twi_close, + .xfer = tpm_atmel_twi_xfer, + .get_desc = tpm_atmel_twi_get_desc, +}; + +U_BOOT_DRIVER(tpm_atmel_twi) = { + .name = "tpm_atmel_twi", + .id = UCLASS_TPM, + .of_match = tpm_atmel_twi_ids, + .ops = &tpm_atmel_twi_ops, + .probe = tpm_atmel_twi_probe, +}; -- cgit v1.2.1 From c2b0f600a1707450ef985e28363893987f36fd8a Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Tue, 6 Oct 2015 22:54:43 +0200 Subject: dm: tpm: Remove every compilation switch for TPM driver model As every TPM drivers support UCLASS_TPM, we can only rely on DM_TPM functions. This simplify a bit the code. Signed-off-by: Christophe Ricard Reviewed-by: Tom Rini Acked-by: Simon Glass --- common/cmd_tpm.c | 13 +-------- drivers/tpm/tpm_tis_infineon.c | 1 - drivers/tpm/tpm_tis_lpc.c | 1 - include/tis.h | 60 ------------------------------------------ include/tpm.h | 6 ----- lib/tpm.c | 20 +++----------- 6 files changed, 4 insertions(+), 97 deletions(-) delete mode 100644 include/tis.h diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c index 97501cc3d1..add6bfb416 100644 --- a/common/cmd_tpm.c +++ b/common/cmd_tpm.c @@ -443,7 +443,6 @@ TPM_COMMAND_NO_ARG(tpm_force_clear) TPM_COMMAND_NO_ARG(tpm_physical_enable) TPM_COMMAND_NO_ARG(tpm_physical_disable) -#ifdef CONFIG_DM_TPM static int get_tpm(struct udevice **devp) { int rc; @@ -476,11 +475,11 @@ static int do_tpm_info(cmd_tbl_t *cmdtp, int flag, int argc, return 0; } -#endif static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { + struct udevice *dev; void *command; uint8_t response[1024]; size_t count, response_length = sizeof(response); @@ -492,17 +491,11 @@ static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, return CMD_RET_FAILURE; } -#ifdef CONFIG_DM_TPM - struct udevice *dev; - rc = get_tpm(&dev); if (rc) return rc; rc = tpm_xfer(dev, command, count, response, &response_length); -#else - rc = tis_sendrecv(command, count, response, &response_length); -#endif free(command); if (!rc) { puts("tpm response:\n"); @@ -657,9 +650,7 @@ TPM_COMMAND_NO_ARG(tpm_end_oiap) U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "") static cmd_tbl_t tpm_commands[] = { -#ifdef CONFIG_DM_TPM U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""), -#endif U_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, "", ""), U_BOOT_CMD_MKENT(startup, 0, 1, @@ -730,9 +721,7 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm, "cmd args...\n" " - Issue TPM command with arguments .\n" "Admin Startup and State Commands:\n" -#ifdef CONFIG_DM_TPM " info - Show information about the TPM\n" -#endif " init\n" " - Put TPM into a state where it waits for 'startup' command.\n" " startup mode\n" diff --git a/drivers/tpm/tpm_tis_infineon.c b/drivers/tpm/tpm_tis_infineon.c index 88eb7869bc..f57c32837b 100644 --- a/drivers/tpm/tpm_tis_infineon.c +++ b/drivers/tpm/tpm_tis_infineon.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/tpm/tpm_tis_lpc.c b/drivers/tpm/tpm_tis_lpc.c index b41c3cec37..257d035d72 100644 --- a/drivers/tpm/tpm_tis_lpc.c +++ b/drivers/tpm/tpm_tis_lpc.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff --git a/include/tis.h b/include/tis.h deleted file mode 100644 index 1985d9e60e..0000000000 --- a/include/tis.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __TIS_H -#define __TIS_H - -#ifndef CONFIG_DM_TPM - -#include - -/* Low-level interface to access TPM */ - -/* - * tis_init() - * - * Initialize the TPM device. Returns 0 on success or -1 on - * failure (in case device probing did not succeed). - */ -int tis_init(void); - -/* - * tis_open() - * - * Requests access to locality 0 for the caller. After all commands have been - * completed the caller is supposed to call tis_close(). - * - * Returns 0 on success, -1 on failure. - */ -int tis_open(void); - -/* - * tis_close() - * - * terminate the currect session with the TPM by releasing the locked - * locality. Returns 0 on success of -1 on failure (in case lock - * removal did not succeed). - */ -int tis_close(void); - -/* - * tis_sendrecv() - * - * Send the requested data to the TPM and then try to get its response - * - * @sendbuf - buffer of the data to send - * @send_size size of the data to send - * @recvbuf - memory to save the response to - * @recv_len - pointer to the size of the response buffer - * - * Returns 0 on success (and places the number of response bytes at recv_len) - * or -1 on failure. - */ -int tis_sendrecv(const uint8_t *sendbuf, size_t send_size, uint8_t *recvbuf, - size_t *recv_len); -#endif - -#endif /* __TIS_H */ diff --git a/include/tpm.h b/include/tpm.h index 086b672718..9a6585d3d4 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -8,8 +8,6 @@ #ifndef __TPM_H #define __TPM_H -#include - /* * Here is a partial implementation of TPM commands. Please consult TCG Main * Specification for definitions of TPM commands. @@ -196,8 +194,6 @@ struct tpm_permanent_flags { u8 disable_full_da_logic_info; } __packed; -#ifdef CONFIG_DM_TPM - /* Max buffer size supported by our tpm */ #define TPM_DEV_BUFSIZE 1260 @@ -375,8 +371,6 @@ int tpm_get_desc(struct udevice *dev, char *buf, int size); int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size, uint8_t *recvbuf, size_t *recv_size); -#endif /* CONFIG_DM_TPM */ - /** * Initialize TPM device. It must be called before any TPM commands. * diff --git a/lib/tpm.c b/lib/tpm.c index 5d5f707e37..8a62216274 100644 --- a/lib/tpm.c +++ b/lib/tpm.c @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -230,6 +229,8 @@ static uint32_t tpm_return_code(const void *response) static uint32_t tpm_sendrecv_command(const void *command, void *response, size_t *size_ptr) { + struct udevice *dev; + int ret; uint8_t response_buffer[COMMAND_BUFFER_SIZE]; size_t response_length; uint32_t err; @@ -240,19 +241,13 @@ static uint32_t tpm_sendrecv_command(const void *command, response = response_buffer; response_length = sizeof(response_buffer); } -#ifdef CONFIG_DM_TPM - struct udevice *dev; - int ret; ret = uclass_first_device(UCLASS_TPM, &dev); if (ret) return ret; err = tpm_xfer(dev, command, tpm_command_size(command), response, &response_length); -#else - err = tis_sendrecv(command, tpm_command_size(command), - response, &response_length); -#endif + if (err < 0) return TPM_LIB_ERROR; if (size_ptr) @@ -264,21 +259,12 @@ static uint32_t tpm_sendrecv_command(const void *command, int tpm_init(void) { int err; - -#ifdef CONFIG_DM_TPM struct udevice *dev; err = uclass_first_device(UCLASS_TPM, &dev); if (err) return err; return tpm_open(dev); -#else - err = tis_init(); - if (err) - return err; - - return tis_open(); -#endif } uint32_t tpm_startup(enum tpm_startup_type mode) -- cgit v1.2.1 From 3e7d940bb695fd8ba450dde7742a58a224efaee4 Mon Sep 17 00:00:00 2001 From: Christophe Ricard Date: Tue, 6 Oct 2015 22:54:44 +0200 Subject: dm: tpm: Every TPM drivers should depends on DM_TPM Every TPM drivers should now depends on DM_TPM and not only TPM. Signed-off-by: Christophe Ricard Reviewed-by: Tom Rini Acked-by: Simon Glass --- drivers/tpm/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig index ff2cdbec33..3ab652cbcd 100644 --- a/drivers/tpm/Kconfig +++ b/drivers/tpm/Kconfig @@ -24,7 +24,7 @@ config TPM_TIS_SANDBOX config TPM_ATMEL_TWI bool "Enable Atmel TWI TPM device driver" - depends on TPM && DM_I2C + depends on DM_TPM && DM_I2C help This driver supports an Atmel TPM device connected on the I2C bus. The usual tpm operations and the 'tpm' command can be used to talk @@ -33,7 +33,7 @@ config TPM_ATMEL_TWI config TPM_TIS_INFINEON bool "Enable support for Infineon SLB9635/45 TPMs on I2C" - depends on TPM && DM_I2C + depends on DM_TPM && DM_I2C help This driver supports Infineon TPM devices connected on the I2C bus. The usual tpm operations and the 'tpm' command can be used to talk @@ -57,7 +57,7 @@ config TPM_TIS_I2C_BURST_LIMITATION_LEN config TPM_TIS_LPC bool "Enable support for Infineon SLB9635/45 TPMs on LPC" - depends on TPM && X86 + depends on DM_TPM && X86 help This driver supports Infineon TPM devices connected on the I2C bus. The usual tpm operations and the 'tpm' command can be used to talk -- cgit v1.2.1 From 2419cd16a1357a6d0f394b4631ea07b4f9e85ac7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 3 Oct 2015 06:39:36 -0600 Subject: dm: tpm: Drop CONFIG_DM_TPM Now that all TPM drivers use driver model, we can drop the special driver model CONFIG option. Signed-off-by: Simon Glass Acked-by: Christophe Ricard --- drivers/tpm/Kconfig | 15 +++------------ drivers/tpm/Makefile | 2 +- lib/Kconfig | 1 + 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig index 3ab652cbcd..31b35f75c9 100644 --- a/drivers/tpm/Kconfig +++ b/drivers/tpm/Kconfig @@ -4,15 +4,6 @@ menu "TPM support" -config DM_TPM - bool "Enable driver model for Trusted Platform Module drivers" - depends on DM && TPM - help - Enable driver model for TPMs. The TIS interface (tis_open(), - tis_sendrecv(), etc.) is then implemented by the TPM uclass. Note - that even with driver model only a single TPM is currently - supported, since the tpm library assumes this. - config TPM_TIS_SANDBOX bool "Enable sandbox TPM driver" depends on SANDBOX @@ -24,7 +15,7 @@ config TPM_TIS_SANDBOX config TPM_ATMEL_TWI bool "Enable Atmel TWI TPM device driver" - depends on DM_TPM && DM_I2C + depends on TPM && DM_I2C help This driver supports an Atmel TPM device connected on the I2C bus. The usual tpm operations and the 'tpm' command can be used to talk @@ -33,7 +24,7 @@ config TPM_ATMEL_TWI config TPM_TIS_INFINEON bool "Enable support for Infineon SLB9635/45 TPMs on I2C" - depends on DM_TPM && DM_I2C + depends on TPM && DM_I2C help This driver supports Infineon TPM devices connected on the I2C bus. The usual tpm operations and the 'tpm' command can be used to talk @@ -57,7 +48,7 @@ config TPM_TIS_I2C_BURST_LIMITATION_LEN config TPM_TIS_LPC bool "Enable support for Infineon SLB9635/45 TPMs on LPC" - depends on DM_TPM && X86 + depends on TPM && X86 help This driver supports Infineon TPM devices connected on the I2C bus. The usual tpm operations and the 'tpm' command can be used to talk diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile index 5748145ad5..1d49e952ae 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -3,7 +3,7 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-$(CONFIG_DM_TPM) += tpm-uclass.o +obj-$(CONFIG_TPM) += tpm-uclass.o obj-$(CONFIG_TPM_ATMEL_TWI) += tpm_atmel_twi.o obj-$(CONFIG_TPM_TIS_INFINEON) += tpm_tis_infineon.o diff --git a/lib/Kconfig b/lib/Kconfig index a8f8460d1d..30e84ed315 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -56,6 +56,7 @@ source lib/rsa/Kconfig config TPM bool "Trusted Platform Module (TPM) Support" + depends on DM help This enables support for TPMs which can be used to provide security features for your board. The TPM can be connected via LPC or I2C -- cgit v1.2.1 From 545dfd101400637219b7024ce0fc02728663380e Mon Sep 17 00:00:00 2001 From: Thomas Chou Date: Fri, 16 Oct 2015 08:44:51 +0800 Subject: env: export fdt_blob to the environment variable Export fdt_blob to the environment variable. So that we may use it to boot Linux. Signed-off-by: Thomas Chou Acked-by: Simon Glass --- common/board_r.c | 3 +++ doc/README.fdt-control | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/common/board_r.c b/common/board_r.c index f8c1baa949..0a4dfe4972 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -446,6 +446,9 @@ static int initr_env(void) env_relocate(); else set_default_env(NULL); +#ifdef CONFIG_OF_CONTROL + setenv_addr("fdtcontroladdr", gd->fdt_blob); +#endif /* Initialize from environment */ load_addr = getenv_ulong("loadaddr", 16, load_addr); diff --git a/doc/README.fdt-control b/doc/README.fdt-control index e6d5ed0bb6..29fd56a815 100644 --- a/doc/README.fdt-control +++ b/doc/README.fdt-control @@ -156,7 +156,10 @@ address of the fdt binary blob, and will override either of the options. Be aware that this environment variable is checked prior to relocation, when only the compiled-in environment is available. Therefore it is not possible to define this variable in the saved SPI/NAND flash -environment, for example (it will be ignored). +environment, for example (it will be ignored). After relocation, this +variable will be set to the address of the newly relocated fdt blob. +It is read-only and cannot be changed. It can optionally be used to +control the boot process of Linux with bootm/bootz commands. To use this, put something like this in your board header file: -- cgit v1.2.1 From 4ea5243a3a2fbc59bbcdd401d75f1744bcd6280f Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 2 Oct 2015 17:44:06 -0600 Subject: fdt: fix fdtdec_get_pci_addr() for CONFIG_PHYS_64BIT PCI addresses are always represented as 3 cells in DT. (one cell for bus and device, and two cells for a 64-bit addres). This does not vary based on either the physical address size of the CPU, nor any #address-cells property in DT (or more precisely, #address-cells must be set to 3 in any PCIe controller's node). Fix fdtdec_get_pci_addr() to use conversion functions that operate on (fixed) cell-sized data rather than (varying) physical-address-sized data, so that the function works on 64-bit systems. Signed-off-by: Stephen Warren Acked-by: Simon Glass Reviewed-by: Thierry Reding --- lib/fdtdec.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 1a86369934..9db033ae73 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -219,13 +219,13 @@ int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type, for (i = 0; i < num; i++) { debug("pci address #%d: %08lx %08lx %08lx\n", i, - (ulong)fdt_addr_to_cpu(cell[0]), - (ulong)fdt_addr_to_cpu(cell[1]), - (ulong)fdt_addr_to_cpu(cell[2])); - if ((fdt_addr_to_cpu(*cell) & type) == type) { - addr->phys_hi = fdt_addr_to_cpu(cell[0]); - addr->phys_mid = fdt_addr_to_cpu(cell[1]); - addr->phys_lo = fdt_addr_to_cpu(cell[2]); + (ulong)fdt32_to_cpu(cell[0]), + (ulong)fdt32_to_cpu(cell[1]), + (ulong)fdt32_to_cpu(cell[2])); + if ((fdt32_to_cpu(*cell) & type) == type) { + addr->phys_hi = fdt32_to_cpu(cell[0]); + addr->phys_mid = fdt32_to_cpu(cell[1]); + addr->phys_lo = fdt32_to_cpu(cell[1]); break; } else { cell += (FDT_PCI_ADDR_CELLS + -- cgit v1.2.1