0 = don't trust, the image may be different (default)
                1 = trust that the image will not change.
 Users:         https://github.com/ibm-capi/libcxl
+
+What:           /sys/class/cxl/<card>/psl_timebase_synced
+Date:           March 2016
+Contact:        linuxppc-dev@lists.ozlabs.org
+Description:    read only
+                Returns 1 if the psl timebase register is synchronized
+                with the core timebase register, 0 otherwise.
+Users:          https://github.com/ibm-capi/libcxl
 
        bool perst_loads_image;
        bool perst_select_user;
        bool perst_same_image;
+       bool psl_timebase_synced;
 };
 
 int cxl_pci_alloc_one_irq(struct cxl *adapter);
 
        adapter->dev.release = release_adapter;
        dev_set_drvdata(&pdev->dev, adapter);
 
+       /*
+        * Hypervisor controls PSL timebase initialization (p1 register).
+        * On FW840, PSL is initialized.
+        */
+       adapter->psl_timebase_synced = true;
+
        if ((rc = cxl_of_read_adapter_handle(adapter, np)))
                goto err1;
 
 
 #define TBSYNC_CNT(n) (((u64)n & 0x7) << (63-6))
 #define _2048_250MHZ_CYCLES 1
 
-static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev)
+static void cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev)
 {
        u64 psl_tb;
        int delta;
        unsigned int retry = 0;
        struct device_node *np;
 
+       adapter->psl_timebase_synced = false;
+
        if (!(np = pnv_pci_get_phb_node(dev)))
-               return -ENODEV;
+               return;
 
        /* Do not fail when CAPP timebase sync is not supported by OPAL */
        of_node_get(np);
        if (! of_get_property(np, "ibm,capp-timebase-sync", NULL)) {
                of_node_put(np);
-               pr_err("PSL: Timebase sync: OPAL support missing\n");
-               return 0;
+               dev_info(&dev->dev, "PSL timebase inactive: OPAL support missing\n");
+               return;
        }
        of_node_put(np);
 
        do {
                msleep(1);
                if (retry++ > 5) {
-                       pr_err("PSL: Timebase sync: giving up!\n");
-                       return -EIO;
+                       dev_info(&dev->dev, "PSL timebase can't synchronize\n");
+                       return;
                }
                psl_tb = cxl_p1_read(adapter, CXL_PSL_Timebase);
                delta = mftb() - psl_tb;
                        delta = -delta;
        } while (tb_to_ns(delta) > 16000);
 
-       return 0;
+       adapter->psl_timebase_synced = true;
+       return;
 }
 
 static int init_implementation_afu_regs(struct cxl_afu *afu)
        if ((rc = pnv_phb_to_cxl_mode(dev, OPAL_PHB_CAPI_MODE_SNOOP_ON)))
                goto err;
 
-       if ((rc = cxl_setup_psl_timebase(adapter, dev)))
-               goto err;
+       /* Ignore error, adapter init is not dependant on timebase sync */
+       cxl_setup_psl_timebase(adapter, dev);
 
        if ((rc = cxl_native_register_psl_err_irq(adapter)))
                goto err;
 
        return scnprintf(buf, PAGE_SIZE, "factory\n");
 }
 
+static ssize_t psl_timebase_synced_show(struct device *device,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct cxl *adapter = to_cxl_adapter(device);
+
+       return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->psl_timebase_synced);
+}
+
 static ssize_t reset_adapter_store(struct device *device,
                                   struct device_attribute *attr,
                                   const char *buf, size_t count)
        __ATTR_RO(psl_revision),
        __ATTR_RO(base_image),
        __ATTR_RO(image_loaded),
+       __ATTR_RO(psl_timebase_synced),
        __ATTR_RW(load_image_on_perst),
        __ATTR_RW(perst_reloads_same_image),
        __ATTR(reset, S_IWUSR, NULL, reset_adapter_store),