18412b410SNuno Sá // SPDX-License-Identifier: GPL-2.0 28412b410SNuno Sá /* 38412b410SNuno Sá * Fan Control HDL CORE driver 48412b410SNuno Sá * 58412b410SNuno Sá * Copyright 2019 Analog Devices Inc. 68412b410SNuno Sá */ 78412b410SNuno Sá #include <linux/bits.h> 88412b410SNuno Sá #include <linux/clk.h> 98412b410SNuno Sá #include <linux/fpga/adi-axi-common.h> 108412b410SNuno Sá #include <linux/hwmon.h> 112aee7e67SNuno Sá #include <linux/hwmon-sysfs.h> 128412b410SNuno Sá #include <linux/interrupt.h> 138412b410SNuno Sá #include <linux/io.h> 148412b410SNuno Sá #include <linux/kernel.h> 158412b410SNuno Sá #include <linux/module.h> 168412b410SNuno Sá #include <linux/of.h> 178412b410SNuno Sá #include <linux/platform_device.h> 188412b410SNuno Sá 198412b410SNuno Sá /* register map */ 208412b410SNuno Sá #define ADI_REG_RSTN 0x0080 218412b410SNuno Sá #define ADI_REG_PWM_WIDTH 0x0084 228412b410SNuno Sá #define ADI_REG_TACH_PERIOD 0x0088 238412b410SNuno Sá #define ADI_REG_TACH_TOLERANCE 0x008c 248412b410SNuno Sá #define ADI_REG_PWM_PERIOD 0x00c0 258412b410SNuno Sá #define ADI_REG_TACH_MEASUR 0x00c4 268412b410SNuno Sá #define ADI_REG_TEMPERATURE 0x00c8 272aee7e67SNuno Sá #define ADI_REG_TEMP_00_H 0x0100 282aee7e67SNuno Sá #define ADI_REG_TEMP_25_L 0x0104 292aee7e67SNuno Sá #define ADI_REG_TEMP_25_H 0x0108 302aee7e67SNuno Sá #define ADI_REG_TEMP_50_L 0x010c 312aee7e67SNuno Sá #define ADI_REG_TEMP_50_H 0x0110 322aee7e67SNuno Sá #define ADI_REG_TEMP_75_L 0x0114 332aee7e67SNuno Sá #define ADI_REG_TEMP_75_H 0x0118 342aee7e67SNuno Sá #define ADI_REG_TEMP_100_L 0x011c 358412b410SNuno Sá 368412b410SNuno Sá #define ADI_REG_IRQ_MASK 0x0040 378412b410SNuno Sá #define ADI_REG_IRQ_PENDING 0x0044 388412b410SNuno Sá #define ADI_REG_IRQ_SRC 0x0048 398412b410SNuno Sá 408412b410SNuno Sá /* IRQ sources */ 418412b410SNuno Sá #define ADI_IRQ_SRC_PWM_CHANGED BIT(0) 428412b410SNuno Sá #define ADI_IRQ_SRC_TACH_ERR BIT(1) 438412b410SNuno Sá #define ADI_IRQ_SRC_TEMP_INCREASE BIT(2) 448412b410SNuno Sá #define ADI_IRQ_SRC_NEW_MEASUR BIT(3) 458412b410SNuno Sá #define ADI_IRQ_SRC_MASK GENMASK(3, 0) 468412b410SNuno Sá #define ADI_IRQ_MASK_OUT_ALL 0xFFFFFFFFU 478412b410SNuno Sá 488412b410SNuno Sá #define SYSFS_PWM_MAX 255 498412b410SNuno Sá 508412b410SNuno Sá struct axi_fan_control_data { 518412b410SNuno Sá void __iomem *base; 528412b410SNuno Sá struct device *hdev; 538412b410SNuno Sá unsigned long clk_rate; 548412b410SNuno Sá int irq; 558412b410SNuno Sá /* pulses per revolution */ 568412b410SNuno Sá u32 ppr; 578412b410SNuno Sá bool hw_pwm_req; 588412b410SNuno Sá bool update_tacho_params; 598412b410SNuno Sá u8 fan_fault; 608412b410SNuno Sá }; 618412b410SNuno Sá 628412b410SNuno Sá static inline void axi_iowrite(const u32 val, const u32 reg, 638412b410SNuno Sá const struct axi_fan_control_data *ctl) 648412b410SNuno Sá { 658412b410SNuno Sá iowrite32(val, ctl->base + reg); 668412b410SNuno Sá } 678412b410SNuno Sá 688412b410SNuno Sá static inline u32 axi_ioread(const u32 reg, 698412b410SNuno Sá const struct axi_fan_control_data *ctl) 708412b410SNuno Sá { 718412b410SNuno Sá return ioread32(ctl->base + reg); 728412b410SNuno Sá } 738412b410SNuno Sá 742aee7e67SNuno Sá /* 752aee7e67SNuno Sá * The core calculates the temperature as: 762aee7e67SNuno Sá * T = /raw * 509.3140064 / 65535) - 280.2308787 772aee7e67SNuno Sá */ 782aee7e67SNuno Sá static ssize_t axi_fan_control_show(struct device *dev, struct device_attribute *da, char *buf) 792aee7e67SNuno Sá { 802aee7e67SNuno Sá struct axi_fan_control_data *ctl = dev_get_drvdata(dev); 812aee7e67SNuno Sá struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 822aee7e67SNuno Sá u32 temp = axi_ioread(attr->index, ctl); 832aee7e67SNuno Sá 842aee7e67SNuno Sá temp = DIV_ROUND_CLOSEST_ULL(temp * 509314ULL, 65535) - 280230; 852aee7e67SNuno Sá 862aee7e67SNuno Sá return sprintf(buf, "%u\n", temp); 872aee7e67SNuno Sá } 882aee7e67SNuno Sá 892aee7e67SNuno Sá static ssize_t axi_fan_control_store(struct device *dev, struct device_attribute *da, 902aee7e67SNuno Sá const char *buf, size_t count) 912aee7e67SNuno Sá { 922aee7e67SNuno Sá struct axi_fan_control_data *ctl = dev_get_drvdata(dev); 932aee7e67SNuno Sá struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 942aee7e67SNuno Sá u32 temp; 952aee7e67SNuno Sá int ret; 962aee7e67SNuno Sá 972aee7e67SNuno Sá ret = kstrtou32(buf, 10, &temp); 982aee7e67SNuno Sá if (ret) 992aee7e67SNuno Sá return ret; 1002aee7e67SNuno Sá 1012aee7e67SNuno Sá temp = DIV_ROUND_CLOSEST_ULL((temp + 280230) * 65535ULL, 509314); 1022aee7e67SNuno Sá axi_iowrite(temp, attr->index, ctl); 1032aee7e67SNuno Sá 1042aee7e67SNuno Sá return count; 1052aee7e67SNuno Sá } 1062aee7e67SNuno Sá 1078412b410SNuno Sá static long axi_fan_control_get_pwm_duty(const struct axi_fan_control_data *ctl) 1088412b410SNuno Sá { 1098412b410SNuno Sá u32 pwm_width = axi_ioread(ADI_REG_PWM_WIDTH, ctl); 1108412b410SNuno Sá u32 pwm_period = axi_ioread(ADI_REG_PWM_PERIOD, ctl); 1118412b410SNuno Sá /* 1128412b410SNuno Sá * PWM_PERIOD is a RO register set by the core. It should never be 0. 1138412b410SNuno Sá * For now we are trusting the HW... 1148412b410SNuno Sá */ 1158412b410SNuno Sá return DIV_ROUND_CLOSEST(pwm_width * SYSFS_PWM_MAX, pwm_period); 1168412b410SNuno Sá } 1178412b410SNuno Sá 1188412b410SNuno Sá static int axi_fan_control_set_pwm_duty(const long val, 1198412b410SNuno Sá struct axi_fan_control_data *ctl) 1208412b410SNuno Sá { 1218412b410SNuno Sá u32 pwm_period = axi_ioread(ADI_REG_PWM_PERIOD, ctl); 1228412b410SNuno Sá u32 new_width; 1238412b410SNuno Sá long __val = clamp_val(val, 0, SYSFS_PWM_MAX); 1248412b410SNuno Sá 1258412b410SNuno Sá new_width = DIV_ROUND_CLOSEST(__val * pwm_period, SYSFS_PWM_MAX); 1268412b410SNuno Sá 1278412b410SNuno Sá axi_iowrite(new_width, ADI_REG_PWM_WIDTH, ctl); 1288412b410SNuno Sá 1298412b410SNuno Sá return 0; 1308412b410SNuno Sá } 1318412b410SNuno Sá 1328412b410SNuno Sá static long axi_fan_control_get_fan_rpm(const struct axi_fan_control_data *ctl) 1338412b410SNuno Sá { 1348412b410SNuno Sá const u32 tach = axi_ioread(ADI_REG_TACH_MEASUR, ctl); 1358412b410SNuno Sá 1368412b410SNuno Sá if (tach == 0) 1378412b410SNuno Sá /* should we return error, EAGAIN maybe? */ 1388412b410SNuno Sá return 0; 1398412b410SNuno Sá /* 1408412b410SNuno Sá * The tacho period should be: 1418412b410SNuno Sá * TACH = 60/(ppr * rpm), where rpm is revolutions per second 1428412b410SNuno Sá * and ppr is pulses per revolution. 1438412b410SNuno Sá * Given the tacho period, we can multiply it by the input clock 1448412b410SNuno Sá * so that we know how many clocks we need to have this period. 1458412b410SNuno Sá * From this, we can derive the RPM value. 1468412b410SNuno Sá */ 1478412b410SNuno Sá return DIV_ROUND_CLOSEST(60 * ctl->clk_rate, ctl->ppr * tach); 1488412b410SNuno Sá } 1498412b410SNuno Sá 1508412b410SNuno Sá static int axi_fan_control_read_temp(struct device *dev, u32 attr, long *val) 1518412b410SNuno Sá { 1528412b410SNuno Sá struct axi_fan_control_data *ctl = dev_get_drvdata(dev); 1538412b410SNuno Sá long raw_temp; 1548412b410SNuno Sá 1558412b410SNuno Sá switch (attr) { 1568412b410SNuno Sá case hwmon_temp_input: 1578412b410SNuno Sá raw_temp = axi_ioread(ADI_REG_TEMPERATURE, ctl); 1588412b410SNuno Sá /* 1598412b410SNuno Sá * The formula for the temperature is: 1608412b410SNuno Sá * T = (ADC * 501.3743 / 2^bits) - 273.6777 1618412b410SNuno Sá * It's multiplied by 1000 to have millidegrees as 1628412b410SNuno Sá * specified by the hwmon sysfs interface. 1638412b410SNuno Sá */ 1648412b410SNuno Sá *val = ((raw_temp * 501374) >> 16) - 273677; 1658412b410SNuno Sá return 0; 1668412b410SNuno Sá default: 1678412b410SNuno Sá return -ENOTSUPP; 1688412b410SNuno Sá } 1698412b410SNuno Sá } 1708412b410SNuno Sá 1718412b410SNuno Sá static int axi_fan_control_read_fan(struct device *dev, u32 attr, long *val) 1728412b410SNuno Sá { 1738412b410SNuno Sá struct axi_fan_control_data *ctl = dev_get_drvdata(dev); 1748412b410SNuno Sá 1758412b410SNuno Sá switch (attr) { 1768412b410SNuno Sá case hwmon_fan_fault: 1778412b410SNuno Sá *val = ctl->fan_fault; 1788412b410SNuno Sá /* clear it now */ 1798412b410SNuno Sá ctl->fan_fault = 0; 1808412b410SNuno Sá return 0; 1818412b410SNuno Sá case hwmon_fan_input: 1828412b410SNuno Sá *val = axi_fan_control_get_fan_rpm(ctl); 1838412b410SNuno Sá return 0; 1848412b410SNuno Sá default: 1858412b410SNuno Sá return -ENOTSUPP; 1868412b410SNuno Sá } 1878412b410SNuno Sá } 1888412b410SNuno Sá 1898412b410SNuno Sá static int axi_fan_control_read_pwm(struct device *dev, u32 attr, long *val) 1908412b410SNuno Sá { 1918412b410SNuno Sá struct axi_fan_control_data *ctl = dev_get_drvdata(dev); 1928412b410SNuno Sá 1938412b410SNuno Sá switch (attr) { 1948412b410SNuno Sá case hwmon_pwm_input: 1958412b410SNuno Sá *val = axi_fan_control_get_pwm_duty(ctl); 1968412b410SNuno Sá return 0; 1978412b410SNuno Sá default: 1988412b410SNuno Sá return -ENOTSUPP; 1998412b410SNuno Sá } 2008412b410SNuno Sá } 2018412b410SNuno Sá 2028412b410SNuno Sá static int axi_fan_control_write_pwm(struct device *dev, u32 attr, long val) 2038412b410SNuno Sá { 2048412b410SNuno Sá struct axi_fan_control_data *ctl = dev_get_drvdata(dev); 2058412b410SNuno Sá 2068412b410SNuno Sá switch (attr) { 2078412b410SNuno Sá case hwmon_pwm_input: 2088412b410SNuno Sá return axi_fan_control_set_pwm_duty(val, ctl); 2098412b410SNuno Sá default: 2108412b410SNuno Sá return -ENOTSUPP; 2118412b410SNuno Sá } 2128412b410SNuno Sá } 2138412b410SNuno Sá 2148412b410SNuno Sá static int axi_fan_control_read_labels(struct device *dev, 2158412b410SNuno Sá enum hwmon_sensor_types type, 2168412b410SNuno Sá u32 attr, int channel, const char **str) 2178412b410SNuno Sá { 2188412b410SNuno Sá switch (type) { 2198412b410SNuno Sá case hwmon_fan: 2208412b410SNuno Sá *str = "FAN"; 2218412b410SNuno Sá return 0; 2228412b410SNuno Sá case hwmon_temp: 2238412b410SNuno Sá *str = "SYSMON4"; 2248412b410SNuno Sá return 0; 2258412b410SNuno Sá default: 2268412b410SNuno Sá return -ENOTSUPP; 2278412b410SNuno Sá } 2288412b410SNuno Sá } 2298412b410SNuno Sá 2308412b410SNuno Sá static int axi_fan_control_read(struct device *dev, 2318412b410SNuno Sá enum hwmon_sensor_types type, 2328412b410SNuno Sá u32 attr, int channel, long *val) 2338412b410SNuno Sá { 2348412b410SNuno Sá switch (type) { 2358412b410SNuno Sá case hwmon_fan: 2368412b410SNuno Sá return axi_fan_control_read_fan(dev, attr, val); 2378412b410SNuno Sá case hwmon_pwm: 2388412b410SNuno Sá return axi_fan_control_read_pwm(dev, attr, val); 2398412b410SNuno Sá case hwmon_temp: 2408412b410SNuno Sá return axi_fan_control_read_temp(dev, attr, val); 2418412b410SNuno Sá default: 2428412b410SNuno Sá return -ENOTSUPP; 2438412b410SNuno Sá } 2448412b410SNuno Sá } 2458412b410SNuno Sá 2468412b410SNuno Sá static int axi_fan_control_write(struct device *dev, 2478412b410SNuno Sá enum hwmon_sensor_types type, 2488412b410SNuno Sá u32 attr, int channel, long val) 2498412b410SNuno Sá { 2508412b410SNuno Sá switch (type) { 2518412b410SNuno Sá case hwmon_pwm: 2528412b410SNuno Sá return axi_fan_control_write_pwm(dev, attr, val); 2538412b410SNuno Sá default: 2548412b410SNuno Sá return -ENOTSUPP; 2558412b410SNuno Sá } 2568412b410SNuno Sá } 2578412b410SNuno Sá 2588412b410SNuno Sá static umode_t axi_fan_control_fan_is_visible(const u32 attr) 2598412b410SNuno Sá { 2608412b410SNuno Sá switch (attr) { 2618412b410SNuno Sá case hwmon_fan_input: 2628412b410SNuno Sá case hwmon_fan_fault: 2638412b410SNuno Sá case hwmon_fan_label: 2648412b410SNuno Sá return 0444; 2658412b410SNuno Sá default: 2668412b410SNuno Sá return 0; 2678412b410SNuno Sá } 2688412b410SNuno Sá } 2698412b410SNuno Sá 2708412b410SNuno Sá static umode_t axi_fan_control_pwm_is_visible(const u32 attr) 2718412b410SNuno Sá { 2728412b410SNuno Sá switch (attr) { 2738412b410SNuno Sá case hwmon_pwm_input: 2748412b410SNuno Sá return 0644; 2758412b410SNuno Sá default: 2768412b410SNuno Sá return 0; 2778412b410SNuno Sá } 2788412b410SNuno Sá } 2798412b410SNuno Sá 2808412b410SNuno Sá static umode_t axi_fan_control_temp_is_visible(const u32 attr) 2818412b410SNuno Sá { 2828412b410SNuno Sá switch (attr) { 2838412b410SNuno Sá case hwmon_temp_input: 2848412b410SNuno Sá case hwmon_temp_label: 2858412b410SNuno Sá return 0444; 2868412b410SNuno Sá default: 2878412b410SNuno Sá return 0; 2888412b410SNuno Sá } 2898412b410SNuno Sá } 2908412b410SNuno Sá 2918412b410SNuno Sá static umode_t axi_fan_control_is_visible(const void *data, 2928412b410SNuno Sá enum hwmon_sensor_types type, 2938412b410SNuno Sá u32 attr, int channel) 2948412b410SNuno Sá { 2958412b410SNuno Sá switch (type) { 2968412b410SNuno Sá case hwmon_fan: 2978412b410SNuno Sá return axi_fan_control_fan_is_visible(attr); 2988412b410SNuno Sá case hwmon_pwm: 2998412b410SNuno Sá return axi_fan_control_pwm_is_visible(attr); 3008412b410SNuno Sá case hwmon_temp: 3018412b410SNuno Sá return axi_fan_control_temp_is_visible(attr); 3028412b410SNuno Sá default: 3038412b410SNuno Sá return 0; 3048412b410SNuno Sá } 3058412b410SNuno Sá } 3068412b410SNuno Sá 3078412b410SNuno Sá /* 3088412b410SNuno Sá * This core has two main ways of changing the PWM duty cycle. It is done, 3098412b410SNuno Sá * either by a request from userspace (writing on pwm1_input) or by the 3108412b410SNuno Sá * core itself. When the change is done by the core, it will use predefined 3118412b410SNuno Sá * parameters to evaluate the tach signal and, on that case we cannot set them. 3128412b410SNuno Sá * On the other hand, when the request is done by the user, with some arbitrary 3138412b410SNuno Sá * value that the core does not now about, we have to provide the tach 3148412b410SNuno Sá * parameters so that, the core can evaluate the signal. On the IRQ handler we 3158412b410SNuno Sá * distinguish this by using the ADI_IRQ_SRC_TEMP_INCREASE interrupt. This tell 3168412b410SNuno Sá * us that the CORE requested a new duty cycle. After this, there is 5s delay 3178412b410SNuno Sá * on which the core waits for the fan rotation speed to stabilize. After this 3188412b410SNuno Sá * we get ADI_IRQ_SRC_PWM_CHANGED irq where we will decide if we need to set 3198412b410SNuno Sá * the tach parameters or not on the next tach measurement cycle (corresponding 3208412b410SNuno Sá * already to the ney duty cycle) based on the %ctl->hw_pwm_req flag. 3218412b410SNuno Sá */ 3228412b410SNuno Sá static irqreturn_t axi_fan_control_irq_handler(int irq, void *data) 3238412b410SNuno Sá { 3248412b410SNuno Sá struct axi_fan_control_data *ctl = (struct axi_fan_control_data *)data; 3258412b410SNuno Sá u32 irq_pending = axi_ioread(ADI_REG_IRQ_PENDING, ctl); 3268412b410SNuno Sá u32 clear_mask; 3278412b410SNuno Sá 328e66705deSNuno Sá if (irq_pending & ADI_IRQ_SRC_TEMP_INCREASE) 329e66705deSNuno Sá /* hardware requested a new pwm */ 330e66705deSNuno Sá ctl->hw_pwm_req = true; 3318412b410SNuno Sá 3328412b410SNuno Sá if (irq_pending & ADI_IRQ_SRC_PWM_CHANGED) { 3338412b410SNuno Sá /* 3348412b410SNuno Sá * if the pwm changes on behalf of software, 3358412b410SNuno Sá * we need to provide new tacho parameters to the core. 3368412b410SNuno Sá * Wait for the next measurement for that... 3378412b410SNuno Sá */ 3388412b410SNuno Sá if (!ctl->hw_pwm_req) { 3398412b410SNuno Sá ctl->update_tacho_params = true; 3408412b410SNuno Sá } else { 3418412b410SNuno Sá ctl->hw_pwm_req = false; 3425d4a2ea9SNuno Sá hwmon_notify_event(ctl->hdev, hwmon_pwm, 3435d4a2ea9SNuno Sá hwmon_pwm_input, 0); 3448412b410SNuno Sá } 3458412b410SNuno Sá } 3468412b410SNuno Sá 347e66705deSNuno Sá if (irq_pending & ADI_IRQ_SRC_NEW_MEASUR) { 348e66705deSNuno Sá if (ctl->update_tacho_params) { 349e66705deSNuno Sá u32 new_tach = axi_ioread(ADI_REG_TACH_MEASUR, ctl); 350e66705deSNuno Sá /* get 25% tolerance */ 351e66705deSNuno Sá u32 tach_tol = DIV_ROUND_CLOSEST(new_tach * 25, 100); 352e66705deSNuno Sá 353e66705deSNuno Sá /* set new tacho parameters */ 354e66705deSNuno Sá axi_iowrite(new_tach, ADI_REG_TACH_PERIOD, ctl); 355e66705deSNuno Sá axi_iowrite(tach_tol, ADI_REG_TACH_TOLERANCE, ctl); 356e66705deSNuno Sá ctl->update_tacho_params = false; 357e66705deSNuno Sá } 358e66705deSNuno Sá } 3598412b410SNuno Sá 3608412b410SNuno Sá if (irq_pending & ADI_IRQ_SRC_TACH_ERR) 3618412b410SNuno Sá ctl->fan_fault = 1; 3628412b410SNuno Sá 3638412b410SNuno Sá /* clear all interrupts */ 3648412b410SNuno Sá clear_mask = irq_pending & ADI_IRQ_SRC_MASK; 3658412b410SNuno Sá axi_iowrite(clear_mask, ADI_REG_IRQ_PENDING, ctl); 3668412b410SNuno Sá 3678412b410SNuno Sá return IRQ_HANDLED; 3688412b410SNuno Sá } 3698412b410SNuno Sá 3708412b410SNuno Sá static int axi_fan_control_init(struct axi_fan_control_data *ctl, 3718412b410SNuno Sá const struct device_node *np) 3728412b410SNuno Sá { 3738412b410SNuno Sá int ret; 3748412b410SNuno Sá 3758412b410SNuno Sá /* get fan pulses per revolution */ 3768412b410SNuno Sá ret = of_property_read_u32(np, "pulses-per-revolution", &ctl->ppr); 3778412b410SNuno Sá if (ret) 3788412b410SNuno Sá return ret; 3798412b410SNuno Sá 3808412b410SNuno Sá /* 1, 2 and 4 are the typical and accepted values */ 3818412b410SNuno Sá if (ctl->ppr != 1 && ctl->ppr != 2 && ctl->ppr != 4) 3828412b410SNuno Sá return -EINVAL; 3838412b410SNuno Sá /* 3848412b410SNuno Sá * Enable all IRQs 3858412b410SNuno Sá */ 3868412b410SNuno Sá axi_iowrite(ADI_IRQ_MASK_OUT_ALL & 3878412b410SNuno Sá ~(ADI_IRQ_SRC_NEW_MEASUR | ADI_IRQ_SRC_TACH_ERR | 3888412b410SNuno Sá ADI_IRQ_SRC_PWM_CHANGED | ADI_IRQ_SRC_TEMP_INCREASE), 3898412b410SNuno Sá ADI_REG_IRQ_MASK, ctl); 3908412b410SNuno Sá 3918412b410SNuno Sá /* bring the device out of reset */ 3928412b410SNuno Sá axi_iowrite(0x01, ADI_REG_RSTN, ctl); 3938412b410SNuno Sá 3948412b410SNuno Sá return ret; 3958412b410SNuno Sá } 3968412b410SNuno Sá 397*a1e308bfSKrzysztof Kozlowski static const struct hwmon_channel_info * const axi_fan_control_info[] = { 3988412b410SNuno Sá HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT), 3998412b410SNuno Sá HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_LABEL), 4008412b410SNuno Sá HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_LABEL), 4018412b410SNuno Sá NULL 4028412b410SNuno Sá }; 4038412b410SNuno Sá 4048412b410SNuno Sá static const struct hwmon_ops axi_fan_control_hwmon_ops = { 4058412b410SNuno Sá .is_visible = axi_fan_control_is_visible, 4068412b410SNuno Sá .read = axi_fan_control_read, 4078412b410SNuno Sá .write = axi_fan_control_write, 4088412b410SNuno Sá .read_string = axi_fan_control_read_labels, 4098412b410SNuno Sá }; 4108412b410SNuno Sá 4118412b410SNuno Sá static const struct hwmon_chip_info axi_chip_info = { 4128412b410SNuno Sá .ops = &axi_fan_control_hwmon_ops, 4138412b410SNuno Sá .info = axi_fan_control_info, 4148412b410SNuno Sá }; 4158412b410SNuno Sá 4162aee7e67SNuno Sá /* temperature threshold below which PWM should be 0% */ 4172aee7e67SNuno Sá static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point1_temp_hyst, axi_fan_control, ADI_REG_TEMP_00_H); 4182aee7e67SNuno Sá /* temperature threshold above which PWM should be 25% */ 4192aee7e67SNuno Sá static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point1_temp, axi_fan_control, ADI_REG_TEMP_25_L); 4202aee7e67SNuno Sá /* temperature threshold below which PWM should be 25% */ 4212aee7e67SNuno Sá static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point2_temp_hyst, axi_fan_control, ADI_REG_TEMP_25_H); 4222aee7e67SNuno Sá /* temperature threshold above which PWM should be 50% */ 4232aee7e67SNuno Sá static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point2_temp, axi_fan_control, ADI_REG_TEMP_50_L); 4242aee7e67SNuno Sá /* temperature threshold below which PWM should be 50% */ 4252aee7e67SNuno Sá static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point3_temp_hyst, axi_fan_control, ADI_REG_TEMP_50_H); 4262aee7e67SNuno Sá /* temperature threshold above which PWM should be 75% */ 4272aee7e67SNuno Sá static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point3_temp, axi_fan_control, ADI_REG_TEMP_75_L); 4282aee7e67SNuno Sá /* temperature threshold below which PWM should be 75% */ 4292aee7e67SNuno Sá static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point4_temp_hyst, axi_fan_control, ADI_REG_TEMP_75_H); 4302aee7e67SNuno Sá /* temperature threshold above which PWM should be 100% */ 4312aee7e67SNuno Sá static SENSOR_DEVICE_ATTR_RW(pwm1_auto_point4_temp, axi_fan_control, ADI_REG_TEMP_100_L); 4322aee7e67SNuno Sá 4332aee7e67SNuno Sá static struct attribute *axi_fan_control_attrs[] = { 4342aee7e67SNuno Sá &sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr, 4352aee7e67SNuno Sá &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, 4362aee7e67SNuno Sá &sensor_dev_attr_pwm1_auto_point2_temp_hyst.dev_attr.attr, 4372aee7e67SNuno Sá &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, 4382aee7e67SNuno Sá &sensor_dev_attr_pwm1_auto_point3_temp_hyst.dev_attr.attr, 4392aee7e67SNuno Sá &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, 4402aee7e67SNuno Sá &sensor_dev_attr_pwm1_auto_point4_temp_hyst.dev_attr.attr, 4412aee7e67SNuno Sá &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr, 4422aee7e67SNuno Sá NULL, 4432aee7e67SNuno Sá }; 4442aee7e67SNuno Sá ATTRIBUTE_GROUPS(axi_fan_control); 4452aee7e67SNuno Sá 4468412b410SNuno Sá static const u32 version_1_0_0 = ADI_AXI_PCORE_VER(1, 0, 'a'); 4478412b410SNuno Sá 4488412b410SNuno Sá static const struct of_device_id axi_fan_control_of_match[] = { 4498412b410SNuno Sá { .compatible = "adi,axi-fan-control-1.00.a", 4508412b410SNuno Sá .data = (void *)&version_1_0_0}, 4518412b410SNuno Sá {}, 4528412b410SNuno Sá }; 4538412b410SNuno Sá MODULE_DEVICE_TABLE(of, axi_fan_control_of_match); 4548412b410SNuno Sá 4558412b410SNuno Sá static int axi_fan_control_probe(struct platform_device *pdev) 4568412b410SNuno Sá { 4578412b410SNuno Sá struct axi_fan_control_data *ctl; 4588412b410SNuno Sá struct clk *clk; 4598412b410SNuno Sá const struct of_device_id *id; 4608412b410SNuno Sá const char *name = "axi_fan_control"; 4618412b410SNuno Sá u32 version; 4628412b410SNuno Sá int ret; 4638412b410SNuno Sá 4648412b410SNuno Sá id = of_match_node(axi_fan_control_of_match, pdev->dev.of_node); 4658412b410SNuno Sá if (!id) 4668412b410SNuno Sá return -EINVAL; 4678412b410SNuno Sá 4688412b410SNuno Sá ctl = devm_kzalloc(&pdev->dev, sizeof(*ctl), GFP_KERNEL); 4698412b410SNuno Sá if (!ctl) 4708412b410SNuno Sá return -ENOMEM; 4718412b410SNuno Sá 4728412b410SNuno Sá ctl->base = devm_platform_ioremap_resource(pdev, 0); 4738412b410SNuno Sá if (IS_ERR(ctl->base)) 4748412b410SNuno Sá return PTR_ERR(ctl->base); 4758412b410SNuno Sá 4760dee25ebSUwe Kleine-König clk = devm_clk_get_enabled(&pdev->dev, NULL); 4778412b410SNuno Sá if (IS_ERR(clk)) { 4788412b410SNuno Sá dev_err(&pdev->dev, "clk_get failed with %ld\n", PTR_ERR(clk)); 4798412b410SNuno Sá return PTR_ERR(clk); 4808412b410SNuno Sá } 4818412b410SNuno Sá 4828412b410SNuno Sá ctl->clk_rate = clk_get_rate(clk); 4838412b410SNuno Sá if (!ctl->clk_rate) 4848412b410SNuno Sá return -EINVAL; 4858412b410SNuno Sá 4868412b410SNuno Sá version = axi_ioread(ADI_AXI_REG_VERSION, ctl); 4878412b410SNuno Sá if (ADI_AXI_PCORE_VER_MAJOR(version) != 4888412b410SNuno Sá ADI_AXI_PCORE_VER_MAJOR((*(u32 *)id->data))) { 4898412b410SNuno Sá dev_err(&pdev->dev, "Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n", 4908412b410SNuno Sá ADI_AXI_PCORE_VER_MAJOR((*(u32 *)id->data)), 4918412b410SNuno Sá ADI_AXI_PCORE_VER_MINOR((*(u32 *)id->data)), 4928412b410SNuno Sá ADI_AXI_PCORE_VER_PATCH((*(u32 *)id->data)), 4938412b410SNuno Sá ADI_AXI_PCORE_VER_MAJOR(version), 4948412b410SNuno Sá ADI_AXI_PCORE_VER_MINOR(version), 4958412b410SNuno Sá ADI_AXI_PCORE_VER_PATCH(version)); 4968412b410SNuno Sá return -ENODEV; 4978412b410SNuno Sá } 4988412b410SNuno Sá 4998412b410SNuno Sá ctl->irq = platform_get_irq(pdev, 0); 5008412b410SNuno Sá if (ctl->irq < 0) 5018412b410SNuno Sá return ctl->irq; 5028412b410SNuno Sá 5038412b410SNuno Sá ret = devm_request_threaded_irq(&pdev->dev, ctl->irq, NULL, 5048412b410SNuno Sá axi_fan_control_irq_handler, 5058412b410SNuno Sá IRQF_ONESHOT | IRQF_TRIGGER_HIGH, 5068412b410SNuno Sá pdev->driver_override, ctl); 5078412b410SNuno Sá if (ret) { 5088412b410SNuno Sá dev_err(&pdev->dev, "failed to request an irq, %d", ret); 5098412b410SNuno Sá return ret; 5108412b410SNuno Sá } 5118412b410SNuno Sá 5128412b410SNuno Sá ret = axi_fan_control_init(ctl, pdev->dev.of_node); 5138412b410SNuno Sá if (ret) { 5148412b410SNuno Sá dev_err(&pdev->dev, "Failed to initialize device\n"); 5158412b410SNuno Sá return ret; 5168412b410SNuno Sá } 5178412b410SNuno Sá 5188412b410SNuno Sá ctl->hdev = devm_hwmon_device_register_with_info(&pdev->dev, 5198412b410SNuno Sá name, 5208412b410SNuno Sá ctl, 5218412b410SNuno Sá &axi_chip_info, 5222aee7e67SNuno Sá axi_fan_control_groups); 5238412b410SNuno Sá 5248412b410SNuno Sá return PTR_ERR_OR_ZERO(ctl->hdev); 5258412b410SNuno Sá } 5268412b410SNuno Sá 5278412b410SNuno Sá static struct platform_driver axi_fan_control_driver = { 5288412b410SNuno Sá .driver = { 5298412b410SNuno Sá .name = "axi_fan_control_driver", 5308412b410SNuno Sá .of_match_table = axi_fan_control_of_match, 5318412b410SNuno Sá }, 5328412b410SNuno Sá .probe = axi_fan_control_probe, 5338412b410SNuno Sá }; 5348412b410SNuno Sá module_platform_driver(axi_fan_control_driver); 5358412b410SNuno Sá 5368412b410SNuno Sá MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>"); 5378412b410SNuno Sá MODULE_DESCRIPTION("Analog Devices Fan Control HDL CORE driver"); 5388412b410SNuno Sá MODULE_LICENSE("GPL"); 539