build: create dummy Makefile
[dpdk.git] / drivers / raw / ifpga / base / opae_intel_max10.c
index 305baba..8e23ca1 100644 (file)
@@ -5,28 +5,52 @@
 #include "opae_intel_max10.h"
 #include <libfdt.h>
 
-static struct intel_max10_device *g_max10;
-
-int max10_reg_read(unsigned int reg, unsigned int *val)
+int max10_reg_read(struct intel_max10_device *dev,
+       unsigned int reg, unsigned int *val)
 {
-       if (!g_max10)
+       if (!dev)
                return -ENODEV;
 
-       return spi_transaction_read(g_max10->spi_tran_dev,
+       dev_debug(dev, "%s: bus:0x%x, reg:0x%x\n", __func__, dev->bus, reg);
+
+       return spi_transaction_read(dev->spi_tran_dev,
                        reg, 4, (unsigned char *)val);
 }
 
-int max10_reg_write(unsigned int reg, unsigned int val)
+int max10_reg_write(struct intel_max10_device *dev,
+       unsigned int reg, unsigned int val)
 {
        unsigned int tmp = val;
 
-       if (!g_max10)
+       if (!dev)
                return -ENODEV;
 
-       return spi_transaction_write(g_max10->spi_tran_dev,
+       dev_debug(dev, "%s: bus:0x%x, reg:0x%x, val:0x%x\n", __func__,
+                       dev->bus, reg, val);
+
+       return spi_transaction_write(dev->spi_tran_dev,
                        reg, 4, (unsigned char *)&tmp);
 }
 
+int max10_sys_read(struct intel_max10_device *dev,
+       unsigned int offset, unsigned int *val)
+{
+       if (!dev)
+               return -ENODEV;
+
+
+       return max10_reg_read(dev, dev->base + offset, val);
+}
+
+int max10_sys_write(struct intel_max10_device *dev,
+       unsigned int offset, unsigned int val)
+{
+       if (!dev)
+               return -ENODEV;
+
+       return max10_reg_write(dev, dev->base + offset, val);
+}
+
 static struct max10_compatible_id max10_id_table[] = {
        {.compatible = MAX10_PAC,},
        {.compatible = MAX10_PAC_N3000,},
@@ -63,11 +87,12 @@ static void max10_check_capability(struct intel_max10_device *max10)
                max10->flags |= MAX10_FLAGS_NO_I2C2 |
                                MAX10_FLAGS_NO_BMCIMG_FLASH;
                dev_info(max10, "found %s card\n", max10->id->compatible);
-       }
+       } else
+               max10->flags |= MAX10_FLAGS_MAC_CACHE;
 }
 
-static int altera_nor_flash_read(u32 offset,
-               void *buffer, u32 len)
+static int altera_nor_flash_read(struct intel_max10_device *dev,
+       u32 offset, void *buffer, u32 len)
 {
        int word_len;
        int i;
@@ -75,13 +100,13 @@ static int altera_nor_flash_read(u32 offset,
        unsigned int value;
        int ret;
 
-       if (!buffer || len <= 0)
+       if (!dev || !buffer || len <= 0)
                return -ENODEV;
 
        word_len = len/4;
 
        for (i = 0; i < word_len; i++) {
-               ret = max10_reg_read(offset + i*4,
+               ret = max10_reg_read(dev, offset + i*4,
                                &value);
                if (ret)
                        return -EBUSY;
@@ -92,12 +117,12 @@ static int altera_nor_flash_read(u32 offset,
        return 0;
 }
 
-static int enable_nor_flash(bool on)
+static int enable_nor_flash(struct intel_max10_device *dev, bool on)
 {
        unsigned int val = 0;
        int ret;
 
-       ret = max10_reg_read(RSU_REG_OFF, &val);
+       ret = max10_sys_read(dev, RSU_REG, &val);
        if (ret) {
                dev_err(NULL "enabling flash error\n");
                return ret;
@@ -108,7 +133,7 @@ static int enable_nor_flash(bool on)
        else
                val &= ~RSU_ENABLE;
 
-       return max10_reg_write(RSU_REG_OFF, val);
+       return max10_sys_write(dev, RSU_REG, val);
 }
 
 static int init_max10_device_table(struct intel_max10_device *max10)
@@ -120,7 +145,7 @@ static int init_max10_device_table(struct intel_max10_device *max10)
        u32 dt_size, dt_addr, val;
        int ret;
 
-       ret = max10_reg_read(DT_AVAIL_REG_OFF, &val);
+       ret = max10_sys_read(max10, DT_AVAIL_REG, &val);
        if (ret) {
                dev_err(max10 "cannot read DT_AVAIL_REG\n");
                return ret;
@@ -131,19 +156,19 @@ static int init_max10_device_table(struct intel_max10_device *max10)
                return -EINVAL;
        }
 
-       ret = max10_reg_read(DT_BASE_ADDR_REG_OFF, &dt_addr);
+       ret = max10_sys_read(max10, DT_BASE_ADDR_REG, &dt_addr);
        if (ret) {
                dev_info(max10 "cannot get base addr of device table\n");
                return ret;
        }
 
-       ret = enable_nor_flash(true);
+       ret = enable_nor_flash(max10, true);
        if (ret) {
                dev_err(max10 "fail to enable flash\n");
                return ret;
        }
 
-       ret = altera_nor_flash_read(dt_addr, &hdr, sizeof(hdr));
+       ret = altera_nor_flash_read(max10, dt_addr, &hdr, sizeof(hdr));
        if (ret) {
                dev_err(max10 "read fdt header fail\n");
                goto done;
@@ -168,7 +193,7 @@ static int init_max10_device_table(struct intel_max10_device *max10)
                goto done;
        }
 
-       ret = altera_nor_flash_read(dt_addr, fdt_root, dt_size);
+       ret = altera_nor_flash_read(max10, dt_addr, fdt_root, dt_size);
        if (ret) {
                dev_err(max10 "cannot read device table\n");
                goto done;
@@ -187,7 +212,7 @@ static int init_max10_device_table(struct intel_max10_device *max10)
        max10->fdt_root = fdt_root;
 
 done:
-       ret = enable_nor_flash(false);
+       ret = enable_nor_flash(max10, false);
 
        if (ret && fdt_root)
                opae_free(fdt_root);
@@ -195,6 +220,348 @@ done:
        return ret;
 }
 
+static u64 fdt_get_number(const fdt32_t *cell, int size)
+{
+       u64 r = 0;
+
+       while (size--)
+               r = (r << 32) | fdt32_to_cpu(*cell++);
+
+       return r;
+}
+
+static int fdt_get_reg(const void *fdt, int node, unsigned int idx,
+               u64 *start, u64 *size)
+{
+       const fdt32_t *prop, *end;
+       int na = 0, ns = 0, len = 0, parent;
+
+       parent = fdt_parent_offset(fdt, node);
+       if (parent < 0)
+               return parent;
+
+       prop = fdt_getprop(fdt, parent, "#address-cells", NULL);
+       na = prop ? fdt32_to_cpu(*prop) : 2;
+
+       prop = fdt_getprop(fdt, parent, "#size-cells", NULL);
+       ns = prop ? fdt32_to_cpu(*prop) : 2;
+
+       prop = fdt_getprop(fdt, node, "reg", &len);
+       if (!prop)
+               return -FDT_ERR_NOTFOUND;
+
+       end = prop + len/sizeof(*prop);
+       prop = prop + (na + ns) * idx;
+
+       if (prop + na + ns > end)
+               return -FDT_ERR_NOTFOUND;
+
+       *start = fdt_get_number(prop, na);
+       *size = fdt_get_number(prop + na, ns);
+
+       return 0;
+}
+
+static int __fdt_stringlist_search(const void *fdt, int offset,
+               const char *prop, const char *string)
+{
+       int length, len, index = 0;
+       const char *list, *end;
+
+       list = fdt_getprop(fdt, offset, prop, &length);
+       if (!list)
+               return length;
+
+       len = strlen(string) + 1;
+       end = list + length;
+
+       while (list < end) {
+               length = strnlen(list, end - list) + 1;
+
+               if (list + length > end)
+                       return -FDT_ERR_BADVALUE;
+
+               if (length == len && memcmp(list, string, length) == 0)
+                       return index;
+
+               list += length;
+               index++;
+       }
+
+       return -FDT_ERR_NOTFOUND;
+}
+
+static int fdt_get_named_reg(const void *fdt, int node, const char *name,
+               u64 *start, u64 *size)
+{
+       int idx;
+
+       idx = __fdt_stringlist_search(fdt, node, "reg-names", name);
+       if (idx < 0)
+               return idx;
+
+       return fdt_get_reg(fdt, node, idx, start, size);
+}
+
+static void max10_sensor_uinit(struct intel_max10_device *dev)
+{
+       struct opae_sensor_info *info;
+
+       TAILQ_FOREACH(info, &dev->opae_sensor_list, node) {
+               TAILQ_REMOVE(&dev->opae_sensor_list, info, node);
+               opae_free(info);
+       }
+}
+
+static bool sensor_reg_valid(struct sensor_reg *reg)
+{
+       return !!reg->size;
+}
+
+static int max10_add_sensor(struct intel_max10_device *dev,
+       struct raw_sensor_info *info, struct opae_sensor_info *sensor)
+{
+       int i;
+       int ret = 0;
+       unsigned int val;
+
+       if (!info || !sensor)
+               return -ENODEV;
+
+       sensor->id = info->id;
+       sensor->name = info->name;
+       sensor->type = info->type;
+       sensor->multiplier = info->multiplier;
+
+       for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++) {
+               if (!sensor_reg_valid(&info->regs[i]))
+                       continue;
+
+               ret = max10_sys_read(dev, info->regs[i].regoff, &val);
+               if (ret)
+                       break;
+
+               if (val == 0xdeadbeef) {
+                       dev_debug(dev, "%s: sensor:%s invalid 0x%x at:%d\n",
+                               __func__, sensor->name, val, i);
+                       continue;
+               }
+
+               val *= info->multiplier;
+
+               switch (i) {
+               case SENSOR_REG_VALUE:
+                       sensor->value_reg = info->regs[i].regoff;
+                       sensor->flags |= OPAE_SENSOR_VALID;
+                       break;
+               case SENSOR_REG_HIGH_WARN:
+                       sensor->high_warn = val;
+                       sensor->flags |= OPAE_SENSOR_HIGH_WARN_VALID;
+                       break;
+               case SENSOR_REG_HIGH_FATAL:
+                       sensor->high_fatal = val;
+                       sensor->flags |= OPAE_SENSOR_HIGH_FATAL_VALID;
+                       break;
+               case SENSOR_REG_LOW_WARN:
+                       sensor->low_warn = val;
+                       sensor->flags |= OPAE_SENSOR_LOW_WARN_VALID;
+                       break;
+               case SENSOR_REG_LOW_FATAL:
+                       sensor->low_fatal = val;
+                       sensor->flags |= OPAE_SENSOR_LOW_FATAL_VALID;
+                       break;
+               case SENSOR_REG_HYSTERESIS:
+                       sensor->hysteresis = val;
+                       sensor->flags |= OPAE_SENSOR_HYSTERESIS_VALID;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+static int
+max10_sensor_init(struct intel_max10_device *dev, int parent)
+{
+       int i, ret = 0, offset = 0;
+       const fdt32_t *num;
+       const char *ptr;
+       u64 start, size;
+       struct raw_sensor_info *raw;
+       struct opae_sensor_info *sensor;
+       char *fdt_root = dev->fdt_root;
+
+       if (!fdt_root) {
+               dev_debug(dev, "skip sensor init as not find Device Tree\n");
+               return 0;
+       }
+
+       fdt_for_each_subnode(offset, fdt_root, parent) {
+               ptr = fdt_get_name(fdt_root, offset, NULL);
+               if (!ptr) {
+                       dev_err(dev, "failed to fdt get name\n");
+                       continue;
+               }
+
+               if (!strstr(ptr, "sensor")) {
+                       dev_debug(dev, "%s is not a sensor node\n", ptr);
+                       continue;
+               }
+
+               dev_debug(dev, "found sensor node %s\n", ptr);
+
+               raw = (struct raw_sensor_info *)opae_zmalloc(sizeof(*raw));
+               if (!raw) {
+                       ret = -ENOMEM;
+                       goto free_sensor;
+               }
+
+               raw->name = fdt_getprop(fdt_root, offset, "sensor_name", NULL);
+               if (!raw->name) {
+                       ret = -EINVAL;
+                       goto free_sensor;
+               }
+
+               raw->type = fdt_getprop(fdt_root, offset, "type", NULL);
+               if (!raw->type) {
+                       ret = -EINVAL;
+                       goto free_sensor;
+               }
+
+               for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++) {
+                       ret = fdt_get_named_reg(fdt_root, offset,
+                                       sensor_reg_name[i], &start,
+                                       &size);
+                       if (ret) {
+                               dev_debug(dev, "no found %d: sensor node %s, %s\n",
+                                               ret, ptr, sensor_reg_name[i]);
+                               if (i == SENSOR_REG_VALUE) {
+                                       ret = -EINVAL;
+                                       goto free_sensor;
+                               }
+
+                               continue;
+                       }
+
+                       /* This is a hack to compatible with non-secure
+                        * solution. If sensors are included in root node,
+                        * then it's non-secure dtb, which use absolute addr
+                        * of non-secure solution.
+                        */
+                       if (parent)
+                               raw->regs[i].regoff = start;
+                       else
+                               raw->regs[i].regoff = start -
+                                       MAX10_BASE_ADDR;
+                       raw->regs[i].size = size;
+               }
+
+               num = fdt_getprop(fdt_root, offset, "id", NULL);
+               if (!num) {
+                       ret = -EINVAL;
+                       goto free_sensor;
+               }
+
+               raw->id = fdt32_to_cpu(*num);
+               num = fdt_getprop(fdt_root, offset, "multiplier", NULL);
+               raw->multiplier = num ? fdt32_to_cpu(*num) : 1;
+
+               dev_debug(dev, "found sensor from DTB: %s: %s: %u: %u\n",
+                               raw->name, raw->type,
+                               raw->id, raw->multiplier);
+
+               for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++)
+                       dev_debug(dev, "sensor reg[%d]: %x: %zu\n",
+                                       i, raw->regs[i].regoff,
+                                       raw->regs[i].size);
+
+               sensor = opae_zmalloc(sizeof(*sensor));
+               if (!sensor) {
+                       ret = -EINVAL;
+                       goto free_sensor;
+               }
+
+               if (max10_add_sensor(dev, raw, sensor)) {
+                       ret = -EINVAL;
+                       opae_free(sensor);
+                       goto free_sensor;
+               }
+
+               if (sensor->flags & OPAE_SENSOR_VALID) {
+                       TAILQ_INSERT_TAIL(&dev->opae_sensor_list, sensor, node);
+                       dev_info(dev, "found valid sensor: %s\n", sensor->name);
+               } else
+                       opae_free(sensor);
+
+               opae_free(raw);
+       }
+
+       return 0;
+
+free_sensor:
+       if (raw)
+               opae_free(raw);
+       max10_sensor_uinit(dev);
+       return ret;
+}
+
+static int check_max10_version(struct intel_max10_device *dev)
+{
+       unsigned int v;
+
+       if (!max10_reg_read(dev, MAX10_SEC_BASE_ADDR + MAX10_BUILD_VER,
+                               &v)) {
+               if (v != 0xffffffff) {
+                       dev_info(dev, "secure MAX10 detected\n");
+                       dev->base = MAX10_SEC_BASE_ADDR;
+                       dev->flags |= MAX10_FLAGS_SECURE;
+               } else {
+                       dev_info(dev, "non-secure MAX10 detected\n");
+                       dev->base = MAX10_BASE_ADDR;
+               }
+               return 0;
+       }
+
+       return -ENODEV;
+}
+
+static int
+max10_secure_hw_init(struct intel_max10_device *dev)
+{
+       int offset, sysmgr_offset = 0;
+       char *fdt_root;
+
+       fdt_root = dev->fdt_root;
+       if (!fdt_root) {
+               dev_debug(dev, "skip init as not find Device Tree\n");
+               return 0;
+       }
+
+       fdt_for_each_subnode(offset, fdt_root, 0) {
+               if (!fdt_node_check_compatible(fdt_root, offset,
+                                       "intel-max10,system-manager")) {
+                       sysmgr_offset = offset;
+                       break;
+               }
+       }
+
+       max10_check_capability(dev);
+
+       max10_sensor_init(dev, sysmgr_offset);
+
+       return 0;
+}
+
+static int
+max10_non_secure_hw_init(struct intel_max10_device *dev)
+{
+       max10_check_capability(dev);
+
+       max10_sensor_init(dev, 0);
+
+       return 0;
+}
+
 struct intel_max10_device *
 intel_max10_device_probe(struct altera_spi_device *spi,
                int chipselect)
@@ -207,6 +574,8 @@ intel_max10_device_probe(struct altera_spi_device *spi,
        if (!dev)
                return NULL;
 
+       TAILQ_INIT(&dev->opae_sensor_list);
+
        dev->spi_master = spi;
 
        dev->spi_tran_dev = spi_transaction_init(spi, chipselect);
@@ -215,34 +584,48 @@ intel_max10_device_probe(struct altera_spi_device *spi,
                goto free_dev;
        }
 
-       /* set the max10 device firstly */
-       g_max10 = dev;
+       /* check the max10 version */
+       ret = check_max10_version(dev);
+       if (ret) {
+               dev_err(dev, "Failed to find max10 hardware!\n");
+               goto free_dev;
+       }
 
-       /* init the MAX10 device table */
+       /* load the MAX10 device table */
        ret = init_max10_device_table(dev);
        if (ret) {
-               dev_err(dev, "init max10 device table fail\n");
+               dev_err(dev, "Init max10 device table fail\n");
                goto free_dev;
        }
 
-       max10_check_capability(dev);
+       /* init max10 devices, like sensor*/
+       if (dev->flags & MAX10_FLAGS_SECURE)
+               ret = max10_secure_hw_init(dev);
+       else
+               ret = max10_non_secure_hw_init(dev);
+       if (ret) {
+               dev_err(dev, "Failed to init max10 hardware!\n");
+               goto free_dtb;
+       }
 
        /* read FPGA loading information */
-       ret = max10_reg_read(FPGA_PAGE_INFO_OFF, &val);
+       ret = max10_sys_read(dev, FPGA_PAGE_INFO, &val);
        if (ret) {
                dev_err(dev, "fail to get FPGA loading info\n");
-               goto spi_tran_fail;
+               goto release_max10_hw;
        }
        dev_info(dev, "FPGA loaded from %s Image\n", val ? "User" : "Factory");
 
        return dev;
 
-spi_tran_fail:
+release_max10_hw:
+       max10_sensor_uinit(dev);
+free_dtb:
        if (dev->fdt_root)
                opae_free(dev->fdt_root);
-       spi_transaction_remove(dev->spi_tran_dev);
+       if (dev->spi_tran_dev)
+               spi_transaction_remove(dev->spi_tran_dev);
 free_dev:
-       g_max10 = NULL;
        opae_free(dev);
 
        return NULL;
@@ -253,13 +636,14 @@ int intel_max10_device_remove(struct intel_max10_device *dev)
        if (!dev)
                return 0;
 
+       max10_sensor_uinit(dev);
+
        if (dev->spi_tran_dev)
                spi_transaction_remove(dev->spi_tran_dev);
 
        if (dev->fdt_root)
                opae_free(dev->fdt_root);
 
-       g_max10 = NULL;
        opae_free(dev);
 
        return 0;