#include #include // readl_relaxed, writel_relaxed #include MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Tango CPU throttling"); /*** CPU TEMPERATURE SENSOR ***/ #define SENSOR_ADDR 0x920100 static void __iomem *sensor_base; #define TEMPSI_CMD sensor_base + 0 #define TEMPSI_RES sensor_base + 4 #define TEMPSI_CFG sensor_base + 8 static const u8 temperature[] = { 46, 51, 55, 60, 64, 69, 74, 79, 83, 88, 93, 97, 101, 106, 110, 115, 120, 124, 129, 133, 137, }; static int tango_get_temp(struct thermal_zone_device *tz, unsigned long *res) { int i; for (i = 20; i < 40; ++i) { writel_relaxed(i << 8 | 2, TEMPSI_CMD); while ((readl_relaxed(TEMPSI_CMD) & 0x80) == 0); if (readl_relaxed(TEMPSI_RES) == 0) break; } *res = temperature[i-20] * 1000; return 0; } static int tango_bind(struct thermal_zone_device *tz, struct thermal_cooling_device *cdev) { return thermal_zone_bind_cooling_device(tz, 0, cdev, 4, 1); } static int tango_get_trip_type(struct thermal_zone_device *tz, int idx, enum thermal_trip_type *res) { if (idx != 0) return -EINVAL; *res = THERMAL_TRIP_PASSIVE; return 0; } static int tango_get_trip_temp(struct thermal_zone_device *tz, int idx, unsigned long *res) { if (idx != 0) return -EINVAL; *res = 70000; return 0; } static struct thermal_zone_device_ops ops = { .bind = tango_bind, .get_temp = tango_get_temp, .get_mode = 0, .get_trip_type = tango_get_trip_type, .get_trip_temp = tango_get_trip_temp, }; static struct thermal_cooling_device *cdev; static struct thermal_zone_device *tzdev; static int ts_init(void) { sensor_base = ioremap(SENSOR_ADDR, 16); writel_relaxed( 1, TEMPSI_CMD); writel_relaxed(50, TEMPSI_CFG); cdev = cpufreq_cooling_register(cpu_present_mask); tzdev = thermal_zone_device_register("tango_tz", 1, 0, NULL, &ops, NULL, 5000, 13000); return 0; } static void __exit ts_cleanup(void) { return; } module_init(ts_init); module_exit(ts_cleanup);