linux/drivers/hwmon/axi-fan-control.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Fan Control HDL CORE driver
 *
 * Copyright 2019 Analog Devices Inc.
 */
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/fpga/adi-axi-common.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/property.h>

/* register map */
#define ADI_REG_RSTN
#define ADI_REG_PWM_WIDTH
#define ADI_REG_TACH_PERIOD
#define ADI_REG_TACH_TOLERANCE
#define ADI_REG_PWM_PERIOD
#define ADI_REG_TACH_MEASUR
#define ADI_REG_TEMPERATURE
#define ADI_REG_TEMP_00_H
#define ADI_REG_TEMP_25_L
#define ADI_REG_TEMP_25_H
#define ADI_REG_TEMP_50_L
#define ADI_REG_TEMP_50_H
#define ADI_REG_TEMP_75_L
#define ADI_REG_TEMP_75_H
#define ADI_REG_TEMP_100_L

#define ADI_REG_IRQ_MASK
#define ADI_REG_IRQ_PENDING
#define ADI_REG_IRQ_SRC

/* IRQ sources */
#define ADI_IRQ_SRC_PWM_CHANGED
#define ADI_IRQ_SRC_TACH_ERR
#define ADI_IRQ_SRC_TEMP_INCREASE
#define ADI_IRQ_SRC_NEW_MEASUR
#define ADI_IRQ_SRC_MASK
#define ADI_IRQ_MASK_OUT_ALL

#define SYSFS_PWM_MAX

struct axi_fan_control_data {};

static inline void axi_iowrite(const u32 val, const u32 reg,
			       const struct axi_fan_control_data *ctl)
{}

static inline u32 axi_ioread(const u32 reg,
			     const struct axi_fan_control_data *ctl)
{}

/*
 * The core calculates the temperature as:
 *	T = /raw * 509.3140064 / 65535) - 280.2308787
 */
static ssize_t axi_fan_control_show(struct device *dev, struct device_attribute *da, char *buf)
{}

static ssize_t axi_fan_control_store(struct device *dev, struct device_attribute *da,
				     const char *buf, size_t count)
{}

static long axi_fan_control_get_pwm_duty(const struct axi_fan_control_data *ctl)
{}

static int axi_fan_control_set_pwm_duty(const long val,
					struct axi_fan_control_data *ctl)
{}

static long axi_fan_control_get_fan_rpm(const struct axi_fan_control_data *ctl)
{}

static int axi_fan_control_read_temp(struct device *dev, u32 attr, long *val)
{}

static int axi_fan_control_read_fan(struct device *dev, u32 attr, long *val)
{}

static int axi_fan_control_read_pwm(struct device *dev, u32 attr, long *val)
{}

static int axi_fan_control_write_pwm(struct device *dev, u32 attr, long val)
{}

static int axi_fan_control_read_labels(struct device *dev,
				       enum hwmon_sensor_types type,
				       u32 attr, int channel, const char **str)
{}

static int axi_fan_control_read(struct device *dev,
				enum hwmon_sensor_types type,
				u32 attr, int channel, long *val)
{}

static int axi_fan_control_write(struct device *dev,
				 enum hwmon_sensor_types type,
				 u32 attr, int channel, long val)
{}

static umode_t axi_fan_control_fan_is_visible(const u32 attr)
{}

static umode_t axi_fan_control_pwm_is_visible(const u32 attr)
{}

static umode_t axi_fan_control_temp_is_visible(const u32 attr)
{}

static umode_t axi_fan_control_is_visible(const void *data,
					  enum hwmon_sensor_types type,
					  u32 attr, int channel)
{}

/*
 * This core has two main ways of changing the PWM duty cycle. It is done,
 * either by a request from userspace (writing on pwm1_input) or by the
 * core itself. When the change is done by the core, it will use predefined
 * parameters to evaluate the tach signal and, on that case we cannot set them.
 * On the other hand, when the request is done by the user, with some arbitrary
 * value that the core does not now about, we have to provide the tach
 * parameters so that, the core can evaluate the signal. On the IRQ handler we
 * distinguish this by using the ADI_IRQ_SRC_TEMP_INCREASE interrupt. This tell
 * us that the CORE requested a new duty cycle. After this, there is 5s delay
 * on which the core waits for the fan rotation speed to stabilize. After this
 * we get ADI_IRQ_SRC_PWM_CHANGED irq where we will decide if we need to set
 * the tach parameters or not on the next tach measurement cycle (corresponding
 * already to the ney duty cycle) based on the %ctl->hw_pwm_req flag.
 */
static irqreturn_t axi_fan_control_irq_handler(int irq, void *data)
{}

static int axi_fan_control_init(struct axi_fan_control_data *ctl,
				const struct device *dev)
{}

static const struct hwmon_channel_info * const axi_fan_control_info[] =;

static const struct hwmon_ops axi_fan_control_hwmon_ops =;

static const struct hwmon_chip_info axi_chip_info =;

/* temperature threshold below which PWM should be 0% */
static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point1_temp_hyst, axi_fan_control, ADI_REG_TEMP_00_H);
/* temperature threshold above which PWM should be 25% */
static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point1_temp, axi_fan_control, ADI_REG_TEMP_25_L);
/* temperature threshold below which PWM should be 25% */
static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point2_temp_hyst, axi_fan_control, ADI_REG_TEMP_25_H);
/* temperature threshold above which PWM should be 50% */
static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point2_temp, axi_fan_control, ADI_REG_TEMP_50_L);
/* temperature threshold below which PWM should be 50% */
static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point3_temp_hyst, axi_fan_control, ADI_REG_TEMP_50_H);
/* temperature threshold above which PWM should be 75% */
static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point3_temp, axi_fan_control, ADI_REG_TEMP_75_L);
/* temperature threshold below which PWM should be 75% */
static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point4_temp_hyst, axi_fan_control, ADI_REG_TEMP_75_H);
/* temperature threshold above which PWM should be 100% */
static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point4_temp, axi_fan_control, ADI_REG_TEMP_100_L);

static struct attribute *axi_fan_control_attrs[] =;
ATTRIBUTE_GROUPS();

static int axi_fan_control_probe(struct platform_device *pdev)
{}

static const u32 version_1_0_0 =;

static const struct of_device_id axi_fan_control_of_match[] =;
MODULE_DEVICE_TABLE(of, axi_fan_control_of_match);

static struct platform_driver axi_fan_control_driver =;
module_platform_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();