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