drivers:staging:nvshm: Add support for BBC serial number
Alexandre Berdery [Thu, 14 Feb 2013 10:44:18 +0000 (11:44 +0100)]
If compatible SHM config version, BBC serial number (PCID) is
populated in tegra_bb sysfs

Bug 1226888

Change-Id: Ic2ee91547b0454ecbefac5aee580f247b1e081d4
Signed-off-by: Alexandre Berdery <aberdery@nvidia.com>
Reviewed-on: http://git-master/r/200765
(cherry picked from commit 35f75aa0191e05d6c8d3b9dac8316e93bb877d8e)
Reviewed-on: http://git-master/r/204573
Reviewed-by: Automatic_Commit_Validation_User
Tested-by: Martin Chabot <mchabot@nvidia.com>
Reviewed-by: Neil Patel <neilp@nvidia.com>
Reviewed-by: Thomas Cherry <tcherry@nvidia.com>

arch/arm/mach-tegra/include/mach/tegra_bb.h
arch/arm/mach-tegra/tegra_bb.c
drivers/staging/nvshm/nvshm_ipc.c
drivers/staging/nvshm/nvshm_types.h
include/linux/platform_data/nvshm.h

index c995283..7d51040 100644 (file)
@@ -61,4 +61,12 @@ void tegra_bb_clear_ipc(struct platform_device *dev);
  */
 int tegra_bb_check_ipc(struct platform_device *dev);
 
+/*
+ * tegra_bb_set_ipc_serial: store SHM serial number for sysfs access
+ * @param struct tegra_bb device pointer
+ * @param serial pointer to SHM serial
+ * @return none
+ */
+void tegra_bb_set_ipc_serial(struct platform_device *pdev, char *serial);
+
 #endif
index 268d2b6..019f1b8 100644 (file)
@@ -98,6 +98,7 @@ struct tegra_bb {
        unsigned long priv_size;
        unsigned long ipc_size;
        unsigned long ipc_irq;
+       char ipc_serial[NVSHM_SERIAL_BYTE_SIZE];
        unsigned int irq;
        struct regulator *vdd_buck4;
        struct regulator *vdd_ldo8;
@@ -576,6 +577,92 @@ static ssize_t show_tegra_bb_state(struct device *dev,
 
 static DEVICE_ATTR(state, S_IRUSR | S_IRGRP, show_tegra_bb_state, NULL);
 
+static ssize_t show_tegra_bb_serial(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct tegra_bb *bb;
+       struct platform_device *pdev = container_of(dev,
+                                                   struct platform_device,
+                                                   dev);
+       struct tegra_bb_platform_data *pdata;
+       int idx, ret, total_len = 0;
+
+       if (!pdev) {
+               dev_err(dev, "%s platform device is NULL!\n", __func__);
+               return 0;
+       }
+
+       pdata = pdev->dev.platform_data;
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "%s platform data not found!\n", __func__);
+               return 0;
+       }
+
+       bb = (struct tegra_bb *)pdata->bb_handle;
+
+       if (!bb) {
+               dev_err(&pdev->dev, "%s tegra_bb not found!\n", __func__);
+               return 0;
+       }
+
+       for (idx = 0; NVSHM_SERIAL_BYTE_SIZE > idx; ++idx) {
+               ret = sprintf(buf+2*idx, "%02X", bb->ipc_serial[idx]);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "%s sprintf shm serial failure!\n",
+                                       __func__);
+                       return 0;
+               }
+               total_len += ret;
+       }
+
+       buf[2*NVSHM_SERIAL_BYTE_SIZE] = '\n';
+       buf[2*NVSHM_SERIAL_BYTE_SIZE+1] = '\0';
+       total_len += 2;
+
+       return total_len;
+}
+
+static DEVICE_ATTR(serial, S_IRUSR | S_IRGRP, show_tegra_bb_serial, NULL);
+
+void tegra_bb_set_ipc_serial(struct platform_device *pdev, char *serial)
+{
+       struct tegra_bb *bb;
+       struct tegra_bb_platform_data *pdata;
+
+       if (!pdev) {
+               pr_err("%s platform device is NULL!\n", __func__);
+               return;
+       }
+
+       pdata = pdev->dev.platform_data;
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "%s platform dev not found!\n", __func__);
+               return;
+       }
+
+       bb = (struct tegra_bb *)pdata->bb_handle;
+
+       if (!bb) {
+               dev_err(&pdev->dev, "%s tegra_bb not found!\n", __func__);
+               return;
+       }
+
+       if (serial == NULL) {
+               /* Remove sysfs entry */
+               device_remove_file(&pdev->dev, &dev_attr_serial);
+               return;
+       }
+
+       /* Create sysfs entry */
+       device_create_file(&pdev->dev, &dev_attr_serial);
+
+       /* Locally store serail number for future sysfs access */
+       memcpy(bb->ipc_serial, serial, sizeof(bb->ipc_serial));
+}
+EXPORT_SYMBOL_GPL(tegra_bb_set_ipc_serial);
+
 #ifndef CONFIG_TEGRA_BASEBAND_SIMU
 static irqreturn_t tegra_bb_isr_handler(int irq, void *data)
 {
index a591674..8e500f2 100644 (file)
@@ -39,9 +39,10 @@ static int ipc_readconfig(struct nvshm_handle *handle)
        conf = (struct nvshm_config *)(handle->mb_base_virt
                                       + NVSHM_CONFIG_OFFSET);
        if (conf->version != NVSHM_CONFIG_VERSION) {
-               pr_err("%s: wrong config version 0x%x\n",
-                      __func__, (unsigned int)conf->version);
-               return -1;
+               pr_warn("%s: new/old config version 0x%x vs. 0x%x\n",
+                               __func__,
+                               (unsigned int)conf->version,
+                               NVSHM_CONFIG_VERSION);
        }
        if (handle->ipc_size != conf->shmem_size) {
                pr_warn("%s shmem mapped/reported not matching: 0x%x/0x%x\n",
@@ -96,6 +97,12 @@ static int ipc_readconfig(struct nvshm_handle *handle)
                                __func__, chan, handle->chan[chan].map.name);
                }
        }
+
+       if (conf->version >= NVSHM_CONFIG_SERIAL_VERSION) {
+               /* Serial number (e.g BBC PCID) */
+               tegra_bb_set_ipc_serial(handle->tegra_bb, conf->serial);
+       }
+
        handle->conf = conf;
        handle->configured = 1;
        return 0;
@@ -174,6 +181,10 @@ static int cleanup_interfaces(struct nvshm_handle *handle)
                pr_debug("%s cleanup %d net channels\n", __func__, nnet);
                nvshm_net_cleanup();
        }
+
+       /* Remove serial sysfs entry */
+       tegra_bb_set_ipc_serial(handle->tegra_bb, NULL);
+
        return 0;
 }
 
index 55dcf19..a648a1b 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef _NVSHM_TYPES_H
 #define _NVSHM_TYPES_H
 
+#include <linux/platform_data/nvshm.h> /* NVSHM_SERIAL_BYTE_SIZE */
+
 /* NVSHM common types */
 
 /* Shared memory fixed offsets */
 #define NVSHM_IPC_RETCODE (0x4)           /* IPC mailbox return code offset */
 #define NVSHM_IPC_SIZE (4096)             /* IPC mailbox region size */
 #define NVSHM_CONFIG_OFFSET (8)           /* shared memory config offset */
-#define NVSHM_MAX_CHANNELS (32)           /* Maximum number of channels */
+#define NVSHM_MAX_CHANNELS (12)           /* Maximum number of channels */
 #define NVSHM_CHAN_NAME_SIZE (27)         /* max channel name size in chars */
-#define NVSHM_CONFIG_VERSION (0x00010001) /* Current configuration version */
+
+/* Versions: */
+/* Original version */
+#define NVSHM_CONFIG_ORIGINAL_VERSION (0x00010001)
+/** Serial version: support for SHM serial version in SHM
+ *  config: SHM serial version is PCID */
+#define NVSHM_CONFIG_SERIAL_VERSION (0x00010002)
+/** Current configuration version (major/minor) */
+#define NVSHM_CONFIG_VERSION NVSHM_CONFIG_SERIAL_VERSION
+
 
 #define NVSHM_AP_POOL_ID (128) /* IOPOOL ID - use 128-255 for AP */
 
@@ -98,6 +109,7 @@ struct nvshm_config {
        int queue_ap_offset;
        int queue_bb_offset;
        struct nvshm_chan_map chan_map[NVSHM_MAX_CHANNELS];
+       char serial[NVSHM_SERIAL_BYTE_SIZE];
 };
 
 /*
index dae8288..faaa4f7 100644 (file)
 #ifndef __PLATFORM_DATA_NVSHM_H
 #define __PLATFORM_DATA_NVSHM_H
 
+#include <linux/types.h>
+
+/* NVSHM serial number size in bytes */
+#define NVSHM_SERIAL_BYTE_SIZE 20
+
 struct nvshm_platform_data {
        void *ipc_base_virt;
        size_t ipc_size;