Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
ee188ee
Documentation
LICENSES
arch
block
certs
crypto
drivers
accel
accessibility
acpi
amba
android
ata
atm
auxdisplay
base
bcma
block
bluetooth
bus
cdrom
cdx
char
clk
clocksource
comedi
connector
counter
cpufreq
cpuidle
crypto
cxl
dax
dca
devfreq
dio
dma-buf
dma
edac
eisa
extcon
firewire
firmware
fpga
fsi
gnss
gpio
gpu
greybus
hid
hsi
hte
hv
hwmon
hwspinlock
hwtracing
i2c
i3c
idle
iio
infiniband
input
interconnect
iommu
ipack
irqchip
isdn
leds
macintosh
mailbox
mcb
md
media
memory
memstick
message
mfd
misc
mmc
most
mtd
mux
net
nfc
ntb
nubus
nvdimm
nvme
nvmem
of
opp
parisc
parport
pci
pcmcia
peci
perf
phy
pinctrl
platform
pnp
power
powercap
pps
ps3
ptp
pwm
rapidio
ras
regulator
remoteproc
reset
rpmsg
rtc
s390
sbus
scsi
sh
siox
slimbus
soc
soundwire
spi
spmi
ssb
staging
target
tc
tee
thermal
broadcom
intel
int340x_thermal
Kconfig
Makefile
intel_bxt_pmic_thermal.c
intel_hfi.c
intel_hfi.h
intel_pch_thermal.c
intel_powerclamp.c
intel_quark_dts_thermal.c
intel_soc_dts_iosf.c
intel_soc_dts_iosf.h
intel_soc_dts_thermal.c
intel_tcc.c
intel_tcc_cooling.c
therm_throt.c
thermal_interrupt.h
x86_pkg_temp_thermal.c
mediatek
qcom
samsung
st
tegra
ti-soc-thermal
Kconfig
Makefile
amlogic_thermal.c
armada_thermal.c
cpufreq_cooling.c
cpuidle_cooling.c
da9062-thermal.c
db8500_thermal.c
devfreq_cooling.c
dove_thermal.c
gov_bang_bang.c
gov_fair_share.c
gov_power_allocator.c
gov_step_wise.c
gov_user_space.c
hisi_thermal.c
imx8mm_thermal.c
imx_sc_thermal.c
imx_thermal.c
k3_bandgap.c
k3_j72xx_bandgap.c
khadas_mcu_fan.c
kirkwood_thermal.c
max77620_thermal.c
qoriq_thermal.c
rcar_gen3_thermal.c
rcar_thermal.c
rockchip_thermal.c
rzg2l_thermal.c
spear_thermal.c
sprd_thermal.c
sun8i_thermal.c
thermal-generic-adc.c
thermal_acpi.c
thermal_core.c
thermal_core.h
thermal_helpers.c
thermal_hwmon.c
thermal_hwmon.h
thermal_mmio.c
thermal_netlink.c
thermal_netlink.h
thermal_of.c
thermal_sysfs.c
thermal_trace.h
thermal_trace_ipa.h
thermal_trip.c
uniphier_thermal.c
thunderbolt
tty
ufs
uio
usb
vdpa
vfio
vhost
video
virt
virtio
vlynq
w1
watchdog
xen
zorro
Kconfig
Makefile
fs
include
init
io_uring
ipc
kernel
lib
mm
net
rust
samples
scripts
security
sound
tools
usr
virt
.clang-format
.cocciconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
.rustfmt.toml
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
drivers
/
thermal
/
intel
/
intel_soc_dts_iosf.c
Copy path
Blame
Blame
Latest commit
History
History
404 lines (335 loc) · 9.84 KB
Breadcrumbs
linux
/
drivers
/
thermal
/
intel
/
intel_soc_dts_iosf.c
Top
File metadata and controls
Code
Blame
404 lines (335 loc) · 9.84 KB
Raw
// SPDX-License-Identifier: GPL-2.0-only /* * intel_soc_dts_iosf.c * Copyright (c) 2015, Intel Corporation. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/bitops.h> #include <linux/intel_tcc.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <asm/iosf_mbi.h> #include "intel_soc_dts_iosf.h" #define SOC_DTS_OFFSET_ENABLE 0xB0 #define SOC_DTS_OFFSET_TEMP 0xB1 #define SOC_DTS_OFFSET_PTPS 0xB2 #define SOC_DTS_OFFSET_PTTS 0xB3 #define SOC_DTS_OFFSET_PTTSS 0xB4 #define SOC_DTS_OFFSET_PTMC 0x80 #define SOC_DTS_TE_AUX0 0xB5 #define SOC_DTS_TE_AUX1 0xB6 #define SOC_DTS_AUX0_ENABLE_BIT BIT(0) #define SOC_DTS_AUX1_ENABLE_BIT BIT(1) #define SOC_DTS_CPU_MODULE0_ENABLE_BIT BIT(16) #define SOC_DTS_CPU_MODULE1_ENABLE_BIT BIT(17) #define SOC_DTS_TE_SCI_ENABLE BIT(9) #define SOC_DTS_TE_SMI_ENABLE BIT(10) #define SOC_DTS_TE_MSI_ENABLE BIT(11) #define SOC_DTS_TE_APICA_ENABLE BIT(14) #define SOC_DTS_PTMC_APIC_DEASSERT_BIT BIT(4) /* DTS encoding for TJ MAX temperature */ #define SOC_DTS_TJMAX_ENCODING 0x7F /* Mask for two trips in status bits */ #define SOC_DTS_TRIP_MASK 0x03 static int update_trip_temp(struct intel_soc_dts_sensors *sensors, int thres_index, int temp) { int status; u32 temp_out; u32 out; unsigned long update_ptps; u32 store_ptps; u32 store_ptmc; u32 store_te_out; u32 te_out; u32 int_enable_bit = SOC_DTS_TE_APICA_ENABLE; if (sensors->intr_type == INTEL_SOC_DTS_INTERRUPT_MSI) int_enable_bit |= SOC_DTS_TE_MSI_ENABLE; temp_out = (sensors->tj_max - temp) / 1000; status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, SOC_DTS_OFFSET_PTPS, &store_ptps); if (status) return status; update_ptps = store_ptps; bitmap_set_value8(&update_ptps, temp_out & 0xFF, thres_index * 8); out = update_ptps; status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, SOC_DTS_OFFSET_PTPS, out); if (status) return status; pr_debug("update_trip_temp PTPS = %x\n", out); status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, SOC_DTS_OFFSET_PTMC, &out); if (status) goto err_restore_ptps; store_ptmc = out; status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, SOC_DTS_TE_AUX0 + thres_index, &te_out); if (status) goto err_restore_ptmc; store_te_out = te_out; /* Enable for CPU module 0 and module 1 */ out |= (SOC_DTS_CPU_MODULE0_ENABLE_BIT | SOC_DTS_CPU_MODULE1_ENABLE_BIT); if (temp) { if (thres_index) out |= SOC_DTS_AUX1_ENABLE_BIT; else out |= SOC_DTS_AUX0_ENABLE_BIT; te_out |= int_enable_bit; } else { if (thres_index) out &= ~SOC_DTS_AUX1_ENABLE_BIT; else out &= ~SOC_DTS_AUX0_ENABLE_BIT; te_out &= ~int_enable_bit; } status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, SOC_DTS_OFFSET_PTMC, out); if (status) goto err_restore_te_out; status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, SOC_DTS_TE_AUX0 + thres_index, te_out); if (status) goto err_restore_te_out; return 0; err_restore_te_out: iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, SOC_DTS_OFFSET_PTMC, store_te_out); err_restore_ptmc: iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, SOC_DTS_OFFSET_PTMC, store_ptmc); err_restore_ptps: iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, SOC_DTS_OFFSET_PTPS, store_ptps); /* Nothing we can do if restore fails */ return status; } static int configure_trip(struct intel_soc_dts_sensor_entry *dts, int thres_index, enum thermal_trip_type trip_type, int temp) { int ret; ret = update_trip_temp(dts->sensors, thres_index, temp); if (ret) return ret; dts->trips[thres_index].temperature = temp; dts->trips[thres_index].type = trip_type; return 0; } static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp) { struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd); struct intel_soc_dts_sensors *sensors = dts->sensors; int status; if (temp > sensors->tj_max) return -EINVAL; mutex_lock(&sensors->dts_update_lock); status = update_trip_temp(sensors, trip, temp); mutex_unlock(&sensors->dts_update_lock); return status; } static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) { int status; u32 out; struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd); struct intel_soc_dts_sensors *sensors; unsigned long raw; sensors = dts->sensors; status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, SOC_DTS_OFFSET_TEMP, &out); if (status) return status; raw = out; out = bitmap_get_value8(&raw, dts->id * 8) - SOC_DTS_TJMAX_ENCODING; *temp = sensors->tj_max - out * 1000; return 0; } static struct thermal_zone_device_ops tzone_ops = { .get_temp = sys_get_curr_temp, .set_trip_temp = sys_set_trip_temp, }; static int soc_dts_enable(int id) { u32 out; int ret; ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, SOC_DTS_OFFSET_ENABLE, &out); if (ret) return ret; if (!(out & BIT(id))) { out |= BIT(id); ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, SOC_DTS_OFFSET_ENABLE, out); if (ret) return ret; } return ret; } static void remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry *dts) { iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, SOC_DTS_OFFSET_ENABLE, dts->store_status); thermal_zone_device_unregister(dts->tzone); } static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts, bool critical_trip) { int writable_trip_cnt = SOC_MAX_DTS_TRIPS; char name[10]; unsigned long trip; int trip_mask; unsigned long ptps; u32 store_ptps; unsigned long i; int ret; /* Store status to restor on exit */ ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, SOC_DTS_OFFSET_ENABLE, &dts->store_status); if (ret) goto err_ret; dts->id = id; if (critical_trip) writable_trip_cnt--; trip_mask = GENMASK(writable_trip_cnt - 1, 0); /* Check if the writable trip we provide is not used by BIOS */ ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, SOC_DTS_OFFSET_PTPS, &store_ptps); if (ret) trip_mask = 0; else { ptps = store_ptps; for_each_set_clump8(i, trip, &ptps, writable_trip_cnt * 8) trip_mask &= ~BIT(i / 8); } dts->trip_mask = trip_mask; snprintf(name, sizeof(name), "soc_dts%d", id); dts->tzone = thermal_zone_device_register_with_trips(name, dts->trips, SOC_MAX_DTS_TRIPS, trip_mask, dts, &tzone_ops, NULL, 0, 0); if (IS_ERR(dts->tzone)) { ret = PTR_ERR(dts->tzone); goto err_ret; } ret = thermal_zone_device_enable(dts->tzone); if (ret) goto err_enable; ret = soc_dts_enable(id); if (ret) goto err_enable; return 0; err_enable: thermal_zone_device_unregister(dts->tzone); err_ret: return ret; } void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors) { u32 sticky_out; int status; u32 ptmc_out; unsigned long flags; spin_lock_irqsave(&sensors->intr_notify_lock, flags); status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, SOC_DTS_OFFSET_PTMC, &ptmc_out); ptmc_out |= SOC_DTS_PTMC_APIC_DEASSERT_BIT; status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, SOC_DTS_OFFSET_PTMC, ptmc_out); status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, SOC_DTS_OFFSET_PTTSS, &sticky_out); pr_debug("status %d PTTSS %x\n", status, sticky_out); if (sticky_out & SOC_DTS_TRIP_MASK) { int i; /* reset sticky bit */ status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, SOC_DTS_OFFSET_PTTSS, sticky_out); spin_unlock_irqrestore(&sensors->intr_notify_lock, flags); for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { pr_debug("TZD update for zone %d\n", i); thermal_zone_device_update(sensors->soc_dts[i].tzone, THERMAL_EVENT_UNSPECIFIED); } } else spin_unlock_irqrestore(&sensors->intr_notify_lock, flags); } EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_interrupt_handler); static void dts_trips_reset(struct intel_soc_dts_sensors *sensors, int dts_index) { configure_trip(&sensors->soc_dts[dts_index], 0, 0, 0); configure_trip(&sensors->soc_dts[dts_index], 1, 0, 0); } struct intel_soc_dts_sensors * intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type, bool critical_trip, int crit_offset) { struct intel_soc_dts_sensors *sensors; int tj_max; int ret; int i; if (!iosf_mbi_available()) return ERR_PTR(-ENODEV); tj_max = intel_tcc_get_tjmax(-1); if (tj_max < 0) return ERR_PTR(tj_max); sensors = kzalloc(sizeof(*sensors), GFP_KERNEL); if (!sensors) return ERR_PTR(-ENOMEM); spin_lock_init(&sensors->intr_notify_lock); mutex_init(&sensors->dts_update_lock); sensors->intr_type = intr_type; sensors->tj_max = tj_max * 1000; for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { enum thermal_trip_type trip_type; int temp; sensors->soc_dts[i].sensors = sensors; ret = configure_trip(&sensors->soc_dts[i], 0, THERMAL_TRIP_PASSIVE, 0); if (ret) goto err_reset_trips; if (critical_trip) { trip_type = THERMAL_TRIP_CRITICAL; temp = sensors->tj_max - crit_offset; } else { trip_type = THERMAL_TRIP_PASSIVE; temp = 0; } ret = configure_trip(&sensors->soc_dts[i], 1, trip_type, temp); if (ret) goto err_reset_trips; } for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { ret = add_dts_thermal_zone(i, &sensors->soc_dts[i], critical_trip); if (ret) goto err_remove_zone; } return sensors; err_remove_zone: for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) remove_dts_thermal_zone(&sensors->soc_dts[i]); err_reset_trips: for (i = 0; i < SOC_MAX_DTS_SENSORS; i++) dts_trips_reset(sensors, i); kfree(sensors); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_init); void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors) { int i; for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { remove_dts_thermal_zone(&sensors->soc_dts[i]); dts_trips_reset(sensors, i); } kfree(sensors); } EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit); MODULE_IMPORT_NS(INTEL_TCC); MODULE_LICENSE("GPL v2");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
You can’t perform that action at this time.