0001
0002
0003
0004
0005
0006 #include <linux/module.h>
0007 #include <linux/of_address.h>
0008 #include <linux/platform_device.h>
0009 #include <linux/thermal.h>
0010
0011 struct thermal_mmio {
0012 void __iomem *mmio_base;
0013 u32 (*read_mmio)(void __iomem *mmio_base);
0014 u32 mask;
0015 int factor;
0016 };
0017
0018 static u32 thermal_mmio_readb(void __iomem *mmio_base)
0019 {
0020 return readb(mmio_base);
0021 }
0022
0023 static int thermal_mmio_get_temperature(void *private, int *temp)
0024 {
0025 int t;
0026 struct thermal_mmio *sensor =
0027 (struct thermal_mmio *)private;
0028
0029 t = sensor->read_mmio(sensor->mmio_base) & sensor->mask;
0030 t *= sensor->factor;
0031
0032 *temp = t;
0033
0034 return 0;
0035 }
0036
0037 static const struct thermal_zone_of_device_ops thermal_mmio_ops = {
0038 .get_temp = thermal_mmio_get_temperature,
0039 };
0040
0041 static int thermal_mmio_probe(struct platform_device *pdev)
0042 {
0043 struct resource *resource;
0044 struct thermal_mmio *sensor;
0045 int (*sensor_init_func)(struct platform_device *pdev,
0046 struct thermal_mmio *sensor);
0047 struct thermal_zone_device *thermal_zone;
0048 int ret;
0049 int temperature;
0050
0051 sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL);
0052 if (!sensor)
0053 return -ENOMEM;
0054
0055 resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0056 sensor->mmio_base = devm_ioremap_resource(&pdev->dev, resource);
0057 if (IS_ERR(sensor->mmio_base))
0058 return PTR_ERR(sensor->mmio_base);
0059
0060 sensor_init_func = device_get_match_data(&pdev->dev);
0061 if (sensor_init_func) {
0062 ret = sensor_init_func(pdev, sensor);
0063 if (ret) {
0064 dev_err(&pdev->dev,
0065 "failed to initialize sensor (%d)\n",
0066 ret);
0067 return ret;
0068 }
0069 }
0070
0071 thermal_zone = devm_thermal_zone_of_sensor_register(&pdev->dev,
0072 0,
0073 sensor,
0074 &thermal_mmio_ops);
0075 if (IS_ERR(thermal_zone)) {
0076 dev_err(&pdev->dev,
0077 "failed to register sensor (%ld)\n",
0078 PTR_ERR(thermal_zone));
0079 return PTR_ERR(thermal_zone);
0080 }
0081
0082 thermal_mmio_get_temperature(sensor, &temperature);
0083 dev_info(&pdev->dev,
0084 "thermal mmio sensor %s registered, current temperature: %d\n",
0085 pdev->name, temperature);
0086
0087 return 0;
0088 }
0089
0090 static int al_thermal_init(struct platform_device *pdev,
0091 struct thermal_mmio *sensor)
0092 {
0093 sensor->read_mmio = thermal_mmio_readb;
0094 sensor->mask = 0xff;
0095 sensor->factor = 1000;
0096
0097 return 0;
0098 }
0099
0100 static const struct of_device_id thermal_mmio_id_table[] = {
0101 { .compatible = "amazon,al-thermal", .data = al_thermal_init},
0102 {}
0103 };
0104 MODULE_DEVICE_TABLE(of, thermal_mmio_id_table);
0105
0106 static struct platform_driver thermal_mmio_driver = {
0107 .probe = thermal_mmio_probe,
0108 .driver = {
0109 .name = "thermal-mmio",
0110 .of_match_table = of_match_ptr(thermal_mmio_id_table),
0111 },
0112 };
0113
0114 module_platform_driver(thermal_mmio_driver);
0115
0116 MODULE_AUTHOR("Talel Shenhar <talel@amazon.com>");
0117 MODULE_DESCRIPTION("Thermal MMIO Driver");
0118 MODULE_LICENSE("GPL v2");