static struct intel_max10_device *g_max10;
+struct opae_sensor_list opae_sensor_list =
+ TAILQ_HEAD_INITIALIZER(opae_sensor_list);
+
int max10_reg_read(unsigned int reg, unsigned int *val)
{
if (!g_max10)
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(void)
+{
+ struct opae_sensor_info *info;
+
+ TAILQ_FOREACH(info, &opae_sensor_list, node) {
+ TAILQ_REMOVE(&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 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_reg_read(info->regs[i].regoff, &val);
+ if (ret)
+ break;
+
+ if (val == 0xdeadbeef)
+ 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 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, 0) {
+ 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;
+ }
+
+ raw->regs[i].regoff = start;
+ 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_info(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(raw, sensor)) {
+ ret = -EINVAL;
+ opae_free(sensor);
+ goto free_sensor;
+ }
+
+ if (sensor->flags & OPAE_SENSOR_VALID)
+ TAILQ_INSERT_TAIL(&opae_sensor_list, sensor, node);
+ else
+ opae_free(sensor);
+
+ opae_free(raw);
+ }
+
+ return 0;
+
+free_sensor:
+ if (raw)
+ opae_free(raw);
+ max10_sensor_uinit();
+ return ret;
+}
+
struct intel_max10_device *
intel_max10_device_probe(struct altera_spi_device *spi,
int chipselect)
}
dev_info(dev, "FPGA loaded from %s Image\n", val ? "User" : "Factory");
+
+ max10_sensor_init(dev);
+
return dev;
spi_tran_fail:
if (!dev)
return 0;
+ max10_sensor_uinit();
+
if (dev->spi_tran_dev)
spi_transaction_remove(dev->spi_tran_dev);