1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2019 Antmicro <www.antmicro.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
22 #include <linux/hwmon.h>
23 #include <linux/litex.h>
25 #define TEMP_REG_OFFSET 0x0
26 #define TEMP_REG_SIZE 2
27 #define VCCINT_REG_OFFSET 0x8
28 #define VCCINT_REG_SIZE 2
29 #define VCCAUX_REG_OFFSET 0x10
30 #define VCCAUX_REG_SIZE 2
31 #define VCCBRAM_REG_OFFSET 0x18
32 #define VCCBRAM_REG_SIZE 2
34 #define CHANNEL_TEMP 0
35 #define CHANNEL_VCCINT 0
36 #define CHANNEL_VCCAUX 1
37 #define CHANNEL_VCCBRAM 2
40 void __iomem
*membase
;
44 /* Transfer functions taken from XILINX UG480 (v1.10.1)
45 * www.xilinx.com/support/documentation/user_guides/ug480_7Series_XADC.pdf
48 static inline long litex_temp_transfer_fun(long val
)
50 return ((val
* 503975ULL) / 4096ULL) - 273150ULL;
53 static inline long litex_supp_transfer_fun(long val
)
55 return ((val
* 3000) / 4096);
58 static inline int litex_read_temp(struct litex_hwmon
*hwmon_s
, u32 attr
,
59 int channel
, long *val
)
61 unsigned long raw_data
;
63 if (attr
!= hwmon_temp_input
)
66 if (channel
!= CHANNEL_TEMP
)
69 raw_data
= litex_read16(hwmon_s
->membase
+ TEMP_REG_OFFSET
);
70 *val
= litex_temp_transfer_fun(raw_data
);
74 static inline int litex_read_in(struct litex_hwmon
*hwmon_s
, u32 attr
,
75 int channel
, long *val
)
78 unsigned long raw_data
;
80 if (attr
!= hwmon_in_input
)
85 offset
= VCCINT_REG_OFFSET
;
88 offset
= VCCAUX_REG_OFFSET
;
91 offset
= VCCBRAM_REG_OFFSET
;
97 raw_data
= litex_read16(hwmon_s
->membase
+ offset
);
98 *val
= litex_supp_transfer_fun(raw_data
);
104 umode_t
litex_hwmon_is_visible(const void *drvdata
,
105 enum hwmon_sensor_types type
,
106 u32 attr
, int channel
)
111 int litex_hwmon_read(struct device
*dev
, enum hwmon_sensor_types type
,
112 u32 attr
, int channel
, long *val
)
114 struct litex_hwmon
*hwmon_s
= dev_get_drvdata(dev
);
118 return litex_read_temp(hwmon_s
, attr
, channel
, val
);
120 return litex_read_in(hwmon_s
, attr
, channel
, val
);
128 static const struct hwmon_ops litex_hwmon_ops
= {
129 .is_visible
= litex_hwmon_is_visible
,
130 .read
= litex_hwmon_read
,
133 /* Attribute management */
135 static const unsigned int litex_temp_config
[] = {
140 static const struct hwmon_channel_info litex_hwmon_temp
= {
142 .config
= litex_temp_config
145 static const unsigned int litex_vcc_config
[] = {
152 static const struct hwmon_channel_info litex_hwmon_vcc
= {
154 .config
= litex_vcc_config
157 static const struct hwmon_channel_info
*litex_hwmon_channel_info
[] = {
163 static const struct hwmon_chip_info litex_chip_info
= {
164 .ops
= &litex_hwmon_ops
,
165 .info
= litex_hwmon_channel_info
168 /* Driver functions */
170 static int litex_hwmon_probe(struct platform_device
*pdev
)
172 struct device_node
*node
= pdev
->dev
.of_node
;
173 struct litex_hwmon
*hwmon_s
;
174 struct resource
*res
;
179 hwmon_s
= devm_kzalloc(&pdev
->dev
, sizeof(*hwmon_s
), GFP_KERNEL
);
183 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
187 hwmon_s
->membase
= devm_of_iomap(&pdev
->dev
, node
, 0, &res
->end
);
188 if (IS_ERR_OR_NULL(hwmon_s
->membase
))
191 hwmon_s
->hdev
= devm_hwmon_device_register_with_info(&pdev
->dev
,
196 platform_set_drvdata(pdev
, hwmon_s
);
197 return PTR_ERR_OR_ZERO(hwmon_s
->hdev
);
200 static const struct of_device_id litex_of_match
[] = {
201 {.compatible
= "litex,hwmon-xadc"},
205 MODULE_DEVICE_TABLE(of
, litex_of_match
);
207 static struct platform_driver litex_hwmon_driver
= {
209 .name
= "litex-hwmon",
210 .of_match_table
= of_match_ptr(litex_of_match
)
212 .probe
= litex_hwmon_probe
,
215 module_platform_driver(litex_hwmon_driver
);