hc
2025-02-14 bbb9540dc49f70f6b703d1c8d1b85fa5f602d86e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 */
 
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/thermal.h>
 
struct thermal_mmio {
   void __iomem *mmio_base;
   u32 (*read_mmio)(void __iomem *mmio_base);
   u32 mask;
   int factor;
};
 
static u32 thermal_mmio_readb(void __iomem *mmio_base)
{
   return readb(mmio_base);
}
 
static int thermal_mmio_get_temperature(void *private, int *temp)
{
   int t;
   struct thermal_mmio *sensor =
       (struct thermal_mmio *)private;
 
   t = sensor->read_mmio(sensor->mmio_base) & sensor->mask;
   t *= sensor->factor;
 
   *temp = t;
 
   return 0;
}
 
static struct thermal_zone_of_device_ops thermal_mmio_ops = {
   .get_temp = thermal_mmio_get_temperature,
};
 
static int thermal_mmio_probe(struct platform_device *pdev)
{
   struct resource *resource;
   struct thermal_mmio *sensor;
   int (*sensor_init_func)(struct platform_device *pdev,
               struct thermal_mmio *sensor);
   struct thermal_zone_device *thermal_zone;
   int ret;
   int temperature;
 
   sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL);
   if (!sensor)
       return -ENOMEM;
 
   resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
   sensor->mmio_base = devm_ioremap_resource(&pdev->dev, resource);
   if (IS_ERR(sensor->mmio_base)) {
       dev_err(&pdev->dev, "failed to ioremap memory (%ld)\n",
           PTR_ERR(sensor->mmio_base));
       return PTR_ERR(sensor->mmio_base);
   }
 
   sensor_init_func = device_get_match_data(&pdev->dev);
   if (sensor_init_func) {
       ret = sensor_init_func(pdev, sensor);
       if (ret) {
           dev_err(&pdev->dev,
               "failed to initialize sensor (%d)\n",
               ret);
           return ret;
       }
   }
 
   thermal_zone = devm_thermal_zone_of_sensor_register(&pdev->dev,
                               0,
                               sensor,
                               &thermal_mmio_ops);
   if (IS_ERR(thermal_zone)) {
       dev_err(&pdev->dev,
           "failed to register sensor (%ld)\n",
           PTR_ERR(thermal_zone));
       return PTR_ERR(thermal_zone);
   }
 
   thermal_mmio_get_temperature(sensor, &temperature);
   dev_info(&pdev->dev,
        "thermal mmio sensor %s registered, current temperature: %d\n",
        pdev->name, temperature);
 
   return 0;
}
 
static int al_thermal_init(struct platform_device *pdev,
              struct thermal_mmio *sensor)
{
   sensor->read_mmio = thermal_mmio_readb;
   sensor->mask = 0xff;
   sensor->factor = 1000;
 
   return 0;
}
 
static const struct of_device_id thermal_mmio_id_table[] = {
   { .compatible = "amazon,al-thermal", .data = al_thermal_init},
   {}
};
MODULE_DEVICE_TABLE(of, thermal_mmio_id_table);
 
static struct platform_driver thermal_mmio_driver = {
   .probe = thermal_mmio_probe,
   .driver = {
       .name = "thermal-mmio",
       .of_match_table = of_match_ptr(thermal_mmio_id_table),
   },
};
 
module_platform_driver(thermal_mmio_driver);
 
MODULE_AUTHOR("Talel Shenhar <talel@amazon.com>");
MODULE_DESCRIPTION("Thermal MMIO Driver");
MODULE_LICENSE("GPL v2");