From: Tianfei Zhang Date: Thu, 14 Nov 2019 09:02:55 +0000 (+0800) Subject: raw/ifpga/base: support sensor X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=45f301724ba7a684ca69edabe91772ca8ab04c98;p=dpdk.git raw/ifpga/base: support sensor The sensor devices are connected in MAX10 FPGA. we used the device tree to describe those sensor devices. Parse the device tree to get the sensor devices and add them into a list. Signed-off-by: Tianfei Zhang Signed-off-by: Andy Pei --- diff --git a/drivers/raw/ifpga/base/opae_intel_max10.c b/drivers/raw/ifpga/base/opae_intel_max10.c index 305baba8d4..ae7a8dfec8 100644 --- a/drivers/raw/ifpga/base/opae_intel_max10.c +++ b/drivers/raw/ifpga/base/opae_intel_max10.c @@ -7,6 +7,9 @@ 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) @@ -195,6 +198,277 @@ 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(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) @@ -235,6 +509,9 @@ intel_max10_device_probe(struct altera_spi_device *spi, } dev_info(dev, "FPGA loaded from %s Image\n", val ? "User" : "Factory"); + + max10_sensor_init(dev); + return dev; spi_tran_fail: @@ -253,6 +530,8 @@ int intel_max10_device_remove(struct intel_max10_device *dev) if (!dev) return 0; + max10_sensor_uinit(); + if (dev->spi_tran_dev) spi_transaction_remove(dev->spi_tran_dev); diff --git a/drivers/raw/ifpga/base/opae_intel_max10.h b/drivers/raw/ifpga/base/opae_intel_max10.h index a52b63e18e..90bf0981aa 100644 --- a/drivers/raw/ifpga/base/opae_intel_max10.h +++ b/drivers/raw/ifpga/base/opae_intel_max10.h @@ -103,4 +103,60 @@ intel_max10_device_probe(struct altera_spi_device *spi, int chipselect); int intel_max10_device_remove(struct intel_max10_device *dev); +/** List of opae sensors */ +TAILQ_HEAD(opae_sensor_list, opae_sensor_info); + +#define SENSOR_REG_VALUE 0x0 +#define SENSOR_REG_HIGH_WARN 0x1 +#define SENSOR_REG_HIGH_FATAL 0x2 +#define SENSOR_REG_LOW_WARN 0x3 +#define SENSOR_REG_LOW_FATAL 0x4 +#define SENSOR_REG_HYSTERESIS 0x5 +#define SENSOR_REG_MAX 0x6 + +static const char * const sensor_reg_name[] = { + "value", + "high_warn", + "high_fatal", + "low_warn", + "low_fatal", + "hysteresis", +}; + +struct sensor_reg { + unsigned int regoff; + size_t size; +}; + +struct raw_sensor_info { + const char *name; + const char *type; + unsigned int id; + unsigned int multiplier; + struct sensor_reg regs[SENSOR_REG_MAX]; +}; + +#define OPAE_SENSOR_VALID 0x1 +#define OPAE_SENSOR_HIGH_WARN_VALID 0x2 +#define OPAE_SENSOR_HIGH_FATAL_VALID 0x4 +#define OPAE_SENSOR_LOW_WARN_VALID 0x8 +#define OPAE_SENSOR_LOW_FATAL_VALID 0x10 +#define OPAE_SENSOR_HYSTERESIS_VALID 0x20 + +struct opae_sensor_info { + TAILQ_ENTRY(opae_sensor_info) node; + const char *name; + const char *type; + unsigned int id; + unsigned int high_fatal; + unsigned int high_warn; + unsigned int low_fatal; + unsigned int low_warn; + unsigned int hysteresis; + unsigned int multiplier; + unsigned int flags; + unsigned int value; + unsigned int value_reg; +}; + #endif