Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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");