1 /* board-coreprimeve3g-thermistor.c
3 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/gfp.h>
13 #include <linux/err.h>
14 #include <linux/sec_thermistor.h>
15 #include <soc/sprd/adc.h>
17 static struct sec_therm_adc_table temp_table_ap[] = {
18 /* adc, temperature */
49 static struct sec_therm_adc_table temp_table_battery[] = {
50 /* adc, temperature */
82 static struct sec_therm_adc_table temp_table_xo[] = {
83 /* adc, temperature */
112 static struct sec_therm_adc_table temp_table_default[] = {
113 /* adc, temperature */
139 struct sec_therm_adc_info kiran_adc_list[] = {
141 .therm_id = SEC_THERM_BATTERY,
142 .name = "batt_therm",
144 .adc_ch = ADC_CHANNEL_1,
147 .therm_id = SEC_THERM_XO,
150 .adc_ch = ADC_CHANNEL_2,
153 .therm_id = SEC_THERM_AP,
156 .adc_ch = ADC_CHANNEL_3,
160 static int sec_therm_temp_table_init(struct sec_therm_adc_info *adc_info)
162 if (unlikely(!adc_info))
165 switch (adc_info->therm_id) {
167 adc_info->temp_table = temp_table_ap;
168 adc_info->temp_table_size = ARRAY_SIZE(temp_table_ap);
170 case SEC_THERM_BATTERY:
171 adc_info->temp_table = temp_table_battery;
172 adc_info->temp_table_size = ARRAY_SIZE(temp_table_battery);
175 adc_info->temp_table = temp_table_xo;
176 adc_info->temp_table_size = ARRAY_SIZE(temp_table_xo);
180 case SEC_THERM_FLASH:
181 adc_info->temp_table = temp_table_default;
182 adc_info->temp_table_size = ARRAY_SIZE(temp_table_default);
191 static int sec_therm_parse_dt(struct device_node *node,
192 struct sec_therm_adc_info *adc_list)
194 struct device_node *child = NULL;
197 for_each_child_of_node(node, child) {
198 int therm_id, therm_adc_ch;
199 const char *therm_name, *therm_adc_name;
201 therm_name = child->name;
203 pr_err("%s: Failed to get thermistor name\n", __func__);
207 ret = of_property_read_u32(child, "sec,therm-id", &therm_id);
209 pr_err("%s: Failed to get thermistor id\n", __func__);
213 therm_adc_name = of_get_property(child, "sec,therm-adc-name", NULL);
214 if (!therm_adc_name) {
215 pr_err("%s: Failed to get adc name\n", __func__);
219 ret = of_property_read_u32(child, "sec,therm-adc-ch", &therm_adc_ch);
221 pr_err("%s: Failed to get thermistor adc channel\n", __func__);
225 pr_info("%s: name:%s, therm_id:%d, adc_name:%s, adc_ch:0x%x\n",
226 __func__, therm_name, therm_id, therm_adc_name, therm_adc_ch);
228 adc_list[i].name = therm_name;
229 adc_list[i].therm_id = therm_id;
230 adc_list[i].adc_name = therm_adc_name;
231 adc_list[i].adc_ch = therm_adc_ch;
238 int sec_therm_adc_read(struct sec_therm_info *info, int therm_id, int *val)
240 struct sec_therm_adc_info *adc_info = NULL;
244 if (unlikely(!info || !val))
247 for (i = 0; i < info->adc_list_size; i++) {
248 if (therm_id == info->adc_list[i].therm_id) {
249 adc_info = &info->adc_list[i];
255 pr_err("%s: Failed to found therm_id %d\n", __func__, therm_id);
259 adc_data = sci_adc_get_value(adc_info->adc_ch, false);
261 pr_err("%s: Failed to read adc channel: %d (%d)\n",
262 __func__, adc_info->adc_ch, ret);
270 int sec_therm_adc_init(struct platform_device *pdev)
272 struct sec_therm_info *info = platform_get_drvdata(pdev);
273 struct sec_therm_adc_info *adc_list = NULL;
274 int adc_list_size = 0;
277 /* device tree support */
278 if (pdev->dev.of_node) {
279 struct device_node *node = pdev->dev.of_node;
280 struct device_node *child;
282 for_each_child_of_node(node, child)
285 if (adc_list_size <= 0) {
286 pr_err("%s: No adc channel info\n", __func__);
290 adc_list = devm_kzalloc(&pdev->dev,
291 sizeof(struct sec_therm_adc_info) * adc_list_size, GFP_KERNEL);
293 pr_err("%s: Failed to allocate memory\n", __func__);
297 ret = sec_therm_parse_dt(node, adc_list);
299 pr_err("%s: Failed to parse dt (%d)\n", __func__, ret);
303 adc_list = kiran_adc_list;
304 adc_list_size = ARRAY_SIZE(kiran_adc_list);
306 for (i = 0; i < adc_list_size; i++) {
307 pr_info("%s: name:%s, therm_id:%d, adc_name:%s, adc_ch:0x%x\n",
309 adc_list[i].name, adc_list[i].therm_id,
310 adc_list[i].adc_name, adc_list[i].adc_ch);
314 for (i = 0; i < adc_list_size; i++) {
315 ret = sec_therm_temp_table_init(&adc_list[i]);
317 pr_err("%s: Failed to init %d adc_temp_table\n",
318 __func__, adc_list[i].therm_id);
323 info->adc_list = adc_list;
324 info->adc_list_size = adc_list_size;
329 devm_kfree(&pdev->dev, adc_list);
333 void sec_therm_adc_exit(struct platform_device *pdev)
335 struct sec_therm_info *info = platform_get_drvdata(pdev);
340 if (pdev->dev.of_node && info->adc_list)
341 devm_kfree(&pdev->dev, info->adc_list);