diff --git a/arch/arm/boot/dts/amlogic/meson8b_m200.dts b/arch/arm/boot/dts/amlogic/meson8b_m200.dts index 353ff97e1f9a..8e33fecea7e3 100644 --- a/arch/arm/boot/dts/amlogic/meson8b_m200.dts +++ b/arch/arm/boot/dts/amlogic/meson8b_m200.dts @@ -244,6 +244,109 @@ pinctrl-0=<&hdmi_cec_1>; reg = <0xc8100000 0x200>; }; + + aml_sensor0: aml-sensor@0 { + compatible = "amlogic, aml-thermal"; + device_name = "thermal"; + #thermal-sensor-cells = <1>; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <768000>; + dyn_coeff = <110>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <318>; + dyn_coeff = <437>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + thermal-zones { + soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1350>; + + thermal-sensors = <&aml_sensor0 3>; + + trips { + switch_on: trip-point@0 { + temperature = <70000>; + hysteresis = <1000>; + type = "passive"; + }; + control: trip-point@1 { + temperature = <80000>; + hysteresis = <1000>; + type = "passive"; + }; + hot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + critical: trip-point@3 { + temperature = <260000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&control>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&control>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&control>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&control>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + }; }; &uart_AO { diff --git a/arch/arm/boot/dts/amlogic/meson8b_m400.dts b/arch/arm/boot/dts/amlogic/meson8b_m400.dts index fbdfea9398f4..68860f72711d 100644 --- a/arch/arm/boot/dts/amlogic/meson8b_m400.dts +++ b/arch/arm/boot/dts/amlogic/meson8b_m400.dts @@ -183,6 +183,169 @@ */ }; }; + cpufreq-meson{ + compatible = "amlogic, cpufreq-meson"; + status = "okay"; + fixpll_target = <1536000>; + clocks = <&clkc CLKID_CPUCLK>, + <&clkc CLKID_PLL_SYS>; + clock-names = "cpu_clk", "sys_clk"; + opp_table = < + /* frequent(Khz) uV */ + 96000 860000 + 312000 860000 + 504000 860000 + 600000 860000 + 720000 860000 + 816000 900000 + 1008000 1140000 + 1200000 1140000 + 1320000 1140000 + 1488000 1140000 + 1536000 1140000 + >; + }; + + dvfs { + compatible = "amlogic, amlogic-dvfs"; + status = "okay"; + vcck_dvfs { + dvfs_id = <1>; + }; + }; + + pmu { + compatible = "amlogic, aml_pmu_prober"; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + aml1218 { + compatible = "amlogic, amlogic_pmu"; + sub_type = "aml1218_pmu"; + i2c_bus = "i2c_bus_ao"; + slave_address = <0x35>; + status = "okay"; + }; + }; + + aocec: aocec{ + compatible = "amlogic, amlogic-aocec"; + device_name = "aocec"; + status = "okay"; + vendor_id = <0x000000>; + cec_osd_string = "MBox"; /* Max Chars: 14 */ + cec_version = <6>; /* 5: 1.4, 6: 2.0 */ + port_num = <1>; + arc_port_mask = <0x0>; + interrupts = <0 151 1>; + interrupt-names = "hdmi_aocec"; + pinctrl-names = "hdmi_cec_1"; + pinctrl-0=<&hdmi_cec_1>; + reg = <0xc8100000 0x200>; + }; + + aml_sensor0: aml-sensor@0 { + compatible = "amlogic, aml-thermal"; + device_name = "thermal"; + #thermal-sensor-cells = <1>; + cooling_devices { + cpufreq_cool_cluster0 { + min_state = <768000>; + dyn_coeff = <110>; + cluster_id = <0>; + node_name = "cpufreq_cool0"; + device_type = "cpufreq"; + }; + cpucore_cool_cluster0 { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "cpucore_cool0"; + device_type = "cpucore"; + }; + gpufreq_cool { + min_state = <318>; + dyn_coeff = <437>; + cluster_id = <0>; + node_name = "gpufreq_cool0"; + device_type = "gpufreq"; + }; + gpucore_cool { + min_state = <1>; + dyn_coeff = <0>; + cluster_id = <0>; + node_name = "gpucore_cool0"; + device_type = "gpucore"; + }; + }; + cpufreq_cool0:cpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + cpucore_cool0:cpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpufreq_cool0:gpufreq_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + gpucore_cool0:gpucore_cool0 { + #cooling-cells = <2>; /* min followed by max */ + }; + }; + thermal-zones { + soc_thermal { + polling-delay = <1000>; + polling-delay-passive = <100>; + sustainable-power = <1350>; + + thermal-sensors = <&aml_sensor0 3>; + + trips { + switch_on: trip-point@0 { + temperature = <70000>; + hysteresis = <1000>; + type = "passive"; + }; + control: trip-point@1 { + temperature = <80000>; + hysteresis = <1000>; + type = "passive"; + }; + hot: trip-point@2 { + temperature = <85000>; + hysteresis = <5000>; + type = "hot"; + }; + critical: trip-point@3 { + temperature = <260000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + cpufreq_cooling_map { + trip = <&control>; + cooling-device = <&cpufreq_cool0 0 4>; + contribution = <1024>; + }; + cpucore_cooling_map { + trip = <&control>; + cooling-device = <&cpucore_cool0 0 3>; + contribution = <1024>; + }; + gpufreq_cooling_map { + trip = <&control>; + cooling-device = <&gpufreq_cool0 0 4>; + contribution = <1024>; + }; + gpucore_cooling_map { + trip = <&control>; + cooling-device = <&gpucore_cool0 0 2>; + contribution = <1024>; + }; + }; + }; + }; }; &uart_AO { diff --git a/arch/arm/configs/meson32_defconfig b/arch/arm/configs/meson32_defconfig index f92b68df8fc9..4b4bd887a0c1 100644 --- a/arch/arm/configs/meson32_defconfig +++ b/arch/arm/configs/meson32_defconfig @@ -60,15 +60,20 @@ CONFIG_AMLOGIC_CLK=y CONFIG_AMLOGIC_M8B_CLK=y CONFIG_AMLOGIC_CRYPTO=y CONFIG_AMLOGIC_CRYPTO_BLKMV=y +CONFIG_AMLOGIC_INPUT=y +CONFIG_AMLOGIC_SARADC=y CONFIG_AMLOGIC_EFUSE=y CONFIG_AMLOGIC_CPU_HOTPLUG=y CONFIG_AMLOGIC_PWM=y -CONFIG_AMLOGIC_INPUT=y -CONFIG_AMLOGIC_SARADC=y CONFIG_AMLOGIC_MMC=y CONFIG_AMLOGIC_M8B_MMC=y CONFIG_AMLOGIC_CEC=y CONFIG_AMLOGIC_M8B_CEC=y +CONFIG_AMLOGIC_TEMP_SENSOR=y +CONFIG_AMLOGIC_M8B_TEMP_SENSOR=y +CONFIG_AMLOGIC_CPUCORE_THERMAL=y +CONFIG_AMLOGIC_GPU_THERMAL=y +CONFIG_AMLOGIC_GPUCORE_THERMAL=y CONFIG_AMLOGIC_POWER=y CONFIG_AMLOGIC_PMU_OF=y CONFIG_AMLOGIC_PMU=y @@ -100,6 +105,11 @@ CONFIG_POWER_RESET_GPIO=y CONFIG_POWER_RESET_GPIO_RESTART=y CONFIG_POWER_RESET_SYSCON=y CONFIG_POWER_SUPPLY=y +CONFIG_THERMAL=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_CPU_THERMAL=y CONFIG_WATCHDOG=y CONFIG_WATCHDOG_CORE=y CONFIG_BCMA=y diff --git a/drivers/amlogic/thermal/Kconfig b/drivers/amlogic/thermal/Kconfig index 861cf1777e68..b5305f0af8af 100644 --- a/drivers/amlogic/thermal/Kconfig +++ b/drivers/amlogic/thermal/Kconfig @@ -6,6 +6,7 @@ menu "Amlogic temperature sensor" config AMLOGIC_TEMP_SENSOR bool "Amlgoic temperature sensor Support" + depends on THERMAL default n ---help--- Thermal sensor low level support for thermal @@ -14,6 +15,24 @@ config AMLOGIC_TEMP_SENSOR If you wan this driver, selest it. +config AMLOGIC_M8B_TEMP_SENSOR + bool "Amlgoic temperature sensor Support for M8 chips" + depends on AMLOGIC_TEMP_SENSOR + depends on MACH_MESON8B + default n + help + this config enables thermal driver for M8/M8baby chips. + Say Y if you want this driver. + +config AMLOGIC_GX_TEMP_SENSOR + bool "Amlgoic temperature sensor Support for GX chips" + depends on AMLOGIC_TEMP_SENSOR + depends on ARM64 + default y + help + this config enables thermal driver for GX/GXB/GXL/GXM chips. + Say Y if you want this driver. + config AMLOGIC_CPUCORE_THERMAL bool "generic cpu core cooling support" depends on AMLOGIC_TEMP_SENSOR diff --git a/drivers/amlogic/thermal/Makefile b/drivers/amlogic/thermal/Makefile index 79cd77a8991e..1599773a5584 100644 --- a/drivers/amlogic/thermal/Makefile +++ b/drivers/amlogic/thermal/Makefile @@ -1,5 +1,6 @@ -obj-$(CONFIG_AMLOGIC_TEMP_SENSOR) += aml_thermal_hw.o +obj-$(CONFIG_AMLOGIC_GX_TEMP_SENSOR) += aml_thermal_hw.o +obj-$(CONFIG_AMLOGIC_M8B_TEMP_SENSOR) += aml_thermal_hw_m8b.o obj-$(CONFIG_AMLOGIC_CPUCORE_THERMAL) += cpucore_cooling.o obj-$(CONFIG_AMLOGIC_GPU_THERMAL) += gpu_cooling.o obj-$(CONFIG_AMLOGIC_GPUCORE_THERMAL) += gpucore_cooling.o diff --git a/drivers/amlogic/thermal/aml_thermal_hw_m8b.c b/drivers/amlogic/thermal/aml_thermal_hw_m8b.c new file mode 100644 index 000000000000..cb2cced95160 --- /dev/null +++ b/drivers/amlogic/thermal/aml_thermal_hw_m8b.c @@ -0,0 +1,442 @@ +/* + * drivers/amlogic/thermal/aml_thermal_hw_m8b.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NOT_WRITE_EFUSE 0x0 +#define EFUEE_PRIVATE 0x4 +#define EFUSE_OPS 0xa + +#define TEMP_ADC_CHANNEL 6 +#define TEMP_NOT_TRIMMED (-1000) +#define TEMP_ADC_ERROR (-1001) + +enum cluster_type { + CLUSTER_BIG = 0, + CLUSTER_LITTLE, + NUM_CLUSTERS +}; + +enum cool_dev_type { + COOL_DEV_TYPE_CPU_FREQ = 0, + COOL_DEV_TYPE_CPU_CORE, + COOL_DEV_TYPE_GPU_FREQ, + COOL_DEV_TYPE_GPU_CORE, + COOL_DEV_TYPE_MAX +}; + +struct cool_dev { + int min_state; + int coeff; + int cluster_id; + char *device_type; + struct device_node *np; + struct thermal_cooling_device *cooling_dev; +}; + +struct aml_thermal_sensor { + bool chip_trimmed : 1; + bool adc_flag : 1; + unsigned int fix_value : 12; + unsigned int extra_flag : 4; + unsigned int ts_c : 5; + unsigned int cool_dev_num : 9; + struct cpumask mask[NUM_CLUSTERS]; + struct cool_dev *cool_devs; + struct thermal_zone_device *tzd; +}; + +static struct aml_thermal_sensor soc_sensor; + +int thermal_firmware_init(void) +{ + int err = 0; + unsigned char buf[4] = {0}; + int temp; + + err = efuse_read_intlItem("temper_cvbs", buf, 4); + if (err >= 0) { + pr_info("efuse buf:%02x %02x %02x %02x, err=%d\n", + buf[0], buf[1], buf[2], buf[3], err); + temp = (buf[1] << 8) | buf[0]; + soc_sensor.ts_c = temp & 0x1F; + soc_sensor.adc_flag = (temp & 0x8000) >> 15; + soc_sensor.fix_value = (temp & 0x7fff) >> 5; + soc_sensor.extra_flag = (buf[3] >> 4) & 0xf; + pr_info("adc:%d, ts_c:%d, flag:%d, ext_flag:%x\n", + soc_sensor.fix_value, soc_sensor.ts_c, + soc_sensor.adc_flag, soc_sensor.extra_flag); + if ((soc_sensor.extra_flag == EFUEE_PRIVATE) || + (soc_sensor.extra_flag == EFUSE_OPS)) { + if (soc_sensor.adc_flag) + soc_sensor.chip_trimmed = 1; + } else + soc_sensor.chip_trimmed = 0; + } + if (soc_sensor.chip_trimmed) { + temp_sensor_adc_init(soc_sensor.ts_c); + return 0; + } else + return -1; + +} +EXPORT_SYMBOL(thermal_firmware_init); + +int get_cpu_temp(void) +{ + int ret = TEMP_NOT_TRIMMED, tempa; + + if (soc_sensor.chip_trimmed) { + ret = get_adc_sample(0, TEMP_ADC_CHANNEL); + if (ret >= 0) { + tempa = (10 * (ret - soc_sensor.fix_value)) / 32 + 27; + ret = tempa; + } else + ret = TEMP_ADC_ERROR; + } + return ret; +} +EXPORT_SYMBOL(get_cpu_temp); + +static int get_cur_temp(void *data, int *temp) +{ + int val; + + val = get_cpu_temp(); + if (val == -1000) + return -EINVAL; + + *temp = val * 1000; + + return 0; +} + +static int get_cool_dev_type(char *type) +{ + if (!strcmp(type, "cpufreq")) + return COOL_DEV_TYPE_CPU_FREQ; + if (!strcmp(type, "cpucore")) + return COOL_DEV_TYPE_CPU_CORE; + if (!strcmp(type, "gpufreq")) + return COOL_DEV_TYPE_GPU_FREQ; + if (!strcmp(type, "gpucore")) + return COOL_DEV_TYPE_GPU_CORE; + return COOL_DEV_TYPE_MAX; +} + +static struct cool_dev *get_cool_dev_by_node(struct device_node *np) +{ + int i; + struct cool_dev *dev; + + if (!np) + return NULL; + for (i = 0; i < soc_sensor.cool_dev_num; i++) { + dev = &soc_sensor.cool_devs[i]; + if (dev->np == np) + return dev; + } + return NULL; +} + +int aml_thermal_min_update(struct thermal_cooling_device *cdev) +{ + struct gpufreq_cooling_device *gf_cdev; + struct gpucore_cooling_device *gc_cdev; + struct cool_dev *cool; + long min_state; + int i; + int cpu, c_id; + + cool = get_cool_dev_by_node(cdev->np); + if (!cool) + return -ENODEV; + + if (cool->cooling_dev == NULL) + cool->cooling_dev = cdev; + + if (cool->min_state == 0) + return 0; + + switch (get_cool_dev_type(cool->device_type)) { + case COOL_DEV_TYPE_CPU_CORE: + /* TODO: cluster ID */ + cool->cooling_dev->ops->get_max_state(cdev, &min_state); + min_state = min_state - cool->min_state; + break; + + case COOL_DEV_TYPE_CPU_FREQ: + for_each_possible_cpu(cpu) { + if (mc_capable()) + c_id = topology_physical_package_id(cpu); + else + c_id = 0; /* force cluster 0 if no MC */ + if (c_id == cool->cluster_id) + break; + } + min_state = cpufreq_cooling_get_level(cpu, cool->min_state); + break; + + case COOL_DEV_TYPE_GPU_CORE: + gc_cdev = (struct gpucore_cooling_device *)cdev->devdata; + cdev->ops->get_max_state(cdev, &min_state); + min_state = min_state - cool->min_state; + break; + + case COOL_DEV_TYPE_GPU_FREQ: + gf_cdev = (struct gpufreq_cooling_device *)cdev->devdata; + min_state = gf_cdev->get_gpu_freq_level(cool->min_state); + break; + + default: + return -EINVAL; + } + + for (i = 0; i < soc_sensor.tzd->trips; i++) + thermal_set_upper(soc_sensor.tzd, cdev, i, min_state); + + return 0; +} +EXPORT_SYMBOL(aml_thermal_min_update); + +int set_cur_mode(struct thermal_zone_device *tzd, enum thermal_device_mode mode) +{ + int i, ret = 0; + struct thermal_cooling_device *cdev; + + /* + * each cooling device should return to max state if thermal is disalbed + */ + if (mode != THERMAL_DEVICE_DISABLED) + return 0; + + for (i = 0; i < soc_sensor.cool_dev_num; i++) { + cdev = soc_sensor.cool_devs[i].cooling_dev; + if (cdev) + ret |= cdev->ops->set_cur_state(cdev, 0); + } + return ret; +} + +static struct thermal_zone_of_device_ops aml_thermal_ops = { + .get_temp = get_cur_temp, + .set_mode = set_cur_mode, +}; + +static int register_cool_dev(struct cool_dev *cool) +{ + int pp; + int id = cool->cluster_id; + struct cpumask *mask; + + switch (get_cool_dev_type(cool->device_type)) { + case COOL_DEV_TYPE_CPU_CORE: + cool->cooling_dev = cpucore_cooling_register(cool->np, + cool->cluster_id); + break; + + case COOL_DEV_TYPE_CPU_FREQ: + mask = &soc_sensor.mask[id]; + cool->cooling_dev = of_cpufreq_power_cooling_register(cool->np, + mask, + cool->coeff, + NULL); + break; + + /* GPU is KO, just save these parameters */ + case COOL_DEV_TYPE_GPU_FREQ: + if (of_property_read_u32(cool->np, "num_of_pp", &pp)) + pr_err("thermal: read num_of_pp failed\n"); + save_gpu_cool_para(cool->coeff, cool->np, pp); + return 0; + + case COOL_DEV_TYPE_GPU_CORE: + save_gpucore_thermal_para(cool->np); + return 0; + + default: + pr_err("thermal: unknown type:%s\n", cool->device_type); + return -EINVAL; + } + + if (IS_ERR(cool->cooling_dev)) { + pr_err("thermal: register %s failed\n", cool->device_type); + return -EINVAL; + } + return 0; +} + +static int parse_cool_device(struct device_node *np) +{ + int i, temp, ret = 0; + struct cool_dev *cool; + struct device_node *node, *child; + const char *str; + + child = of_get_next_child(np, NULL); + for (i = 0; i < soc_sensor.cool_dev_num; i++) { + cool = &soc_sensor.cool_devs[i]; + if (child == NULL) + break; + if (of_property_read_u32(child, "min_state", &temp)) + pr_err("thermal: read min_state failed\n"); + else + cool->min_state = temp; + + if (of_property_read_u32(child, "dyn_coeff", &temp)) + pr_err("thermal: read dyn_coeff failed\n"); + else + cool->coeff = temp; + + if (of_property_read_u32(child, "cluster_id", &temp)) + pr_err("thermal: read cluster_id failed\n"); + else + cool->cluster_id = temp; + + if (of_property_read_string(child, "device_type", &str)) + pr_err("thermal: read device_type failed\n"); + else + cool->device_type = (char *)str; + + if (of_property_read_string(child, "node_name", &str)) + pr_err("thermal: read node_name failed\n"); + else { + node = of_find_node_by_name(NULL, str); + if (!node) + pr_err("thermal: can't find node\n"); + cool->np = node; + } + if (cool->np) + ret += register_cool_dev(cool); + child = of_get_next_child(np, child); + } + return ret; +} + +static int aml_thermal_probe(struct platform_device *pdev) +{ + int cpu, i, c_id; + struct device_node *np, *child; + struct cool_dev *cool; + struct cpufreq_policy *policy; + + memset(&soc_sensor, 0, sizeof(struct aml_thermal_sensor)); + policy = cpufreq_cpu_get(0); + if (!policy || !policy->freq_table) { + dev_info(&pdev->dev, + "Frequency policy not init. Deferring probe...\n"); + return -EPROBE_DEFER; + } + + if (thermal_firmware_init() < 0) { + dev_err(&pdev->dev, "chip is not trimmed, disable thermal\n"); + return -EINVAL; + } + + for_each_possible_cpu(cpu) { + if (mc_capable()) + c_id = topology_physical_package_id(cpu); + else + c_id = CLUSTER_BIG; /* Always cluster 0 if no mc */ + if (c_id > NUM_CLUSTERS) { + pr_err("Cluster id: %d > %d\n", c_id, NUM_CLUSTERS); + return -EINVAL; + } + cpumask_set_cpu(cpu, &soc_sensor.mask[c_id]); + } + + np = pdev->dev.of_node; + child = of_get_child_by_name(np, "cooling_devices"); + if (child == NULL) { + pr_err("thermal: can't found cooling_devices\n"); + return -EINVAL; + } + soc_sensor.cool_dev_num = of_get_child_count(child); + i = sizeof(struct cool_dev) * soc_sensor.cool_dev_num; + soc_sensor.cool_devs = kzalloc(i, GFP_KERNEL); + if (soc_sensor.cool_devs == NULL) { + pr_err("thermal: alloc mem failed\n"); + return -ENOMEM; + } + + if (parse_cool_device(child)) + return -EINVAL; + + soc_sensor.tzd = thermal_zone_of_sensor_register(&pdev->dev, + 3, + &soc_sensor, + &aml_thermal_ops); + + if (IS_ERR(soc_sensor.tzd)) { + dev_warn(&pdev->dev, "Error registering sensor: %p\n", + soc_sensor.tzd); + return PTR_ERR(soc_sensor.tzd); + } + + /* update min state for each device */ + for (i = 0; i < soc_sensor.cool_dev_num; i++) { + cool = &soc_sensor.cool_devs[i]; + if (cool->cooling_dev) + aml_thermal_min_update(cool->cooling_dev); + } + thermal_zone_device_update(soc_sensor.tzd, THERMAL_EVENT_UNSPECIFIED); + + return 0; +} + +static int aml_thermal_remove(struct platform_device *pdev) +{ + kfree(soc_sensor.cool_devs); + return 0; +} + +static const struct of_device_id aml_thermal_of_match[] = { + { .compatible = "amlogic, aml-thermal" }, + {}, +}; + +static struct platform_driver aml_thermal_platdrv = { + .driver = { + .name = "aml-thermal", + .owner = THIS_MODULE, + .of_match_table = aml_thermal_of_match, + }, + .probe = aml_thermal_probe, + .remove = aml_thermal_remove, +}; + + +static int __init aml_thermal_platdrv_init(void) +{ + return platform_driver_register(&(aml_thermal_platdrv)); +} +late_initcall(aml_thermal_platdrv_init); diff --git a/drivers/amlogic/thermal/cpucore_cooling.c b/drivers/amlogic/thermal/cpucore_cooling.c index 93d4b4fa2f43..f3c0f8c4a9c4 100644 --- a/drivers/amlogic/thermal/cpucore_cooling.c +++ b/drivers/amlogic/thermal/cpucore_cooling.c @@ -24,6 +24,7 @@ #include #include #include +#include /** * struct cpucore_cooling_device - data for cooling device with cpucore diff --git a/include/linux/amlogic/aml_thermal_hw.h b/include/linux/amlogic/aml_thermal_hw.h index 4fc18da001cd..872b06212b0b 100644 --- a/include/linux/amlogic/aml_thermal_hw.h +++ b/include/linux/amlogic/aml_thermal_hw.h @@ -17,6 +17,11 @@ #ifndef ARCH__THERMAL_H__ #define ARCH__THERMAL_H__ + +#ifndef mc_capable +#define mc_capable() 0 +#endif + struct thermal_cooling_device; extern int thermal_firmware_init(void); extern int get_cpu_temp(void);