0001
0002
0003 #include <linux/bitfield.h>
0004 #include <linux/clk.h>
0005 #include <linux/hwmon.h>
0006 #include <linux/kernel.h>
0007 #include <linux/module.h>
0008 #include <linux/mod_devicetable.h>
0009 #include <linux/platform_device.h>
0010 #include <linux/polynomial.h>
0011 #include <linux/regmap.h>
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 static const struct polynomial poly_N_to_temp = {
0036 .terms = {
0037 {4, -34627, 1000, 1},
0038 {3, 110230, 1000, 1},
0039 {2, -191650, 1000, 1},
0040 {1, 306040, 1000, 1},
0041 {0, -56197, 1, 1}
0042 }
0043 };
0044
0045 #define PVT_SENSOR_CTRL 0x0
0046 #define PVT_SENSOR_CFG 0x4
0047 #define SENSOR_CFG_CLK_CFG GENMASK(27, 20)
0048 #define SENSOR_CFG_TRIM_VAL GENMASK(13, 9)
0049 #define SENSOR_CFG_SAMPLE_ENA BIT(8)
0050 #define SENSOR_CFG_START_CAPTURE BIT(7)
0051 #define SENSOR_CFG_CONTINIOUS_MODE BIT(6)
0052 #define SENSOR_CFG_PSAMPLE_ENA GENMASK(1, 0)
0053 #define PVT_SENSOR_STAT 0x8
0054 #define SENSOR_STAT_DATA_VALID BIT(10)
0055 #define SENSOR_STAT_DATA GENMASK(9, 0)
0056
0057 #define FAN_CFG 0x0
0058 #define FAN_CFG_DUTY_CYCLE GENMASK(23, 16)
0059 #define INV_POL BIT(3)
0060 #define GATE_ENA BIT(2)
0061 #define PWM_OPEN_COL_ENA BIT(1)
0062 #define FAN_STAT_CFG BIT(0)
0063 #define FAN_PWM_FREQ 0x4
0064 #define FAN_PWM_CYC_10US GENMASK(25, 15)
0065 #define FAN_PWM_FREQ_FREQ GENMASK(14, 0)
0066 #define FAN_CNT 0xc
0067 #define FAN_CNT_DATA GENMASK(15, 0)
0068
0069 #define LAN966X_PVT_CLK 1200000
0070
0071 struct lan966x_hwmon {
0072 struct regmap *regmap_pvt;
0073 struct regmap *regmap_fan;
0074 struct clk *clk;
0075 unsigned long clk_rate;
0076 };
0077
0078 static int lan966x_hwmon_read_temp(struct device *dev, long *val)
0079 {
0080 struct lan966x_hwmon *hwmon = dev_get_drvdata(dev);
0081 unsigned int data;
0082 int ret;
0083
0084 ret = regmap_read(hwmon->regmap_pvt, PVT_SENSOR_STAT, &data);
0085 if (ret < 0)
0086 return ret;
0087
0088 if (!(data & SENSOR_STAT_DATA_VALID))
0089 return -ENODATA;
0090
0091 *val = polynomial_calc(&poly_N_to_temp,
0092 FIELD_GET(SENSOR_STAT_DATA, data));
0093
0094 return 0;
0095 }
0096
0097 static int lan966x_hwmon_read_fan(struct device *dev, long *val)
0098 {
0099 struct lan966x_hwmon *hwmon = dev_get_drvdata(dev);
0100 unsigned int data;
0101 int ret;
0102
0103 ret = regmap_read(hwmon->regmap_fan, FAN_CNT, &data);
0104 if (ret < 0)
0105 return ret;
0106
0107
0108
0109
0110
0111 *val = FIELD_GET(FAN_CNT_DATA, data) * 60 / 2;
0112
0113 return 0;
0114 }
0115
0116 static int lan966x_hwmon_read_pwm(struct device *dev, long *val)
0117 {
0118 struct lan966x_hwmon *hwmon = dev_get_drvdata(dev);
0119 unsigned int data;
0120 int ret;
0121
0122 ret = regmap_read(hwmon->regmap_fan, FAN_CFG, &data);
0123 if (ret < 0)
0124 return ret;
0125
0126 *val = FIELD_GET(FAN_CFG_DUTY_CYCLE, data);
0127
0128 return 0;
0129 }
0130
0131 static int lan966x_hwmon_read_pwm_freq(struct device *dev, long *val)
0132 {
0133 struct lan966x_hwmon *hwmon = dev_get_drvdata(dev);
0134 unsigned long tmp;
0135 unsigned int data;
0136 int ret;
0137
0138 ret = regmap_read(hwmon->regmap_fan, FAN_PWM_FREQ, &data);
0139 if (ret < 0)
0140 return ret;
0141
0142
0143
0144
0145
0146 data = FIELD_GET(FAN_PWM_FREQ_FREQ, data) + 1;
0147 tmp = DIV_ROUND_CLOSEST(hwmon->clk_rate, 256);
0148 *val = DIV_ROUND_CLOSEST(tmp, data);
0149
0150 return 0;
0151 }
0152
0153 static int lan966x_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
0154 u32 attr, int channel, long *val)
0155 {
0156 switch (type) {
0157 case hwmon_temp:
0158 return lan966x_hwmon_read_temp(dev, val);
0159 case hwmon_fan:
0160 return lan966x_hwmon_read_fan(dev, val);
0161 case hwmon_pwm:
0162 switch (attr) {
0163 case hwmon_pwm_input:
0164 return lan966x_hwmon_read_pwm(dev, val);
0165 case hwmon_pwm_freq:
0166 return lan966x_hwmon_read_pwm_freq(dev, val);
0167 default:
0168 return -EOPNOTSUPP;
0169 }
0170 default:
0171 return -EOPNOTSUPP;
0172 }
0173 }
0174
0175 static int lan966x_hwmon_write_pwm(struct device *dev, long val)
0176 {
0177 struct lan966x_hwmon *hwmon = dev_get_drvdata(dev);
0178
0179 if (val < 0 || val > 255)
0180 return -EINVAL;
0181
0182 return regmap_update_bits(hwmon->regmap_fan, FAN_CFG,
0183 FAN_CFG_DUTY_CYCLE,
0184 FIELD_PREP(FAN_CFG_DUTY_CYCLE, val));
0185 }
0186
0187 static int lan966x_hwmon_write_pwm_freq(struct device *dev, long val)
0188 {
0189 struct lan966x_hwmon *hwmon = dev_get_drvdata(dev);
0190
0191 if (val <= 0)
0192 return -EINVAL;
0193
0194 val = DIV_ROUND_CLOSEST(hwmon->clk_rate, val);
0195 val = DIV_ROUND_CLOSEST(val, 256) - 1;
0196 val = clamp_val(val, 0, FAN_PWM_FREQ_FREQ);
0197
0198 return regmap_update_bits(hwmon->regmap_fan, FAN_PWM_FREQ,
0199 FAN_PWM_FREQ_FREQ,
0200 FIELD_PREP(FAN_PWM_FREQ_FREQ, val));
0201 }
0202
0203 static int lan966x_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
0204 u32 attr, int channel, long val)
0205 {
0206 switch (type) {
0207 case hwmon_pwm:
0208 switch (attr) {
0209 case hwmon_pwm_input:
0210 return lan966x_hwmon_write_pwm(dev, val);
0211 case hwmon_pwm_freq:
0212 return lan966x_hwmon_write_pwm_freq(dev, val);
0213 default:
0214 return -EOPNOTSUPP;
0215 }
0216 default:
0217 return -EOPNOTSUPP;
0218 }
0219 }
0220
0221 static umode_t lan966x_hwmon_is_visible(const void *data,
0222 enum hwmon_sensor_types type,
0223 u32 attr, int channel)
0224 {
0225 umode_t mode = 0;
0226
0227 switch (type) {
0228 case hwmon_temp:
0229 switch (attr) {
0230 case hwmon_temp_input:
0231 mode = 0444;
0232 break;
0233 default:
0234 break;
0235 }
0236 break;
0237 case hwmon_fan:
0238 switch (attr) {
0239 case hwmon_fan_input:
0240 mode = 0444;
0241 break;
0242 default:
0243 break;
0244 }
0245 break;
0246 case hwmon_pwm:
0247 switch (attr) {
0248 case hwmon_pwm_input:
0249 case hwmon_pwm_freq:
0250 mode = 0644;
0251 break;
0252 default:
0253 break;
0254 }
0255 break;
0256 default:
0257 break;
0258 }
0259
0260 return mode;
0261 }
0262
0263 static const struct hwmon_channel_info *lan966x_hwmon_info[] = {
0264 HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
0265 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
0266 HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT),
0267 HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_FREQ),
0268 NULL
0269 };
0270
0271 static const struct hwmon_ops lan966x_hwmon_ops = {
0272 .is_visible = lan966x_hwmon_is_visible,
0273 .read = lan966x_hwmon_read,
0274 .write = lan966x_hwmon_write,
0275 };
0276
0277 static const struct hwmon_chip_info lan966x_hwmon_chip_info = {
0278 .ops = &lan966x_hwmon_ops,
0279 .info = lan966x_hwmon_info,
0280 };
0281
0282 static void lan966x_hwmon_disable(void *data)
0283 {
0284 struct lan966x_hwmon *hwmon = data;
0285
0286 regmap_update_bits(hwmon->regmap_pvt, PVT_SENSOR_CFG,
0287 SENSOR_CFG_SAMPLE_ENA | SENSOR_CFG_CONTINIOUS_MODE,
0288 0);
0289 }
0290
0291 static int lan966x_hwmon_enable(struct device *dev,
0292 struct lan966x_hwmon *hwmon)
0293 {
0294 unsigned int mask = SENSOR_CFG_CLK_CFG |
0295 SENSOR_CFG_SAMPLE_ENA |
0296 SENSOR_CFG_START_CAPTURE |
0297 SENSOR_CFG_CONTINIOUS_MODE |
0298 SENSOR_CFG_PSAMPLE_ENA;
0299 unsigned int val;
0300 unsigned int div;
0301 int ret;
0302
0303
0304 val = SENSOR_CFG_SAMPLE_ENA | SENSOR_CFG_CONTINIOUS_MODE;
0305
0306
0307 div = DIV_ROUND_CLOSEST(hwmon->clk_rate, LAN966X_PVT_CLK);
0308 val |= FIELD_PREP(SENSOR_CFG_CLK_CFG, div);
0309
0310 ret = regmap_update_bits(hwmon->regmap_pvt, PVT_SENSOR_CFG,
0311 mask, val);
0312 if (ret)
0313 return ret;
0314
0315 return devm_add_action_or_reset(dev, lan966x_hwmon_disable, hwmon);
0316 }
0317
0318 static struct regmap *lan966x_init_regmap(struct platform_device *pdev,
0319 const char *name)
0320 {
0321 struct regmap_config regmap_config = {
0322 .reg_bits = 32,
0323 .reg_stride = 4,
0324 .val_bits = 32,
0325 };
0326 void __iomem *base;
0327
0328 base = devm_platform_ioremap_resource_byname(pdev, name);
0329 if (IS_ERR(base))
0330 return ERR_CAST(base);
0331
0332 regmap_config.name = name;
0333
0334 return devm_regmap_init_mmio(&pdev->dev, base, ®map_config);
0335 }
0336
0337 static void lan966x_clk_disable(void *data)
0338 {
0339 struct lan966x_hwmon *hwmon = data;
0340
0341 clk_disable_unprepare(hwmon->clk);
0342 }
0343
0344 static int lan966x_clk_enable(struct device *dev, struct lan966x_hwmon *hwmon)
0345 {
0346 int ret;
0347
0348 ret = clk_prepare_enable(hwmon->clk);
0349 if (ret)
0350 return ret;
0351
0352 return devm_add_action_or_reset(dev, lan966x_clk_disable, hwmon);
0353 }
0354
0355 static int lan966x_hwmon_probe(struct platform_device *pdev)
0356 {
0357 struct device *dev = &pdev->dev;
0358 struct lan966x_hwmon *hwmon;
0359 struct device *hwmon_dev;
0360 int ret;
0361
0362 hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL);
0363 if (!hwmon)
0364 return -ENOMEM;
0365
0366 hwmon->clk = devm_clk_get(dev, NULL);
0367 if (IS_ERR(hwmon->clk))
0368 return dev_err_probe(dev, PTR_ERR(hwmon->clk),
0369 "failed to get clock\n");
0370
0371 ret = lan966x_clk_enable(dev, hwmon);
0372 if (ret)
0373 return dev_err_probe(dev, ret, "failed to enable clock\n");
0374
0375 hwmon->clk_rate = clk_get_rate(hwmon->clk);
0376
0377 hwmon->regmap_pvt = lan966x_init_regmap(pdev, "pvt");
0378 if (IS_ERR(hwmon->regmap_pvt))
0379 return dev_err_probe(dev, PTR_ERR(hwmon->regmap_pvt),
0380 "failed to get regmap for PVT registers\n");
0381
0382 hwmon->regmap_fan = lan966x_init_regmap(pdev, "fan");
0383 if (IS_ERR(hwmon->regmap_fan))
0384 return dev_err_probe(dev, PTR_ERR(hwmon->regmap_fan),
0385 "failed to get regmap for fan registers\n");
0386
0387 ret = lan966x_hwmon_enable(dev, hwmon);
0388 if (ret)
0389 return dev_err_probe(dev, ret, "failed to enable sensor\n");
0390
0391 hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev,
0392 "lan966x_hwmon", hwmon,
0393 &lan966x_hwmon_chip_info, NULL);
0394 if (IS_ERR(hwmon_dev))
0395 return dev_err_probe(dev, PTR_ERR(hwmon_dev),
0396 "failed to register hwmon device\n");
0397
0398 return 0;
0399 }
0400
0401 static const struct of_device_id lan966x_hwmon_of_match[] = {
0402 { .compatible = "microchip,lan9668-hwmon" },
0403 {}
0404 };
0405 MODULE_DEVICE_TABLE(of, lan966x_hwmon_of_match);
0406
0407 static struct platform_driver lan966x_hwmon_driver = {
0408 .probe = lan966x_hwmon_probe,
0409 .driver = {
0410 .name = "lan966x-hwmon",
0411 .of_match_table = lan966x_hwmon_of_match,
0412 },
0413 };
0414 module_platform_driver(lan966x_hwmon_driver);
0415
0416 MODULE_DESCRIPTION("LAN966x Hardware Monitoring Driver");
0417 MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
0418 MODULE_LICENSE("GPL");