[PATCH v2] cpufreq: nforce2: Remove meaningless return
Delete a line of meaningless return and some useless blank lines. In a function whose return type is void, returning on the last line is not required. Signed-off-by: Yangtao Li --- Changes in v2: -revert modify of MODULE_ -delete some blank lines --- drivers/cpufreq/cpufreq-nforce2.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c index dbf82f36d270..33c309a08c64 100644 --- a/drivers/cpufreq/cpufreq-nforce2.c +++ b/drivers/cpufreq/cpufreq-nforce2.c @@ -123,8 +123,6 @@ static void nforce2_write_pll(int pll) /* Now write the value in all 64 registers */ for (temp = 0; temp <= 0x3f; temp++) pci_write_config_dword(nforce2_dev, NFORCE2_PLLREG, pll); - - return; } /** @@ -438,4 +436,3 @@ static void __exit nforce2_exit(void) module_init(nforce2_init); module_exit(nforce2_exit); - -- 2.17.0
[PATCH 4/4] dmaengine: qcom_hidma: convert to DEFINE_SHOW_ATTRIBUTE
Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Yangtao Li Acked-by: Sinan Kaya --- drivers/dma/qcom/hidma_dbg.c | 33 ++--- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/drivers/dma/qcom/hidma_dbg.c b/drivers/dma/qcom/hidma_dbg.c index 3bdcb8056a36..9523faf7acdc 100644 --- a/drivers/dma/qcom/hidma_dbg.c +++ b/drivers/dma/qcom/hidma_dbg.c @@ -85,11 +85,11 @@ static void hidma_ll_devstats(struct seq_file *s, void *llhndl) } /* - * hidma_chan_stats: display HIDMA channel statistics + * hidma_chan_show: display HIDMA channel statistics * * Display the statistics for the current HIDMA virtual channel device. */ -static int hidma_chan_stats(struct seq_file *s, void *unused) +static int hidma_chan_show(struct seq_file *s, void *unused) { struct hidma_chan *mchan = s->private; struct hidma_desc *mdesc; @@ -117,11 +117,11 @@ static int hidma_chan_stats(struct seq_file *s, void *unused) } /* - * hidma_dma_info: display HIDMA device info + * hidma_dma_show: display HIDMA device info * * Display the info for the current HIDMA device. */ -static int hidma_dma_info(struct seq_file *s, void *unused) +static int hidma_dma_show(struct seq_file *s, void *unused) { struct hidma_dev *dmadev = s->private; resource_size_t sz; @@ -138,29 +138,8 @@ static int hidma_dma_info(struct seq_file *s, void *unused) return 0; } -static int hidma_chan_stats_open(struct inode *inode, struct file *file) -{ - return single_open(file, hidma_chan_stats, inode->i_private); -} - -static int hidma_dma_info_open(struct inode *inode, struct file *file) -{ - return single_open(file, hidma_dma_info, inode->i_private); -} - -static const struct file_operations hidma_chan_fops = { - .open = hidma_chan_stats_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations hidma_dma_fops = { - .open = hidma_dma_info_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(hidma_chan); +DEFINE_SHOW_ATTRIBUTE(hidma_dma); void hidma_debug_uninit(struct hidma_dev *dmadev) { -- 2.17.0
[PATCH 3/4] dmaengine: pxa: remove DBGFS_FUNC_DECL()
We already have the DEFINE_SHOW_ATTRIBUTE, There is no need to define such a macro, so remove DBGFS_FUNC_DECL. Signed-off-by: Yangtao Li Acked-by: Robert Jarzmik --- drivers/dma/pxa_dma.c | 36 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c index 825725057e00..e78fe98b5cf1 100644 --- a/drivers/dma/pxa_dma.c +++ b/drivers/dma/pxa_dma.c @@ -189,7 +189,7 @@ bool pxad_filter_fn(struct dma_chan *chan, void *param); #include #include -static int dbg_show_requester_chan(struct seq_file *s, void *p) +static int requester_chan_show(struct seq_file *s, void *p) { struct pxad_phy *phy = s->private; int i; @@ -220,7 +220,7 @@ static int is_phys_valid(unsigned long addr) #define PXA_DCSR_STR(flag) (dcsr & PXA_DCSR_##flag ? #flag" " : "") #define PXA_DCMD_STR(flag) (dcmd & PXA_DCMD_##flag ? #flag" " : "") -static int dbg_show_descriptors(struct seq_file *s, void *p) +static int descriptors_show(struct seq_file *s, void *p) { struct pxad_phy *phy = s->private; int i, max_show = 20, burst, width; @@ -263,7 +263,7 @@ static int dbg_show_descriptors(struct seq_file *s, void *p) return 0; } -static int dbg_show_chan_state(struct seq_file *s, void *p) +static int chan_state_show(struct seq_file *s, void *p) { struct pxad_phy *phy = s->private; u32 dcsr, dcmd; @@ -306,7 +306,7 @@ static int dbg_show_chan_state(struct seq_file *s, void *p) return 0; } -static int dbg_show_state(struct seq_file *s, void *p) +static int state_show(struct seq_file *s, void *p) { struct pxad_device *pdev = s->private; @@ -317,22 +317,10 @@ static int dbg_show_state(struct seq_file *s, void *p) return 0; } -#define DBGFS_FUNC_DECL(name) \ -static int dbg_open_##name(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, dbg_show_##name, inode->i_private); \ -} \ -static const struct file_operations dbg_fops_##name = { \ - .open = dbg_open_##name, \ - .llseek = seq_lseek, \ - .read = seq_read, \ - .release= single_release, \ -} - -DBGFS_FUNC_DECL(state); -DBGFS_FUNC_DECL(chan_state); -DBGFS_FUNC_DECL(descriptors); -DBGFS_FUNC_DECL(requester_chan); +DEFINE_SHOW_ATTRIBUTE(state); +DEFINE_SHOW_ATTRIBUTE(chan_state); +DEFINE_SHOW_ATTRIBUTE(descriptors); +DEFINE_SHOW_ATTRIBUTE(requester_chan); static struct dentry *pxad_dbg_alloc_chan(struct pxad_device *pdev, int ch, struct dentry *chandir) @@ -348,13 +336,13 @@ static struct dentry *pxad_dbg_alloc_chan(struct pxad_device *pdev, if (chan) chan_state = debugfs_create_file("state", 0400, chan, dt, -_fops_chan_state); +_state_fops); if (chan_state) chan_descr = debugfs_create_file("descriptors", 0400, chan, dt, -_fops_descriptors); +_fops); if (chan_descr) chan_reqs = debugfs_create_file("requesters", 0400, chan, dt, - _fops_requester_chan); + _chan_fops); if (!chan_reqs) goto err_state; @@ -375,7 +363,7 @@ static void pxad_init_debugfs(struct pxad_device *pdev) goto err_root; pdev->dbgfs_state = debugfs_create_file("state", 0400, pdev->dbgfs_root, - pdev, _fops_state); + pdev, _fops); if (!pdev->dbgfs_state) goto err_state; -- 2.17.0
[PATCH 1/4] dmaengine: amba-pl08x: convert to DEFINE_SHOW_ATTRIBUTE
Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Yangtao Li --- drivers/dma/amba-pl08x.c | 14 ++ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 97483df1f82e..fc8c2bab563c 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -2505,24 +2505,14 @@ static int pl08x_debugfs_show(struct seq_file *s, void *data) return 0; } -static int pl08x_debugfs_open(struct inode *inode, struct file *file) -{ - return single_open(file, pl08x_debugfs_show, inode->i_private); -} - -static const struct file_operations pl08x_debugfs_operations = { - .open = pl08x_debugfs_open, - .read = seq_read, - .llseek = seq_lseek, - .release= single_release, -}; +DEFINE_SHOW_ATTRIBUTE(pl08x_debugfs); static void init_pl08x_debugfs(struct pl08x_driver_data *pl08x) { /* Expose a simple debugfs interface to view all clocks */ (void) debugfs_create_file(dev_name(>adev->dev), S_IFREG | S_IRUGO, NULL, pl08x, - _debugfs_operations); + _debugfs_fops); } #else -- 2.17.0
[PATCH 2/4] dmaengine: mic_x100_dma: convert to DEFINE_SHOW_ATTRIBUTE
Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Yangtao Li --- drivers/dma/mic_x100_dma.c | 22 +++--- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/drivers/dma/mic_x100_dma.c b/drivers/dma/mic_x100_dma.c index adfd316db1a8..6a91e28d537d 100644 --- a/drivers/dma/mic_x100_dma.c +++ b/drivers/dma/mic_x100_dma.c @@ -676,7 +676,7 @@ static void mic_dma_dev_unreg(struct mic_dma_device *mic_dma_dev) } /* DEBUGFS CODE */ -static int mic_dma_reg_seq_show(struct seq_file *s, void *pos) +static int mic_dma_reg_show(struct seq_file *s, void *pos) { struct mic_dma_device *mic_dma_dev = s->private; int i, chan_num, first_chan = mic_dma_dev->start_ch; @@ -707,23 +707,7 @@ static int mic_dma_reg_seq_show(struct seq_file *s, void *pos) return 0; } -static int mic_dma_reg_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, mic_dma_reg_seq_show, inode->i_private); -} - -static int mic_dma_reg_debug_release(struct inode *inode, struct file *file) -{ - return single_release(inode, file); -} - -static const struct file_operations mic_dma_reg_ops = { - .owner = THIS_MODULE, - .open= mic_dma_reg_debug_open, - .read= seq_read, - .llseek = seq_lseek, - .release = mic_dma_reg_debug_release -}; +DEFINE_SHOW_ATTRIBUTE(mic_dma_reg); /* Debugfs parent dir */ static struct dentry *mic_dma_dbg; @@ -747,7 +731,7 @@ static int mic_dma_driver_probe(struct mbus_device *mbdev) if (mic_dma_dev->dbg_dir) debugfs_create_file("mic_dma_reg", 0444, mic_dma_dev->dbg_dir, mic_dma_dev, - _dma_reg_ops); + _dma_reg_fops); } return 0; } -- 2.17.0
[PATCH] usb: host: isp1362-hcd: convert to DEFINE_SHOW_ATTRIBUTE
Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Yangtao Li --- drivers/usb/host/isp1362-hcd.c | 16 +++- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index b21c386e6a46..28bf8bfb091e 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2159,25 +2159,15 @@ static int isp1362_show(struct seq_file *s, void *unused) return 0; } - -static int isp1362_open(struct inode *inode, struct file *file) -{ - return single_open(file, isp1362_show, inode); -} - -static const struct file_operations debug_ops = { - .open = isp1362_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(isp1362); /* expect just one isp1362_hcd per system */ static void create_debug_file(struct isp1362_hcd *isp1362_hcd) { isp1362_hcd->debug_file = debugfs_create_file("isp1362", S_IRUGO, usb_debug_root, - isp1362_hcd, _ops); + isp1362_hcd, + _fops); } static void remove_debug_file(struct isp1362_hcd *isp1362_hcd) -- 2.17.0
[PATCH] softirq: modify comments about PF_MEMALLOC in __do_softirq
--- kernel/softirq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/softirq.c b/kernel/softirq.c index 6f584861d329..6193e1d1b30d 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -257,7 +257,7 @@ asmlinkage __visible void __softirq_entry __do_softirq(void) int softirq_bit; /* -* Mask out PF_MEMALLOC s current task context is borrowed for the +* Mask out PF_MEMALLOC as current task context is borrowed for the * softirq. A softirq handled such as network RX might set PF_MEMALLOC * again if the socket is related to swap */ -- 2.17.0
[PATCH v4 0/2] cpufreq: Add sunxi nvmem based CPU scaling driver
Add sunxi nvmem based CPU scaling driver, refers to qcom-cpufreq-kryo. Yangtao Li (2): cpufreq: Add sunxi nvmem based CPU scaling driver dt-bindings: cpufreq: Document allwinner,sun50i-h6-operating-points .../bindings/opp/sun50i-nvmem-cpufreq.txt | 167 + MAINTAINERS | 7 + drivers/cpufreq/Kconfig.arm | 12 + drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq-dt-platdev.c | 2 + drivers/cpufreq/sun50i-cpufreq-nvmem.c| 226 ++ 6 files changed, 415 insertions(+) create mode 100644 Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt create mode 100644 drivers/cpufreq/sun50i-cpufreq-nvmem.c --- v4: -I removed this sunxi_cpufreq_soc_data structure for now. -Convert to less generic name. -Update soc_bin xlate. v3: -update changelog and title -convert compatibles to allwinner,cpu-operating-points-v2 -document the valid names for opp-microvolt- v2: -update changelog -convert to dev_pm_opp_set_prop_name instead of dev_pm_opp_set_supported_hw -some change in OPP Node --- 2.17.0
[PATCH v4 1/2] cpufreq: Add sunxi nvmem based CPU scaling driver
For some SoCs, the CPU frequency subset and voltage value of each OPP varies based on the silicon variant in use. The sun50i-cpufreq-nvmem driver reads the efuse value from the SoC to provide the OPP framework with required information. Signed-off-by: Yangtao Li --- MAINTAINERS| 7 + drivers/cpufreq/Kconfig.arm| 12 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq-dt-platdev.c | 2 + drivers/cpufreq/sun50i-cpufreq-nvmem.c | 226 + 5 files changed, 248 insertions(+) create mode 100644 drivers/cpufreq/sun50i-cpufreq-nvmem.c diff --git a/MAINTAINERS b/MAINTAINERS index 3671fdea5010..4ad6dd051149 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -667,6 +667,13 @@ S: Maintained F: Documentation/i2c/busses/i2c-ali1563 F: drivers/i2c/busses/i2c-ali1563.c +ALLWINNER CPUFREQ DRIVER +M: Yangtao Li +L: linux...@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt +F: drivers/cpufreq/sun50i-cpufreq-nvmem.c + ALLWINNER SECURITY SYSTEM M: Corentin Labbe L: linux-cry...@vger.kernel.org diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 179a1d302f48..71377e01a370 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -18,6 +18,18 @@ config ACPI_CPPC_CPUFREQ If in doubt, say N. +config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM + tristate "Allwinner nvmem based SUN50I CPUFreq driver" + depends on ARCH_SUNXI + depends on NVMEM_SUNXI_SID + select PM_OPP + help + This adds the nvmem based CPUFreq driver for Allwinner + h6 SoC. + + To compile this driver as a module, choose M here: the + module will be called sun50i-cpufreq-nvmem. + config ARM_ARMADA_37XX_CPUFREQ tristate "Armada 37xx CPUFreq support" depends on ARCH_MVEBU && CPUFREQ_DT diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 689b26c6f949..a78b8da80383 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_ARM_SCMI_CPUFREQ)+= scmi-cpufreq.o obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ)+= spear-cpufreq.o obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o +obj-$(CONFIG_ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM) += sun50i-cpufreq-nvmem.o obj-$(CONFIG_ARM_TANGO_CPUFREQ)+= tango-cpufreq.o obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 47729a22c159..50e7810f3a28 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -105,6 +105,8 @@ static const struct of_device_id whitelist[] __initconst = { * platforms using "operating-points-v2" property. */ static const struct of_device_id blacklist[] __initconst = { + { .compatible = "allwinner,sun50i-h6", }, + { .compatible = "calxeda,highbank", }, { .compatible = "calxeda,ecx-2000", }, diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c new file mode 100644 index ..eca32e443716 --- /dev/null +++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Allwinner CPUFreq nvmem based driver + * + * The sun50i-cpufreq-nvmem driver reads the efuse value from the SoC to + * provide the OPP framework with required information. + * + * Copyright (C) 2019 Yangtao Li + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#define MAX_NAME_LEN 7 + +#define NVMEM_MASK 0x7 +#define NVMEM_SHIFT5 + +static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev; + +/** + * sun50i_cpufreq_get_efuse() - Parse and return efuse value present on SoC + * @versions: Set to the value parsed from efuse + * + * Returns 0 if success. + */ +static int sun50i_cpufreq_get_efuse(u32 *versions) +{ + struct nvmem_cell *speedbin_nvmem; + struct device_node *np; + struct device *cpu_dev; + u32 *speedbin, efuse_value; + size_t len; + int ret; + + cpu_dev = get_cpu_device(0); + if (!cpu_dev) + return -ENODEV; + + np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); + if (!np) + return -ENOENT; + + ret = of_device_is_compatible(np, + "allwinner,sun50i-h6-operating-points"); + if (!ret) { + of_node_put(np); + return -ENOENT; + } + + speedbin_nvmem = of_nvmem_cell_get(np, NULL); + of_node_put(np); + if
[PATCH v4 2/2] dt-bindings: cpufreq: Document allwinner,sun50i-h6-operating-points
Allwinner Process Voltage Scaling Tables defines the voltage and frequency value based on the speedbin blown in the efuse combination. The sunxi-cpufreq-nvmem driver reads the efuse value from the SoC to provide the OPP framework with required information. This is used to determine the voltage and frequency value for each OPP of operating-points-v2 table when it is parsed by the OPP framework. The "allwinner,sun50i-h6-operating-points" DT extends the "operating-points-v2" with following parameters: - nvmem-cells (NVMEM area containig the speedbin information) - opp-microvolt-: voltage in micro Volts. At runtime, the platform can pick a and matching opp-microvolt- property. HW: : sun50iw-h6 speed0 speed1 speed2 Signed-off-by: Yangtao Li --- .../bindings/opp/sun50i-nvmem-cpufreq.txt | 167 ++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt diff --git a/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt b/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt new file mode 100644 index ..3cb39c6caec3 --- /dev/null +++ b/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt @@ -0,0 +1,167 @@ +Allwinner Technologies, Inc. NVMEM CPUFreq and OPP bindings +=== + +For some SoCs, the CPU frequency subset and voltage value of each OPP +varies based on the silicon variant in use. Allwinner Process Voltage +Scaling Tables defines the voltage and frequency value based on the +speedbin blown in the efuse combination. The sun50i-cpufreq-nvmem driver +reads the efuse value from the SoC to provide the OPP framework with +required information. + +Required properties: + +In 'cpus' nodes: +- operating-points-v2: Phandle to the operating-points-v2 table to use. + +In 'operating-points-v2' table: +- compatible: Should be + - 'allwinner,sun50i-h6-operating-points'. +- nvmem-cells: A phandle pointing to a nvmem-cells node representing the + efuse registers that has information about the speedbin + that is used to select the right frequency/voltage value + pair. Please refer the for nvmem-cells bindings + Documentation/devicetree/bindings/nvmem/nvmem.txt and + also examples below. + +In every OPP node: +- opp-microvolt-: Voltage in micro Volts. + At runtime, the platform can pick a and + matching opp-microvolt- property. + [See: opp.txt] + HW: : + sun50iw-h6 speed0 speed1 speed2 + +Example 1: +- + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu2: cpu@2 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <2>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu3: cpu@3 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <3>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; +}; + +
[PATCH] PM / Domains: remove unnecessary unlikely()
WARN_ON() already contains an unlikely(), so it's not necessary to use unlikely. Signed-off-by: Yangtao Li --- drivers/base/power/domain.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 96a6dc9d305c..598a4e02aee1 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -391,11 +391,9 @@ int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state) if (unlikely(!genpd->set_performance_state)) return -EINVAL; - if (unlikely(!dev->power.subsys_data || -!dev->power.subsys_data->domain_data)) { - WARN_ON(1); + if (WARN_ON(!dev->power.subsys_data || +!dev->power.subsys_data->domain_data)) return -EINVAL; - } genpd_lock(genpd); -- 2.17.0
[RESEND] dt-bindings: cpufreq: Document allwinner,sun50i-h6-operating-points
Allwinner Process Voltage Scaling Tables defines the voltage and frequency value based on the speedbin blown in the efuse combination. The sunxi-cpufreq-nvmem driver reads the efuse value from the SoC to provide the OPP framework with required information. This is used to determine the voltage and frequency value for each OPP of operating-points-v2 table when it is parsed by the OPP framework. The "allwinner,sun50i-h6-operating-points" DT extends the "operating-points-v2" with following parameters: - nvmem-cells (NVMEM area containig the speedbin information) - opp-microvolt-: voltage in micro Volts. At runtime, the platform can pick a and matching opp-microvolt- property. HW: : sun50i-h6 speed0 speed1 speed2 Signed-off-by: Yangtao Li Acked-by: Maxime Ripard --- just fix a typo: sun50iw-h6 -> sun50i-h6 This patch is [2/2]. for [1/2]: https://patchwork.kernel.org/patch/10903381/ --- .../bindings/opp/sun50i-nvmem-cpufreq.txt | 167 ++ 1 file changed, 167 insertions(+) create mode 100644 Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt diff --git a/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt b/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt new file mode 100644 index ..7deae57a587b --- /dev/null +++ b/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt @@ -0,0 +1,167 @@ +Allwinner Technologies, Inc. NVMEM CPUFreq and OPP bindings +=== + +For some SoCs, the CPU frequency subset and voltage value of each OPP +varies based on the silicon variant in use. Allwinner Process Voltage +Scaling Tables defines the voltage and frequency value based on the +speedbin blown in the efuse combination. The sun50i-cpufreq-nvmem driver +reads the efuse value from the SoC to provide the OPP framework with +required information. + +Required properties: + +In 'cpus' nodes: +- operating-points-v2: Phandle to the operating-points-v2 table to use. + +In 'operating-points-v2' table: +- compatible: Should be + - 'allwinner,sun50i-h6-operating-points'. +- nvmem-cells: A phandle pointing to a nvmem-cells node representing the + efuse registers that has information about the speedbin + that is used to select the right frequency/voltage value + pair. Please refer the for nvmem-cells bindings + Documentation/devicetree/bindings/nvmem/nvmem.txt and + also examples below. + +In every OPP node: +- opp-microvolt-: Voltage in micro Volts. + At runtime, the platform can pick a and + matching opp-microvolt- property. + [See: opp.txt] + HW: : + sun50i-h6 speed0 speed1 speed2 + +Example 1: +- + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu2: cpu@2 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <2>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu3: cpu@3 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <3>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ +
[PATCH 2/3] thermal: sun50i: add thermal driver for h6
This patch adds the support for allwinner thermal sensor, within allwinner SoC. It will register sensors for thermal framework and use device tree to bind cooling device. Based on driver code found here: https://megous.com/git/linux and https://github.com/Allwinner-Homlet/H6-BSP4.9-linux Signed-off-by: Yangtao Li --- MAINTAINERS | 7 + drivers/thermal/Kconfig | 14 ++ drivers/thermal/Makefile | 1 + drivers/thermal/sun50i_thermal.c | 357 +++ 4 files changed, 379 insertions(+) create mode 100644 drivers/thermal/sun50i_thermal.c diff --git a/MAINTAINERS b/MAINTAINERS index 3c65228e93c5..8da56582e72a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -674,6 +674,13 @@ L: linux-cry...@vger.kernel.org S: Maintained F: drivers/crypto/sunxi-ss/ +ALLWINNER THERMAL DRIVER +M: Yangtao Li +L: linux...@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/thermal/sun50i-thermal.txt +F: drivers/thermal/sun50i_thermal.c + ALLWINNER VPU DRIVER M: Maxime Ripard M: Paul Kocialkowski diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 653aa27a25a4..2a8d1c98c6ca 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -252,6 +252,20 @@ config SPEAR_THERMAL Enable this to plug the SPEAr thermal sensor driver into the Linux thermal framework. +config SUN50I_THERMAL + tristate "Allwinner sun50i thermal driver" + depends on ARCH_SUNXI || COMPILE_TEST + depends on HAS_IOMEM + depends on NVMEM + depends on OF + depends on RESET_CONTROLLER + help + Support for the sun50i thermal sensor driver into the Linux thermal + framework. + + To compile this driver as a module, choose M here: the + module will be called sun50i-thermal. + config ROCKCHIP_THERMAL tristate "Rockchip thermal driver" depends on ARCH_ROCKCHIP || COMPILE_TEST diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 486d682be047..a09b30b90003 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -30,6 +30,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o # platform thermal drivers obj-y += broadcom/ obj-$(CONFIG_SPEAR_THERMAL)+= spear_thermal.o +obj-$(CONFIG_SUN50I_THERMAL) += sun50i_thermal.o obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o obj-$(CONFIG_RCAR_GEN3_THERMAL)+= rcar_gen3_thermal.o diff --git a/drivers/thermal/sun50i_thermal.c b/drivers/thermal/sun50i_thermal.c new file mode 100644 index ..3bdb3677b3d4 --- /dev/null +++ b/drivers/thermal/sun50i_thermal.c @@ -0,0 +1,357 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Thermal sensor driver for Allwinner SOC + * Copyright (C) 2019 Yangtao Li + * + * Based on the work of Icenowy Zheng + * Based on the work of Ondrej Jirman + * Based on the work of Josef Gajdusek + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_SENSOR_NUM 4 + +#define FT_TEMP_MASK GENMASK(11, 0) +#define TEMP_CALIB_MASKGENMASK(11, 0) +#define TEMP_TO_REG672 +#define CALIBRATE_DEFAULT 0x800 + +#define SUN50I_THS_CTRL0 0x00 +#define SUN50I_H6_THS_ENABLE 0x04 +#define SUN50I_H6_THS_PC 0x08 +#define SUN50I_H6_THS_MFC 0x30 +#define SUN50I_H6_TEMP_CALIB 0xa0 +#define SUN50I_H6_TEMP_DATA0xc0 + +#define SUN50I_THS_CTRL0_T_ACQ(x) ((GENMASK(15, 0) & (x)) << 16) +#define SUN50I_THS_FILTER_EN BIT(2) +#define SUN50I_THS_FILTER_TYPE(x) (GENMASK(1, 0) & (x)) +#define SUN50I_H6_THS_PC_TEMP_PERIOD(x)((GENMASK(19, 0) & (x)) << 12) + +/* millidegree celsius */ +#define SUN50I_H6_FT_DEVIATION 7000 + +struct tsens_device; + +struct tsensor { + struct tsens_device *tmdev; + struct thermal_zone_device *tzd; + int id; +}; + +struct sun50i_thermal_chip { + int sensor_num; + int offset; + int scale; + int ft_deviation; + int temp_calib_base; + int temp_data_base; + int (*enable)(struct tsens_device *tmdev); + int (*disable)(struct tsens_device *tmdev); +}; + + +struct tsens_device { + const struct sun50i_thermal_chip*chip; + struct device *dev; + struct regmap *regmap; + struct reset_control*reset; + struct clk *bus_clk; + st
[PATCH 3/3] dt-bindings: thermal: add binding document for h6 thermal controller
This patch adds binding document for allwinner h6 thermal controller. Signed-off-by: Yangtao Li --- .../bindings/thermal/sun50i-thermal.txt | 32 +++ 1 file changed, 32 insertions(+) create mode 100644 Documentation/devicetree/bindings/thermal/sun50i-thermal.txt diff --git a/Documentation/devicetree/bindings/thermal/sun50i-thermal.txt b/Documentation/devicetree/bindings/thermal/sun50i-thermal.txt new file mode 100644 index ..67eda7794262 --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/sun50i-thermal.txt @@ -0,0 +1,32 @@ +Binding for Thermal Sensor of Allwinner SOC. + +This describes the device tree binding for the Allwinner thermal controller +which measures the on-SoC temperatures. + +Required properties: +- compatible: + - "allwinner,sun50i-h6-ths" : For H6 +- reg: Address range of the thermal controller +- clocks, clock-names: Clocks needed for the thermal controller. + The required clocks for h6 are: "bus". +- resets, reset-names: Reference to the reset controller controlling + the thermal controller. +- nvmem-cells: A phandle to the calibration data provided by a nvmem device. If + unspecified default values shall be used. +- nvmem-cell-names: Should be "calib" +- #thermal-sensor-cells : For H6 Should be 1. + See ./thermal.txt for a description. + +Example: + + ths: ths@1c25000 { + compatible = "allwinner,sun50i-h6-ths"; + reg = <0x05070400 0x100>; + clocks = < CLK_BUS_THS>; + clock-names = "bus"; + resets = < RST_BUS_THS>; + reset-names = "bus"; + nvmem-cells = <_calib>; + nvmem-cell-names = "calib"; + #thermal-sensor-cells = <1>; + }; -- 2.17.0
[PATCH 1/3] arm64: defconfig: add allwinner sid support
Sid contains speedbin information and temperature sensor calibration information and more, which are important for SOC. This patch enables CONFIG_NVMEM_SUNXI_SID by default. Signed-off-by: Yangtao Li --- arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 2d9c39033c1a..8c23dd60f906 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -736,6 +736,7 @@ CONFIG_PHY_TEGRA_XUSB=y CONFIG_HISI_PMU=y CONFIG_QCOM_L2_PMU=y CONFIG_QCOM_L3_PMU=y +CONFIG_NVMEM_SUNXI_SID=y CONFIG_QCOM_QFPROM=y CONFIG_ROCKCHIP_EFUSE=y CONFIG_UNIPHIER_EFUSE=y -- 2.17.0
[PATCH 0/3] add thermal driver for h6
This patchset support thermal driver of allwinner H6. Yangtao Li (3): arm64: defconfig: add allwinner sid support thermal: sun50i: add thermal driver for h6 dt-bindings: thermal: add binding document for h6 thermal controller .../bindings/thermal/sun50i-thermal.txt | 32 ++ MAINTAINERS | 7 + arch/arm64/configs/defconfig | 1 + drivers/thermal/Kconfig | 14 + drivers/thermal/Makefile | 1 + drivers/thermal/sun50i_thermal.c | 357 ++ 6 files changed, 412 insertions(+) create mode 100644 Documentation/devicetree/bindings/thermal/sun50i-thermal.txt create mode 100644 drivers/thermal/sun50i_thermal.c -- 2.17.0
[PATCH] iio: adc: sun4i-gpadc-iio convert to SPDX license tags
Updates license to use SPDX-License-Identifier. Signed-off-by: Yangtao Li --- drivers/iio/adc/sun4i-gpadc-iio.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index 04d7147e0110..f13c6248a662 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* ADC driver for sunxi platforms' (A10, A13 and A31) GPADC * * Copyright (c) 2016 Quentin Schulz * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License version 2 as published by the - * Free Software Foundation. - * * The Allwinner SoCs all have an ADC that can also act as a touchscreen * controller and a thermal sensor. * The thermal sensor works only when the ADC acts as a touchscreen controller -- 2.17.0
[PATCH] arm64: dts: allwinner: h6: Enable HDMI output on orangepi 3
Orangepi 3 has HDMI type A connector. Signed-off-by: Yangtao Li --- rebase: sunxi/dt64-for-5.2 arm64: dts: allwinner: a64-amarula-relic: Add OV5640 camera node --- .../dts/allwinner/sun50i-h6-orangepi-3.dts| 25 +++ 1 file changed, 25 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts index 17d496990108..6ed3a1ee297d 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts @@ -21,6 +21,17 @@ stdout-path = "serial0:115200n8"; }; + connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <_out_con>; + }; + }; + }; + leds { compatible = "gpio-leds"; @@ -50,6 +61,10 @@ cpu-supply = <_dcdca>; }; + { + status = "okay"; +}; + { status = "okay"; }; @@ -58,6 +73,16 @@ status = "okay"; }; + { + status = "okay"; +}; + +_out { + hdmi_out_con: endpoint { + remote-endpoint = <_con_in>; + }; +}; + { vmmc-supply = <_cldo1>; cd-gpios = < 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ -- 2.17.0
[PATCH 7/7] iio: adc: sun4i-gpadc-iio convert to SPDX license tags
Updates license to use SPDX-License-Identifier. Signed-off-by: Yangtao Li --- drivers/iio/adc/sun4i-gpadc-iio.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index 9b6fc592f54c..cf2bf3ab3342 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* ADC driver for sunxi platforms' (A10, A13 and A31) GPADC * * Copyright (c) 2016 Quentin Schulz * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License version 2 as published by the - * Free Software Foundation. - * * The Allwinner SoCs all have an ADC that can also act as a touchscreen * controller and a thermal sensor. * The thermal sensor works only when the ADC acts as a touchscreen controller -- 2.17.1
[PATCH 2/7] iio: adc: sun4i-gpadc: introduce temp_data in gpadc_data
For some SOCs, the temperature data register start address may be different, so introduce temp_data in gpadc_data. Also modify read temperature to support multiple sensor. Signed-off-by: Yangtao Li --- drivers/iio/adc/sun4i-gpadc-iio.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index 844fd52bd22f..b41ec0d5964d 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -57,6 +57,7 @@ struct gpadc_data { unsigned int(*adc_chan_select)(unsigned int chan); unsigned intadc_chan_mask; unsigned intsensor_count; + unsigned inttemp_data_base; }; static const struct gpadc_data sun4i_gpadc_data = { @@ -67,6 +68,7 @@ static const struct gpadc_data sun4i_gpadc_data = { .adc_chan_select = _gpadc_chan_select, .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, .sensor_count = 1, + .temp_data_base = SUN4I_GPADC_TEMP_DATA, }; static const struct gpadc_data sun5i_gpadc_data = { @@ -77,6 +79,7 @@ static const struct gpadc_data sun5i_gpadc_data = { .adc_chan_select = _gpadc_chan_select, .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, .sensor_count = 1, + .temp_data_base = SUN4I_GPADC_TEMP_DATA, }; static const struct gpadc_data sun6i_gpadc_data = { @@ -87,6 +90,7 @@ static const struct gpadc_data sun6i_gpadc_data = { .adc_chan_select = _gpadc_chan_select, .adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK, .sensor_count = 1, + .temp_data_base = SUN4I_GPADC_TEMP_DATA, }; static const struct gpadc_data sun8i_a33_gpadc_data = { @@ -94,6 +98,7 @@ static const struct gpadc_data sun8i_a33_gpadc_data = { .temp_scale = 162, .tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN, .sensor_count = 1, + .temp_data_base = SUN4I_GPADC_TEMP_DATA, }; struct sun4i_sensor_tzd { @@ -291,7 +296,8 @@ static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val, if (info->no_irq) { pm_runtime_get_sync(indio_dev->dev.parent); - regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val); + regmap_read(info->regmap, info->data->temp_data_base + + 0x4 * sensor, val); pm_runtime_mark_last_busy(indio_dev->dev.parent); pm_runtime_put_autosuspend(indio_dev->dev.parent); -- 2.17.1
[PATCH 1/7] iio: adc: sun4i-gpadc: rework for support multiple thermal sensor
For some SOCs, there are more than one thermal sensor, and there are currently four sensors on the A80. So we need to do some work in order to support multiple thermal sensors: 1) add sensor_count in gpadc_data. 2) introduce sun4i_sensor_tzd in sun4i_gpadc_iio, to support multiple thermal_zone_device and distinguish between different sensors. 3) modify read temperature and initialization function. Signed-off-by: Yangtao Li --- drivers/iio/adc/sun4i-gpadc-iio.c | 61 +++ 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index 04d7147e0110..844fd52bd22f 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -56,6 +56,7 @@ struct gpadc_data { unsigned inttp_adc_select; unsigned int(*adc_chan_select)(unsigned int chan); unsigned intadc_chan_mask; + unsigned intsensor_count; }; static const struct gpadc_data sun4i_gpadc_data = { @@ -65,6 +66,7 @@ static const struct gpadc_data sun4i_gpadc_data = { .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, .adc_chan_select = _gpadc_chan_select, .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, + .sensor_count = 1, }; static const struct gpadc_data sun5i_gpadc_data = { @@ -74,6 +76,7 @@ static const struct gpadc_data sun5i_gpadc_data = { .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, .adc_chan_select = _gpadc_chan_select, .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, + .sensor_count = 1, }; static const struct gpadc_data sun6i_gpadc_data = { @@ -83,14 +86,24 @@ static const struct gpadc_data sun6i_gpadc_data = { .tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT, .adc_chan_select = _gpadc_chan_select, .adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK, + .sensor_count = 1, }; static const struct gpadc_data sun8i_a33_gpadc_data = { .temp_offset = -1662, .temp_scale = 162, .tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN, + .sensor_count = 1, }; +struct sun4i_sensor_tzd { + struct sun4i_gpadc_iio *info; + struct thermal_zone_device *tzd; + unsigned intsensor_id; +}; + +#define MAX_SENSOR_COUNT 4 + struct sun4i_gpadc_iio { struct iio_dev *indio_dev; struct completion completion; @@ -105,7 +118,7 @@ struct sun4i_gpadc_iio { boolno_irq; /* prevents concurrent reads of temperature and ADC */ struct mutexmutex; - struct thermal_zone_device *tzd; + struct sun4i_sensor_tzd tzds[MAX_SENSOR_COUNT]; struct device *sensor_device; }; @@ -270,7 +283,8 @@ static int sun4i_gpadc_adc_read(struct iio_dev *indio_dev, int channel, return sun4i_gpadc_read(indio_dev, channel, val, info->fifo_data_irq); } -static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val) +static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val, +unsigned int sensor) { struct sun4i_gpadc_iio *info = iio_priv(indio_dev); @@ -324,7 +338,7 @@ static int sun4i_gpadc_read_raw(struct iio_dev *indio_dev, ret = sun4i_gpadc_adc_read(indio_dev, chan->channel, val); else - ret = sun4i_gpadc_temp_read(indio_dev, val); + ret = sun4i_gpadc_temp_read(indio_dev, val, 0); if (ret) return ret; @@ -417,10 +431,11 @@ static int sun4i_gpadc_runtime_resume(struct device *dev) static int sun4i_gpadc_get_temp(void *data, int *temp) { - struct sun4i_gpadc_iio *info = data; + struct sun4i_sensor_tzd *tzd = data; + struct sun4i_gpadc_iio *info = tzd->info; int val, scale, offset; - if (sun4i_gpadc_temp_read(info->indio_dev, )) + if (sun4i_gpadc_temp_read(info->indio_dev, , tzd->sensor_id)) return -ETIMEDOUT; sun4i_gpadc_temp_scale(info->indio_dev, ); @@ -609,6 +624,28 @@ static int sun4i_gpadc_probe_mfd(struct platform_device *pdev, return 0; } +static int sun4i_sensor_init(struct sun4i_gpadc_iio *info) +{ + int i = 0; + + for (; i < info->data->sensor_count; i++) { + info->tzds[i].info = info; + info->tzds[i].sensor_id = i; + info->tzds[i].tzd = devm_thermal_zone_of_sensor_register( + info->sensor_device, i, >tzds[i], + _ts_tz_ops); + + if (IS_ERR(info->tzds[i].tzd)) { + dev_err(info->sensor_device, +
[PATCH 3/7] iio: adc: sun4i-gpadc: introduce gpadc_enable and gpadc_disable in gpadc_data
Different sensors may have different enable and disable functions, so introduce enable and disable in gpadc_data to support soc specific function. Signed-off-by: Yangtao Li --- drivers/iio/adc/sun4i-gpadc-iio.c | 37 ++- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index b41ec0d5964d..de6b8556a549 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -49,6 +49,8 @@ static unsigned int sun6i_gpadc_chan_select(unsigned int chan) return SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(chan); } +struct sun4i_gpadc_iio; + struct gpadc_data { int temp_offset; int temp_scale; @@ -56,10 +58,15 @@ struct gpadc_data { unsigned inttp_adc_select; unsigned int(*adc_chan_select)(unsigned int chan); unsigned intadc_chan_mask; + int (*gpadc_enable)(struct sun4i_gpadc_iio *info); + int (*gpadc_disable)(struct sun4i_gpadc_iio *info); unsigned intsensor_count; unsigned inttemp_data_base; }; +static int sun4i_gpadc_disable(struct sun4i_gpadc_iio *info); +static int sun4i_gpadc_enable(struct sun4i_gpadc_iio *info); + static const struct gpadc_data sun4i_gpadc_data = { .temp_offset = -1932, .temp_scale = 133, @@ -67,6 +74,8 @@ static const struct gpadc_data sun4i_gpadc_data = { .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, .adc_chan_select = _gpadc_chan_select, .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, + .gpadc_enable = sun4i_gpadc_enable, + .gpadc_disable = sun4i_gpadc_disable, .sensor_count = 1, .temp_data_base = SUN4I_GPADC_TEMP_DATA, }; @@ -78,6 +87,8 @@ static const struct gpadc_data sun5i_gpadc_data = { .tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT, .adc_chan_select = _gpadc_chan_select, .adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK, + .gpadc_enable = sun4i_gpadc_enable, + .gpadc_disable = sun4i_gpadc_disable, .sensor_count = 1, .temp_data_base = SUN4I_GPADC_TEMP_DATA, }; @@ -89,6 +100,8 @@ static const struct gpadc_data sun6i_gpadc_data = { .tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT, .adc_chan_select = _gpadc_chan_select, .adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK, + .gpadc_enable = sun4i_gpadc_enable, + .gpadc_disable = sun4i_gpadc_disable, .sensor_count = 1, .temp_data_base = SUN4I_GPADC_TEMP_DATA, }; @@ -97,6 +110,8 @@ static const struct gpadc_data sun8i_a33_gpadc_data = { .temp_offset = -1662, .temp_scale = 162, .tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN, + .gpadc_enable = sun4i_gpadc_enable, + .gpadc_disable = sun4i_gpadc_disable, .sensor_count = 1, .temp_data_base = SUN4I_GPADC_TEMP_DATA, }; @@ -402,10 +417,8 @@ static irqreturn_t sun4i_gpadc_fifo_data_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static int sun4i_gpadc_runtime_suspend(struct device *dev) +static int sun4i_gpadc_disable(struct sun4i_gpadc_iio *info) { - struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); - /* Disable the ADC on IP */ regmap_write(info->regmap, SUN4I_GPADC_CTRL1, 0); /* Disable temperature sensor on IP */ @@ -414,10 +427,8 @@ static int sun4i_gpadc_runtime_suspend(struct device *dev) return 0; } -static int sun4i_gpadc_runtime_resume(struct device *dev) +static int sun4i_gpadc_enable(struct sun4i_gpadc_iio *info) { - struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); - /* clkin = 6MHz */ regmap_write(info->regmap, SUN4I_GPADC_CTRL0, SUN4I_GPADC_CTRL0_ADC_CLK_DIVIDER(2) | @@ -435,6 +446,20 @@ static int sun4i_gpadc_runtime_resume(struct device *dev) return 0; } +static int sun4i_gpadc_runtime_suspend(struct device *dev) +{ + struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); + + return info->data->gpadc_disable(info); +} + +static int sun4i_gpadc_runtime_resume(struct device *dev) +{ + struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); + + return info->data->gpadc_enable(info); +} + static int sun4i_gpadc_get_temp(void *data, int *temp) { struct sun4i_sensor_tzd *tzd = data; -- 2.17.1
[PATCH 5/7] dt-bindings: mfd: Add H6 GPADC binding
This patch adds documentation for the H6 GPADC binding. Signed-off-by: Yangtao Li --- .../devicetree/bindings/mfd/sun4i-gpadc.txt | 27 +-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt b/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt index 86dd8191b04c..eeaf27eb8abd 100644 --- a/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt +++ b/Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt @@ -5,11 +5,22 @@ and sometimes as a touchscreen controller. Required properties: - compatible: "allwinner,sun8i-a33-ths", + "allwinner,sun50i-h6-ths", - reg: mmio address range of the chip, - - #thermal-sensor-cells: shall be 0, + - #thermal-sensor-cells: shall be 0 for sun8i-a33-ths, + shall be 1 for sun50i-h6-ths, - #io-channel-cells: shall be 0, -Example: +Optional properties: + - clocks: Must contain an entry for each entry in clock-names. + See common clock-bindings.txt for details. + - clock-names: A list of clock names. For sun50i-h6-ths, it must contain +"bus". + - resets: Must contain an entry for each entry in reset-names. + See ../reset/reset.txt for details. + - reset-names: For sun50i-h6-ths, it must contain "bus". + +Example1: ths: ths@1c25000 { compatible = "allwinner,sun8i-a33-ths"; reg = <0x01c25000 0x100>; @@ -17,6 +28,18 @@ Example: #io-channel-cells = <0>; }; +Example2: + ths: ths@1c25000 { + compatible = "allwinner,sun50i-h6-ths"; + reg = <0x05070400 0x100>; + clocks = < CLK_BUS_THS>; + clock-names = "bus"; + resets = < RST_BUS_THS>; + reset-names = "bus"; + #thermal-sensor-cells = <1>; + #io-channel-cells = <0>; + }; + sun4i, sun5i and sun6i SoCs are also supported via the older binding: sun4i resistive touchscreen controller -- 2.17.1
[PATCH 6/7] iio: adc: sun4i-gpadc-iio: add support for H6 thermal sensor
This patch adds support for the H6 ths sensor. TODO: calibrate thermal sensor by using information from sid. Signed-off-by: Yangtao Li --- drivers/iio/adc/sun4i-gpadc-iio.c | 65 +++ include/linux/mfd/sun4i-gpadc.h | 9 + 2 files changed, 74 insertions(+) diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index f24eb76d65c0..9b6fc592f54c 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -120,6 +120,20 @@ static const struct gpadc_data sun8i_a33_gpadc_data = { .temp_data_base = SUN4I_GPADC_TEMP_DATA, }; +static int sun50i_gpadc_disable(struct sun4i_gpadc_iio *info); +static int sun50i_gpadc_enable(struct sun4i_gpadc_iio *info); + +static const struct gpadc_data sun50i_h6_gpadc_data = { + .temp_offset = -2809, + .temp_scale = -67, + .has_bus_clk = true, + .has_bus_rst = true, + .gpadc_enable = sun50i_gpadc_enable, + .gpadc_disable = sun50i_gpadc_disable, + .sensor_count = 2, + .temp_data_base = SUN50I_H6_GPADC_TEMP_DATA, +}; + struct sun4i_sensor_tzd { struct sun4i_gpadc_iio *info; struct thermal_zone_device *tzd; @@ -452,6 +466,53 @@ static int sun4i_gpadc_enable(struct sun4i_gpadc_iio *info) return 0; } +static int sun50i_gpadc_enable(struct sun4i_gpadc_iio *info) +{ + int ret, val; + + ret = reset_control_deassert(info->reset); + if (ret) + return ret; + + ret = clk_prepare_enable(info->bus_clk); + if (ret) + goto assert_reset; + + /* +* clkin = 24MHz +* T acquire = clkin / (SUN50I_GPADC_CTRL0_T_ACQ + 1) +* = 20us +*/ + regmap_write(info->regmap, SUN4I_GPADC_CTRL0, +SUN50I_GPADC_CTRL0_T_ACQ(479)); + /* average over 4 samples */ + regmap_write(info->regmap, SUN50I_H6_GPADC_CTRL3, +SUN4I_GPADC_CTRL3_FILTER_EN | +SUN4I_GPADC_CTRL3_FILTER_TYPE(1)); + /* period = (SUN50I_GPADC_TPR_TEMP_PERIOD + 1) * 4096 / clkin; ~10ms */ + regmap_write(info->regmap, SUN50I_GPADC_TPR, +SUN50I_GPADC_TPR_TEMP_PERIOD(58)); + /* TODO: calibrate ths */ + /* enable sensor */ + val = GENMASK(info->data->sensor_count - 1, 0); + regmap_write(info->regmap, SUN4I_GPADC_CTRL1, val); + + return 0; + +assert_reset: + reset_control_assert(info->reset); + + return ret; +} + +static int sun50i_gpadc_disable(struct sun4i_gpadc_iio *info) +{ + clk_disable_unprepare(info->bus_clk); + reset_control_assert(info->reset); + + return 0; +} + static int sun4i_gpadc_runtime_suspend(struct device *dev) { struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev)); @@ -546,6 +607,10 @@ static const struct of_device_id sun4i_gpadc_of_id[] = { .compatible = "allwinner,sun8i-a33-ths", .data = _a33_gpadc_data, }, + { + .compatible = "allwinner,sun50i-h6-ths", + .data = _h6_gpadc_data, + }, { /* sentinel */ } }; diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h index 139872c2e0fe..f505013e9c0d 100644 --- a/include/linux/mfd/sun4i-gpadc.h +++ b/include/linux/mfd/sun4i-gpadc.h @@ -19,6 +19,9 @@ #define SUN4I_GPADC_CTRL0_FS_DIV(x)((GENMASK(3, 0) & (x)) << 16) #define SUN4I_GPADC_CTRL0_T_ACQ(x) (GENMASK(15, 0) & (x)) +/* TP_CTRL0 bits for sun50i SOCs */ +#define SUN50I_GPADC_CTRL0_T_ACQ(x)((GENMASK(15, 0) & (x)) << 16) + #define SUN4I_GPADC_CTRL1 0x04 #define SUN4I_GPADC_CTRL1_STYLUS_UP_DEBOUNCE(x)((GENMASK(7, 0) & (x)) << 12) @@ -49,6 +52,9 @@ #define SUN4I_GPADC_CTRL2_PRE_MEA_EN BIT(24) #define SUN4I_GPADC_CTRL2_PRE_MEA_THRE_CNT(x) (GENMASK(23, 0) & (x)) +#define SUN50I_GPADC_TPR 0x08 +#define SUN50I_GPADC_TPR_TEMP_PERIOD(x)((GENMASK(19, 0) & (x)) << 12) + #define SUN4I_GPADC_CTRL3 0x0c #define SUN4I_GPADC_CTRL3_FILTER_ENBIT(2) @@ -84,6 +90,9 @@ #define SUN4I_GPADC_TEMP_DATA 0x20 #define SUN4I_GPADC_DATA 0x24 +#define SUN50I_H6_GPADC_CTRL3 0x30 +#define SUN50I_H6_GPADC_TEMP_DATA 0xc0 + #define SUN4I_GPADC_IRQ_FIFO_DATA 0 #define SUN4I_GPADC_IRQ_TEMP_DATA 1 -- 2.17.1
[PATCH 4/7] iio: adc: sun4i-gpadc-iio: support clocks and reset
H6 has bus clock and a reset, so introduce something in gpadc_data/sun4i_gpadc_iio and adds the process of the clocks and resets. This is pre-work for supprt it. Signed-off-by: Yangtao Li --- drivers/iio/adc/sun4i-gpadc-iio.c | 32 +-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index de6b8556a549..f24eb76d65c0 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -22,6 +22,7 @@ * shutdown for not being used. */ +#include #include #include #include @@ -31,6 +32,7 @@ #include #include #include +#include #include #include @@ -52,6 +54,8 @@ static unsigned int sun6i_gpadc_chan_select(unsigned int chan) struct sun4i_gpadc_iio; struct gpadc_data { + boolhas_bus_clk; + boolhas_bus_rst; int temp_offset; int temp_scale; unsigned inttp_mode_en; @@ -140,6 +144,8 @@ struct sun4i_gpadc_iio { struct mutexmutex; struct sun4i_sensor_tzd tzds[MAX_SENSOR_COUNT]; struct device *sensor_device; + struct clk *bus_clk; + struct reset_control*reset; }; #define SUN4I_GPADC_ADC_CHANNEL(_channel, _name) { \ @@ -564,14 +570,36 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev, if (IS_ERR(base)) return PTR_ERR(base); - info->regmap = devm_regmap_init_mmio(>dev, base, -_gpadc_regmap_config); + if (info->data->has_bus_clk) + info->regmap = devm_regmap_init_mmio_clk(>dev, "bus", +base, + _gpadc_regmap_config); + else + info->regmap = devm_regmap_init_mmio(>dev, base, + _gpadc_regmap_config); + if (IS_ERR(info->regmap)) { ret = PTR_ERR(info->regmap); dev_err(>dev, "failed to init regmap: %d\n", ret); return ret; } + if (info->data->has_bus_rst) { + info->reset = devm_reset_control_get(>dev, "bus"); + if (IS_ERR(info->reset)) { + ret = PTR_ERR(info->reset); + return ret; + } + } + + if (info->data->has_bus_clk) { + info->bus_clk = devm_clk_get(>dev, "bus"); + if (IS_ERR(info->bus_clk)) { + ret = PTR_ERR(info->bus_clk); + return ret; + } + } + if (IS_ENABLED(CONFIG_THERMAL_OF)) info->sensor_device = >dev; -- 2.17.1
[PATCH 0/7] Add support for H6 thermal sensor
This patchset adds support for the H6 ths sensor. Based on IIO-based thermal sensor driver for Allwinner H3 and A83T SoC, thx to Philipp Rossak's work. TODO: calibrate thermal sensor by using information from sid. Yangtao Li (7): iio: adc: sun4i-gpadc: rework for support multiple thermal sensor iio: adc: sun4i-gpadc: introduce temp_data in gpadc_data iio: adc: sun4i-gpadc: introduce gpadc_enable and gpadc_disable in gpadc_data iio: adc: sun4i-gpadc-iio: support clocks and reset dt-bindings: mfd: Add H6 GPADC binding iio: adc: sun4i-gpadc-iio: add support for H6 thermal sensor iio: adc: sun4i-gpadc-iio convert to SPDX license tags .../devicetree/bindings/mfd/sun4i-gpadc.txt | 27 ++- drivers/iio/adc/sun4i-gpadc-iio.c | 208 +++--- include/linux/mfd/sun4i-gpadc.h | 9 + 3 files changed, 213 insertions(+), 31 deletions(-) -- 2.17.1
[PATCH v2 0/2] add thermal driver for h6
This patchset supprt H6 thermal controller. Yangtao Li (2): thermal: sun8i: add thermal driver for h6 dt-bindings: thermal: add binding document for h6 thermal controller .../bindings/thermal/sun8i-thermal.txt| 34 ++ MAINTAINERS | 7 + drivers/thermal/Kconfig | 14 + drivers/thermal/Makefile | 1 + drivers/thermal/sun8i_thermal.c | 422 ++ 5 files changed, 478 insertions(+) create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.txt create mode 100644 drivers/thermal/sun8i_thermal.c --- v2: -Additions and deletions of some comments -Change some function prefix to "ths_" -Support interrupt --- 2.17.0
[PATCH v2 1/2] thermal: sun8i: add thermal driver for h6
This patch adds the support for allwinner thermal sensor, within allwinner SoC. It will register sensors for thermal framework and use device tree to bind cooling device. Signed-off-by: Yangtao Li --- MAINTAINERS | 7 + drivers/thermal/Kconfig | 14 ++ drivers/thermal/Makefile| 1 + drivers/thermal/sun8i_thermal.c | 422 4 files changed, 444 insertions(+) create mode 100644 drivers/thermal/sun8i_thermal.c diff --git a/MAINTAINERS b/MAINTAINERS index 005902ea1450..4e753ed20cd0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -674,6 +674,13 @@ L: linux-cry...@vger.kernel.org S: Maintained F: drivers/crypto/sunxi-ss/ +ALLWINNER THERMAL DRIVER +M: Yangtao Li +L: linux...@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/thermal/sun8i-thermal.txt +F: drivers/thermal/sun8i_thermal.c + ALLWINNER VPU DRIVER M: Maxime Ripard M: Paul Kocialkowski diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 66a709d5d6b9..f03d941c5686 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -263,6 +263,20 @@ config SPEAR_THERMAL Enable this to plug the SPEAr thermal sensor driver into the Linux thermal framework. +config SUN8I_THERMAL + tristate "Allwinner sun8i thermal driver" + depends on ARCH_SUNXI || COMPILE_TEST + depends on HAS_IOMEM + depends on NVMEM_SUNXI_SID + depends on OF + depends on RESET_CONTROLLER + help + Support for the sun8i thermal sensor driver into the Linux thermal + framework. + + To compile this driver as a module, choose M here: the + module will be called sun8i-thermal. + config ROCKCHIP_THERMAL tristate "Rockchip thermal driver" depends on ARCH_ROCKCHIP || COMPILE_TEST diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 74a37c7f847a..fa6f8b206281 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -31,6 +31,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o obj-y += broadcom/ obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o obj-$(CONFIG_SPEAR_THERMAL)+= spear_thermal.o +obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o obj-$(CONFIG_RCAR_GEN3_THERMAL)+= rcar_gen3_thermal.o diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c new file mode 100644 index ..c9920f58fc80 --- /dev/null +++ b/drivers/thermal/sun8i_thermal.c @@ -0,0 +1,422 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Thermal sensor driver for Allwinner SOC + * Copyright (C) 2019 Yangtao Li + * + * Based on the work of Icenowy Zheng + * Based on the work of Ondrej Jirman + * Based on the work of Josef Gajdusek + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_SENSOR_NUM 4 + +#define FT_TEMP_MASK GENMASK(11, 0) +#define TEMP_CALIB_MASKGENMASK(11, 0) +#define TEMP_TO_REG672 +#define CALIBRATE_DEFAULT 0x800 + +#define SUN50I_THS_CTRL0 0x00 +#define SUN50I_H6_THS_ENABLE 0x04 +#define SUN50I_H6_THS_PC 0x08 +#define SUN50I_H6_THS_DIC 0x10 +#define SUN50I_H6_THS_DIS 0x20 +#define SUN50I_H6_THS_MFC 0x30 +#define SUN50I_H6_THS_TEMP_CALIB 0xa0 +#define SUN50I_H6_THS_TEMP_DATA0xc0 + +#define SUN50I_THS_CTRL0_T_ACQ(x) ((GENMASK(15, 0) & (x)) << 16) +#define SUN50I_THS_FILTER_EN BIT(2) +#define SUN50I_THS_FILTER_TYPE(x) (GENMASK(1, 0) & (x)) +#define SUN50I_H6_THS_PC_TEMP_PERIOD(x)((GENMASK(19, 0) & (x)) << 12) +#define SUN50I_H6_THS_DATA_IRQ_STS(x) BIT(x) + +/* millidegree celsius */ +#define SUN50I_H6_FT_DEVIATION 7000 + +struct ths_device; + +struct tsensor { + struct ths_device *tmdev; + struct thermal_zone_device *tzd; + int id; +}; + +struct ths_thermal_chip { + int sensor_num; + int offset; + int scale; + int ft_deviation; + int temp_calib_base; + int temp_data_base; + int (*enable)(struct ths_device *tmdev); + int (*disable)(struct ths_device *tmdev); + irqreturn_t (*irq_thread)(int irq, void *data); +}; + +struct ths_device { + const struct ths_thermal_chip *chip; + struct device
[PATCH v2 2/2] dt-bindings: thermal: add binding document for h6 thermal controller
This patch adds binding document for allwinner h6 thermal controller. Signed-off-by: Yangtao Li --- .../bindings/thermal/sun8i-thermal.txt| 34 +++ 1 file changed, 34 insertions(+) create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.txt diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.txt b/Documentation/devicetree/bindings/thermal/sun8i-thermal.txt new file mode 100644 index ..bd417260501f --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.txt @@ -0,0 +1,34 @@ +* Allwinner Thermal + +This describes the device tree binding for the Allwinner thermal controller +which measures the on-SoC temperatures. + +Required properties: +- compatible: + - "allwinner,sun50i-h6-ths" : For H6 +- reg: Address range of the thermal controller +- clocks, clock-names: Clocks needed for the thermal controller. + The required clocks for h6 are: "bus". +- resets: Reference to the reset controller controlling the thermal controller. +- interrupts: IRQ for the thermal controller +- #thermal-sensor-cells : For H6 Should be 1. + See ./thermal.txt for a description. + +Optional properties: +- nvmem-cells: A phandle to the calibration data provided by a nvmem device. If + unspecified default values shall be used. +- nvmem-cell-names: Should be "calib". + +Example: + + ths: ths@1c25000 { + compatible = "allwinner,sun50i-h6-ths"; + reg = <0x05070400 0x100>; + clocks = < CLK_BUS_THS>; + clock-names = "bus"; + resets = < RST_BUS_THS>; + interrupts = ; + nvmem-cells = <_calib>; + nvmem-cell-names = "calib"; + #thermal-sensor-cells = <1>; + }; -- 2.17.0
[PATCH] PM / core: fix kerneldoc comment for dpm_watchdog_handler()
This brings the kernel doc in line with the function signature. Signed-off-by: Yangtao Li --- drivers/base/power/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index f80d298de3fa..0cff68bd7b4b 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -478,7 +478,7 @@ struct dpm_watchdog { /** * dpm_watchdog_handler - Driver suspend / resume watchdog handler. - * @data: Watchdog object address. + * @t: The timer that pm watchdog depends on. * * Called when a driver has timed out suspending or resuming. * There's not much we can do here to recover so panic() to -- 2.17.0
[PATCH] PM / core: fix kerneldoc comment for device_pm_wait_for_dev
Rearrange comment to make the comment style consistent, the previous function parameters are described first. Signed-off-by: Yangtao Li --- drivers/base/power/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 0cff68bd7b4b..eddb54057ed6 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -2069,8 +2069,8 @@ EXPORT_SYMBOL_GPL(__suspend_report_result); /** * device_pm_wait_for_dev - Wait for suspend/resume of a device to complete. - * @dev: Device to wait for. * @subordinate: Device that needs to wait for @dev. + * @dev: Device to wait for. */ int device_pm_wait_for_dev(struct device *subordinate, struct device *dev) { -- 2.17.0
[PATCH 2/4] PM / core: Introduce DEVICE_SUSPEND_FUNC() helper macro
The devices_suspend_noirq, device_suspend_late, device_suspen functions are basically the same. As we have seen: static int device_xxx(struct device *dev) { if (dpm_async_fn(dev, async_xxx)) return 0; return __device_xxx(dev, pm_transition, false); } The DEVICE_SUSPEND_FUNC() helper macro can decrease code duplication. Signed-off-by: Yangtao Li --- drivers/base/power/main.c | 33 - 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index cb44bb6b2b66..6026bda5e787 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -719,6 +719,15 @@ static bool dpm_async_fn(struct device *dev, async_func_t func) return false; } +#define DEVICE_SUSPEND_FUNC(__func, __name)\ +static int __func(struct device *dev) \ +{ \ + if (dpm_async_fn(dev, async_ ## __name))\ + return 0; \ + \ + return __device_ ## __name(dev, pm_transition, false); \ +} + static void async_resume_noirq(void *data, async_cookie_t cookie) { struct device *dev = (struct device *)data; @@ -1369,13 +1378,7 @@ static void async_suspend_noirq(void *data, async_cookie_t cookie) put_device(dev); } -static int device_suspend_noirq(struct device *dev) -{ - if (dpm_async_fn(dev, async_suspend_noirq)) - return 0; - - return __device_suspend_noirq(dev, pm_transition, false); -} +DEVICE_SUSPEND_FUNC(device_suspend_noirq, suspend_noirq); void dpm_noirq_begin(void) { @@ -1568,13 +1571,7 @@ static void async_suspend_late(void *data, async_cookie_t cookie) put_device(dev); } -static int device_suspend_late(struct device *dev) -{ - if (dpm_async_fn(dev, async_suspend_late)) - return 0; - - return __device_suspend_late(dev, pm_transition, false); -} +DEVICE_SUSPEND_FUNC(device_suspend_late, suspend_late); /** * dpm_suspend_late - Execute "late suspend" callbacks for all devices. @@ -1829,13 +1826,7 @@ static void async_suspend(void *data, async_cookie_t cookie) put_device(dev); } -static int device_suspend(struct device *dev) -{ - if (dpm_async_fn(dev, async_suspend)) - return 0; - - return __device_suspend(dev, pm_transition, false); -} +DEVICE_SUSPEND_FUNC(device_suspend, suspend); /** * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices. -- 2.17.0
[PATCH 0/4] PM / core: Introduce some helper for better Code reuse
This patch set introduces some functions and macros that help reduce code duplication. Yangtao Li (4): PM / core: Introduce dpm_async_fn() helper PM / core: Introduce DEVICE_SUSPEND_FUNC() helper macro PM / core: Introduce ASYNC_RESUME_FUNC() helper macro PM / core: Introduce ASYNC_SUSPEND_FUNC() helper macro drivers/base/power/main.c | 182 -- 1 file changed, 59 insertions(+), 123 deletions(-) -- 2.17.0
[PATCH 1/4] PM / core: Introduce dpm_async_fn() helper
When we want to execute device pm functions asynchronously, we'll do the following for the device: 1) reinit_completion(>power.completion); 2) Check if the device enables asynchronous suspend. 3) If necessary, execute the corresponding function asynchronously. There are a lot of such repeated operations here, in fact we can avoid this. So introduce dpm_async_fn() to have better code readability and reuse. And use this function to do some cleanup. Signed-off-by: Yangtao Li --- drivers/base/power/main.c | 62 +++ 1 file changed, 23 insertions(+), 39 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index eddb54057ed6..cb44bb6b2b66 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -706,6 +706,19 @@ static bool is_async(struct device *dev) && !pm_trace_is_enabled(); } +static bool dpm_async_fn(struct device *dev, async_func_t func) +{ + reinit_completion(>power.completion); + + if (is_async(dev)) { + get_device(dev); + async_schedule(func, dev); + return true; + } + + return false; +} + static void async_resume_noirq(void *data, async_cookie_t cookie) { struct device *dev = (struct device *)data; @@ -732,13 +745,8 @@ void dpm_noirq_resume_devices(pm_message_t state) * in case the starting of async threads is * delayed by non-async resuming devices. */ - list_for_each_entry(dev, _noirq_list, power.entry) { - reinit_completion(>power.completion); - if (is_async(dev)) { - get_device(dev); - async_schedule_dev(async_resume_noirq, dev); - } - } + list_for_each_entry(dev, _noirq_list, power.entry) + dpm_async_fn(dev, async_resume_noirq); while (!list_empty(_noirq_list)) { dev = to_device(dpm_noirq_list.next); @@ -889,13 +897,8 @@ void dpm_resume_early(pm_message_t state) * in case the starting of async threads is * delayed by non-async resuming devices. */ - list_for_each_entry(dev, _late_early_list, power.entry) { - reinit_completion(>power.completion); - if (is_async(dev)) { - get_device(dev); - async_schedule_dev(async_resume_early, dev); - } - } + list_for_each_entry(dev, _late_early_list, power.entry) + dpm_async_fn(dev, async_resume_early); while (!list_empty(_late_early_list)) { dev = to_device(dpm_late_early_list.next); @@ -1053,13 +1056,8 @@ void dpm_resume(pm_message_t state) pm_transition = state; async_error = 0; - list_for_each_entry(dev, _suspended_list, power.entry) { - reinit_completion(>power.completion); - if (is_async(dev)) { - get_device(dev); - async_schedule_dev(async_resume, dev); - } - } + list_for_each_entry(dev, _suspended_list, power.entry) + dpm_async_fn(dev, async_resume); while (!list_empty(_suspended_list)) { dev = to_device(dpm_suspended_list.next); @@ -1373,13 +1371,9 @@ static void async_suspend_noirq(void *data, async_cookie_t cookie) static int device_suspend_noirq(struct device *dev) { - reinit_completion(>power.completion); - - if (is_async(dev)) { - get_device(dev); - async_schedule_dev(async_suspend_noirq, dev); + if (dpm_async_fn(dev, async_suspend_noirq)) return 0; - } + return __device_suspend_noirq(dev, pm_transition, false); } @@ -1576,13 +1570,8 @@ static void async_suspend_late(void *data, async_cookie_t cookie) static int device_suspend_late(struct device *dev) { - reinit_completion(>power.completion); - - if (is_async(dev)) { - get_device(dev); - async_schedule_dev(async_suspend_late, dev); + if (dpm_async_fn(dev, async_suspend_late)) return 0; - } return __device_suspend_late(dev, pm_transition, false); } @@ -1842,13 +1831,8 @@ static void async_suspend(void *data, async_cookie_t cookie) static int device_suspend(struct device *dev) { - reinit_completion(>power.completion); - - if (is_async(dev)) { - get_device(dev); - async_schedule_dev(async_suspend, dev); + if (dpm_async_fn(dev, async_suspend)) return 0; - } return __device_suspend(dev, pm_transition, false); } -- 2.17.0
[PATCH 3/4] PM / core: Introduce ASYNC_RESUME_FUNC() helper macro
The async_resume_noirq, async_resume_early, async_resume functions are basically the same. As we have seen: static void async_xxx(void *data, async_cookie_t cookie) { struct device *dev = (struct device *)data; int error; error = device_xxx(dev, pm_transition, true); if (error) pm_dev_err(dev, pm_transition, " async", error); put_device(dev); } The ASYNC_RESUME_FUNC() helper macro can decrease code duplication. Signed-off-by: Yangtao Li --- drivers/base/power/main.c | 46 +-- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 6026bda5e787..d512bee9d9ca 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -728,18 +728,21 @@ static int __func(struct device *dev) \ return __device_ ## __name(dev, pm_transition, false); \ } -static void async_resume_noirq(void *data, async_cookie_t cookie) -{ - struct device *dev = (struct device *)data; - int error; - - error = device_resume_noirq(dev, pm_transition, true); - if (error) - pm_dev_err(dev, pm_transition, " async", error); - - put_device(dev); +#define ASYNC_RESUME_FUNC(__func, __name) \ +static void __func(void *data, async_cookie_t cookie) \ +{ \ + struct device *dev = (struct device *)data; \ + int error; \ + \ + error = device_ ## __name(dev, pm_transition, true);\ + if (error) \ + pm_dev_err(dev, pm_transition, " async", error);\ + \ + put_device(dev);\ } +ASYNC_RESUME_FUNC(async_resume_noirq, resume_noirq); + void dpm_noirq_resume_devices(pm_message_t state) { struct device *dev; @@ -876,17 +879,7 @@ static int device_resume_early(struct device *dev, pm_message_t state, bool asyn return error; } -static void async_resume_early(void *data, async_cookie_t cookie) -{ - struct device *dev = (struct device *)data; - int error; - - error = device_resume_early(dev, pm_transition, true); - if (error) - pm_dev_err(dev, pm_transition, " async", error); - - put_device(dev); -} +ASYNC_RESUME_FUNC(async_resume_early, resume_early); /** * dpm_resume_early - Execute "early resume" callbacks for all devices. @@ -1035,16 +1028,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) return error; } -static void async_resume(void *data, async_cookie_t cookie) -{ - struct device *dev = (struct device *)data; - int error; - - error = device_resume(dev, pm_transition, true); - if (error) - pm_dev_err(dev, pm_transition, " async", error); - put_device(dev); -} +ASYNC_RESUME_FUNC(async_resume, resume); /** * dpm_resume - Execute "resume" callbacks for non-sysdev devices. -- 2.17.0
[PATCH 4/4] PM / core: Introduce ASYNC_SUSPEND_FUNC() helper macro
The async_suspend_noirq, async_suspend_late, async_suspend functions are basically the same. As we have seen: static void async_xxx(void *data, async_cookie_t cookie) { struct device *dev = (struct device *)data; int error; error = __device_xxx(dev, pm_transition, true); if (error) { dpm_save_failed_dev(dev_name(dev)); pm_dev_err(dev, pm_transition, " async", error); } put_device(dev); } The ASYNC_SUSPEND_FUNC() helper macro can decrease code duplication. Signed-off-by: Yangtao Li --- drivers/base/power/main.c | 55 --- 1 file changed, 16 insertions(+), 39 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index d512bee9d9ca..3882dc5fee9f 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1348,20 +1348,22 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a return error; } -static void async_suspend_noirq(void *data, async_cookie_t cookie) -{ - struct device *dev = (struct device *)data; - int error; - - error = __device_suspend_noirq(dev, pm_transition, true); - if (error) { - dpm_save_failed_dev(dev_name(dev)); - pm_dev_err(dev, pm_transition, " async", error); - } - - put_device(dev); +#define ASYNC_SUSPEND_FUNC(__func, __name) \ +static void __func(void *data, async_cookie_t cookie) \ +{ \ + struct device *dev = (struct device *)data; \ + int error; \ + \ + error = __device_ ## __name(dev, pm_transition, true); \ + if (error) {\ + dpm_save_failed_dev(dev_name(dev)); \ + pm_dev_err(dev, pm_transition, " async", error);\ + } \ + \ + put_device(dev);\ } +ASYNC_SUSPEND_FUNC(async_suspend_noirq, suspend_noirq); DEVICE_SUSPEND_FUNC(device_suspend_noirq, suspend_noirq); void dpm_noirq_begin(void) @@ -1542,19 +1544,7 @@ static int __device_suspend_late(struct device *dev, pm_message_t state, bool as return error; } -static void async_suspend_late(void *data, async_cookie_t cookie) -{ - struct device *dev = (struct device *)data; - int error; - - error = __device_suspend_late(dev, pm_transition, true); - if (error) { - dpm_save_failed_dev(dev_name(dev)); - pm_dev_err(dev, pm_transition, " async", error); - } - put_device(dev); -} - +ASYNC_SUSPEND_FUNC(async_suspend_late, suspend_late); DEVICE_SUSPEND_FUNC(device_suspend_late, suspend_late); /** @@ -1796,20 +1786,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) return error; } -static void async_suspend(void *data, async_cookie_t cookie) -{ - struct device *dev = (struct device *)data; - int error; - - error = __device_suspend(dev, pm_transition, true); - if (error) { - dpm_save_failed_dev(dev_name(dev)); - pm_dev_err(dev, pm_transition, " async", error); - } - - put_device(dev); -} - +ASYNC_SUSPEND_FUNC(async_suspend, suspend); DEVICE_SUSPEND_FUNC(device_suspend, suspend); /** -- 2.17.0
[PATCH] interconnect: convert to DEFINE_SHOW_ATTRIBUTE
Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Yangtao Li --- drivers/interconnect/core.c | 13 + 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index 6005a1c189f6..871eb4bc4efc 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -90,18 +90,7 @@ static int icc_summary_show(struct seq_file *s, void *data) return 0; } - -static int icc_summary_open(struct inode *inode, struct file *file) -{ - return single_open(file, icc_summary_show, inode->i_private); -} - -static const struct file_operations icc_summary_fops = { - .open = icc_summary_open, - .read = seq_read, - .llseek = seq_lseek, - .release= single_release, -}; +DEFINE_SHOW_ATTRIBUTE(icc_summary); static struct icc_node *node_find(const int id) { -- 2.17.0
[PATCH v2 0/5] nvmem: sunxi-sid: add SID controller support for H6
Add SID support for H6, and do some cleanup. For endianness issue, add a new ref_read func. Yangtao Li (5): nvmem: sunxi-sid: fix wrong description in kernel doc nvmem: sunxi-sid: add binding for H6's SID controller nvmem: sunxi-sid: convert to SPDX license tags nvmem: sunxi-sid: add new reg_read func nvmem: sunxi-sid: add support for H6's SID controller --- v2: -add a new ref_read func -only support H6 now --- .../bindings/nvmem/allwinner,sunxi-sid.txt| 3 +- drivers/nvmem/sunxi_sid.c | 47 +++ 2 files changed, 39 insertions(+), 11 deletions(-) -- 2.17.0
[PATCH v2 2/5] nvmem: sunxi-sid: add binding for H6's SID controller
Add a binding for H6's SID controller. Acked-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Yangtao Li --- Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt index d37017e343b1..cfb18b4ef8f7 100644 --- a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt +++ b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt @@ -8,6 +8,7 @@ Required properties: "allwinner,sun8i-h3-sid" "allwinner,sun50i-a64-sid" "allwinner,sun50i-h5-sid" + "allwinner,sun50i-h6-sid" - reg: Should contain registers location and length -- 2.17.0
[PATCH v2 3/5] nvmem: sunxi-sid: convert to SPDX license tags
Updates license to use SPDX-License-Identifier. Acked-by: Maxime Ripard Signed-off-by: Yangtao Li --- drivers/nvmem/sunxi_sid.c | 11 +-- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index 570a2e354f30..54620d72ddb9 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Allwinner sunXi SoCs Security ID support. * * Copyright (c) 2013 Oliver Schinagl * Copyright (C) 2014 Maxime Ripard - * - * 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 -- 2.17.0
[PATCH v2 4/5] nvmem: sunxi-sid: add new reg_read func
Because there was an endianness issue. It seems that reg_read function which the nvmem the driver currently exposes is wrong. So add the new read function, the new function is used when the native_endian flag is set. Signed-off-by: Yangtao Li --- drivers/nvmem/sunxi_sid.c | 29 + 1 file changed, 29 insertions(+) diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index 54620d72ddb9..5b8a42f686cd 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -37,6 +37,7 @@ struct sunxi_sid_cfg { u32 value_offset; u32 size; boolneed_register_readout; + boolnative_endian; }; struct sunxi_sid { @@ -75,6 +76,31 @@ static int sunxi_sid_read(void *context, unsigned int offset, return 0; } +static u8 sunxi_sid_read_byte_native(const struct sunxi_sid *sid, + const unsigned int offset) +{ + u32 sid_key; + + sid_key = ioread32(sid->base + round_down(offset, 4)); + sid_key >>= (offset % 4) * 8; + + return sid_key; +} + +static int sunxi_sid_read_native(void *context, unsigned int offset, + void *val, size_t bytes) +{ + struct sunxi_sid *sid = context; + u8 *buf = val; + + offset += sid->value_offset; + + while (bytes--) + *buf++ = sunxi_sid_read_byte_native(sid, offset++); + + return 0; +} + static int sun8i_sid_register_readout(const struct sunxi_sid *sid, const unsigned int offset, u32 *out) @@ -169,9 +195,12 @@ static int sunxi_sid_probe(struct platform_device *pdev) econfig.dev = dev; if (cfg->need_register_readout) econfig.reg_read = sun8i_sid_read_by_reg; + else if (cfg->native_endian) + econfig.reg_read = sunxi_sid_read_native; else econfig.reg_read = sunxi_sid_read; econfig.priv = sid; + nvmem = devm_nvmem_register(dev, ); if (IS_ERR(nvmem)) return PTR_ERR(nvmem); -- 2.17.0
[PATCH v2 5/5] nvmem: sunxi-sid: add support for H6's SID controller
Add support for H6's SID controller. It supports 4K-bit EFUSE, bigger than before. And convert to use sunxi_sid_read_native func. Signed-off-by: Yangtao Li --- drivers/nvmem/sunxi_sid.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index 5b8a42f686cd..3c2b06140490 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -239,11 +239,18 @@ static const struct sunxi_sid_cfg sun50i_a64_cfg = { .size = 0x100, }; +static const struct sunxi_sid_cfg sun50i_h6_cfg = { + .value_offset = 0x200, + .size = 0x200, + .native_endian = true, +}; + static const struct of_device_id sunxi_sid_of_match[] = { { .compatible = "allwinner,sun4i-a10-sid", .data = _a10_cfg }, { .compatible = "allwinner,sun7i-a20-sid", .data = _a20_cfg }, { .compatible = "allwinner,sun8i-h3-sid", .data = _h3_cfg }, { .compatible = "allwinner,sun50i-a64-sid", .data = _a64_cfg }, + { .compatible = "allwinner,sun50i-h6-sid", .data = _h6_cfg }, {/* sentinel */}, }; MODULE_DEVICE_TABLE(of, sunxi_sid_of_match); -- 2.17.0
[PATCH v2 1/5] nvmem: sunxi-sid: fix wrong description in kernel doc
qfprom->sunxi-sid Acked-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Yangtao Li --- Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt index 99c4ba6a3f61..d37017e343b1 100644 --- a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt +++ b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt @@ -12,7 +12,7 @@ Required properties: - reg: Should contain registers location and length = Data cells = -Are child nodes of qfprom, bindings of which as described in +Are child nodes of sunxi-sid, bindings of which as described in bindings/nvmem/nvmem.txt Example for sun4i: -- 2.17.0
[PATCH v2 1/2] cpufreq: Add sunxi nvmem based CPU scaling driver
For some SoCs, the CPU frequency subset and voltage value of each OPP varies based on the silicon variant in use. The sunxi-cpufreq-nvmem driver reads the efuse value from the SoC to provide the OPP framework with required information. Signed-off-by: Yangtao Li --- MAINTAINERS | 7 + drivers/cpufreq/Kconfig.arm | 10 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq-dt-platdev.c | 2 + drivers/cpufreq/sunxi-cpufreq-nvmem.c | 234 ++ 5 files changed, 254 insertions(+) create mode 100644 drivers/cpufreq/sunxi-cpufreq-nvmem.c diff --git a/MAINTAINERS b/MAINTAINERS index 391405091c6b..bfd18ba6aa1a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -667,6 +667,13 @@ S: Maintained F: Documentation/i2c/busses/i2c-ali1563 F: drivers/i2c/busses/i2c-ali1563.c +ALLWINNER CPUFREQ DRIVER +M: Yangtao Li +L: linux...@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt +F: drivers/cpufreq/sunxi-cpufreq-nvmem.c + ALLWINNER SECURITY SYSTEM M: Corentin Labbe L: linux-cry...@vger.kernel.org diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 179a1d302f48..25933c4321a7 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -18,6 +18,16 @@ config ACPI_CPPC_CPUFREQ If in doubt, say N. +config ARM_ALLWINNER_CPUFREQ_NVMEM + tristate "Allwinner nvmem based CPUFreq" + depends on ARCH_SUNXI + depends on NVMEM_SUNXI_SID + select PM_OPP + help + This adds the CPUFreq driver for Allwinner nvmem based SoC. + + If in doubt, say N. + config ARM_ARMADA_37XX_CPUFREQ tristate "Armada 37xx CPUFreq support" depends on ARCH_MVEBU && CPUFREQ_DT diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 689b26c6f949..da28de67613c 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_ARM_SCMI_CPUFREQ)+= scmi-cpufreq.o obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ)+= spear-cpufreq.o obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o +obj-$(CONFIG_ARM_ALLWINNER_CPUFREQ_NVMEM) += sunxi-cpufreq-nvmem.o obj-$(CONFIG_ARM_TANGO_CPUFREQ)+= tango-cpufreq.o obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 47729a22c159..50e7810f3a28 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -105,6 +105,8 @@ static const struct of_device_id whitelist[] __initconst = { * platforms using "operating-points-v2" property. */ static const struct of_device_id blacklist[] __initconst = { + { .compatible = "allwinner,sun50i-h6", }, + { .compatible = "calxeda,highbank", }, { .compatible = "calxeda,ecx-2000", }, diff --git a/drivers/cpufreq/sunxi-cpufreq-nvmem.c b/drivers/cpufreq/sunxi-cpufreq-nvmem.c new file mode 100644 index ..a72caac572c4 --- /dev/null +++ b/drivers/cpufreq/sunxi-cpufreq-nvmem.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Allwinner CPUFreq nvmem based driver + * + * The sunxi-cpufreq-nvmem driver reads the efuse value from the SoC to + * provide the OPP framework with required information. + * + * Copyright (C) 2019 Yangtao Li + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#define MAX_NAME_LEN 7 + +struct sunxi_cpufreq_soc_data { + u32 (*efuse_xlate)(const struct sunxi_cpufreq_soc_data *soc_data, + u32 efuse); + u32 nvmem_mask; + u32 nvmem_shift; +}; + +static struct platform_device *cpufreq_dt_pdev, *sunxi_cpufreq_pdev; + +static u32 sun50i_efuse_xlate(const struct sunxi_cpufreq_soc_data *soc_data, + u32 efuse) +{ + return (efuse >> soc_data->nvmem_shift) & soc_data->nvmem_mask; +} + +/** + * sunxi_cpufreq_get_efuse() - Parse and return efuse value present on SoC + * @soc_data: Pointer to sunxi_cpufreq_soc_data context + * @versions: Set to the value parsed from efuse + * + * Returns 0 if success. + */ +static int sunxi_cpufreq_get_efuse(const struct sunxi_cpufreq_soc_data *soc_data, + u32 *versions) +{ + struct nvmem_cell *speedbin_nvmem; + struct device_node *np; + struct device *cpu_dev; + u32 *speedbin; + size_t len; + int ret; + + cpu_dev = get_cpu_device(0); + if (!cpu_dev) + return -ENODEV; + + np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); + if (!np) +
[PATCH v2 0/2] cpufreq: Add sunxi nvmem based CPU scaling driver
Add sunxi nvmem based CPU scaling driver, refers to qcom-cpufreq-kryo. Yangtao Li (2): cpufreq: Add sunxi nvmem based CPU scaling driver dt-bindings: cpufreq: Document operating-points-v2-sunxi-cpu .../bindings/opp/sunxi-nvmem-cpufreq.txt | 166 + MAINTAINERS | 7 + drivers/cpufreq/Kconfig.arm | 10 + drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq-dt-platdev.c | 2 + drivers/cpufreq/sunxi-cpufreq-nvmem.c | 234 ++ 6 files changed, 420 insertions(+) create mode 100644 Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt create mode 100644 drivers/cpufreq/sunxi-cpufreq-nvmem.c --- v2: -update changelog -convert to dev_pm_opp_set_prop_name use instead of dev_pm_opp_set_supported_hw -some change in OPP Node --- 2.17.0
[PATCH v2 2/2] dt-bindings: cpufreq: Document operating-points-v2-sunxi-cpu
Allwinner Process Voltage Scaling Tables defines the voltage and frequency value based on the speedbin blown in the efuse combination. The sunxi-cpufreq-nvmem driver reads the efuse value from the SoC to provide the OPP framework with required information. This is used to determine the voltage and frequency value for each OPP of operating-points-v2 table when it is parsed by the OPP framework. The "operating-points-v2-sunxi-cpu" DT extends the "operating-points-v2" with following parameters: - nvmem-cells (NVMEM area containig the speedbin information) - opp-microvolt-: voltage in micro Volts. At runtime, the platform can pick a and matching opp-microvolt- property Signed-off-by: Yangtao Li --- .../bindings/opp/sunxi-nvmem-cpufreq.txt | 166 ++ 1 file changed, 166 insertions(+) create mode 100644 Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt diff --git a/Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt b/Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt new file mode 100644 index ..c81a2075b974 --- /dev/null +++ b/Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt @@ -0,0 +1,166 @@ +Allwinner Technologies, Inc. NVMEM CPUFreq and OPP bindings +=== + +For some SoCs, the CPU frequency subset and voltage value of each OPP +varies based on the silicon variant in use. Allwinner Process Voltage +Scaling Tables defines the voltage and frequency value based on the +speedbin blown in the efuse combination. The sunxi-cpufreq-nvmem driver +reads the efuse value from the SoC to provide the OPP framework with +required information. + +Required properties: + +In 'cpus' nodes: +- operating-points-v2: Phandle to the operating-points-v2 table to use. + +In 'operating-points-v2' table: +- compatible: Should be + - 'operating-points-v2-sunxi-cpu'. +- nvmem-cells: A phandle pointing to a nvmem-cells node representing the + efuse registers that has information about the + speedbin that is used to select the right frequency/voltage + value pair. + Please refer the for nvmem-cells + bindings Documentation/devicetree/bindings/nvmem/nvmem.txt + and also examples below. + +In every OPP node: +- opp-microvolt-: Voltage in micro Volts. + At runtime, the platform can pick a and + matching opp-microvolt- property. + [See: opp.txt] + +Example 1: +- + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu2: cpu@2 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <2>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu3: cpu@3 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <3>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; +}; + +cpu_opp_table: opp_table { +compatible = "operating-points-v2-sunxi-cpu"; +nvmem-cells = <_efuse>; +opp-shared; + +opp@4
[PATCH v3 0/2] cpufreq: Add sunxi nvmem based CPU scaling driver
Add sunxi nvmem based CPU scaling driver, refers to qcom-cpufreq-kryo. Yangtao Li (2): cpufreq: Add sunxi nvmem based CPU scaling driver dt-bindings: cpufreq: Document allwinner,cpu-operating-points-v2 .../bindings/opp/sunxi-nvmem-cpufreq.txt | 168 + MAINTAINERS | 7 + drivers/cpufreq/Kconfig.arm | 10 + drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq-dt-platdev.c | 2 + drivers/cpufreq/sunxi-cpufreq-nvmem.c | 232 ++ 6 files changed, 420 insertions(+) create mode 100644 Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt create mode 100644 drivers/cpufreq/sunxi-cpufreq-nvmem.c --- v3: -update changelog and title -convert compatibles to allwinner,cpu-operating-points-v2 -document the valid names for opp-microvolt- v2: -update changelog -convert to dev_pm_opp_set_prop_name instead of dev_pm_opp_set_supported_hw -some change in OPP Node --- 2.17.0
[PATCH v3 1/2] cpufreq: Add sunxi nvmem based CPU scaling driver
For some SoCs, the CPU frequency subset and voltage value of each OPP varies based on the silicon variant in use. The sunxi-cpufreq-nvmem driver reads the efuse value from the SoC to provide the OPP framework with required information. Signed-off-by: Yangtao Li --- MAINTAINERS | 7 + drivers/cpufreq/Kconfig.arm | 10 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq-dt-platdev.c | 2 + drivers/cpufreq/sunxi-cpufreq-nvmem.c | 232 ++ 5 files changed, 252 insertions(+) create mode 100644 drivers/cpufreq/sunxi-cpufreq-nvmem.c diff --git a/MAINTAINERS b/MAINTAINERS index 391405091c6b..bfd18ba6aa1a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -667,6 +667,13 @@ S: Maintained F: Documentation/i2c/busses/i2c-ali1563 F: drivers/i2c/busses/i2c-ali1563.c +ALLWINNER CPUFREQ DRIVER +M: Yangtao Li +L: linux...@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt +F: drivers/cpufreq/sunxi-cpufreq-nvmem.c + ALLWINNER SECURITY SYSTEM M: Corentin Labbe L: linux-cry...@vger.kernel.org diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 179a1d302f48..25933c4321a7 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -18,6 +18,16 @@ config ACPI_CPPC_CPUFREQ If in doubt, say N. +config ARM_ALLWINNER_CPUFREQ_NVMEM + tristate "Allwinner nvmem based CPUFreq" + depends on ARCH_SUNXI + depends on NVMEM_SUNXI_SID + select PM_OPP + help + This adds the CPUFreq driver for Allwinner nvmem based SoC. + + If in doubt, say N. + config ARM_ARMADA_37XX_CPUFREQ tristate "Armada 37xx CPUFreq support" depends on ARCH_MVEBU && CPUFREQ_DT diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 689b26c6f949..da28de67613c 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_ARM_SCMI_CPUFREQ)+= scmi-cpufreq.o obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ)+= spear-cpufreq.o obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o +obj-$(CONFIG_ARM_ALLWINNER_CPUFREQ_NVMEM) += sunxi-cpufreq-nvmem.o obj-$(CONFIG_ARM_TANGO_CPUFREQ)+= tango-cpufreq.o obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 47729a22c159..50e7810f3a28 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -105,6 +105,8 @@ static const struct of_device_id whitelist[] __initconst = { * platforms using "operating-points-v2" property. */ static const struct of_device_id blacklist[] __initconst = { + { .compatible = "allwinner,sun50i-h6", }, + { .compatible = "calxeda,highbank", }, { .compatible = "calxeda,ecx-2000", }, diff --git a/drivers/cpufreq/sunxi-cpufreq-nvmem.c b/drivers/cpufreq/sunxi-cpufreq-nvmem.c new file mode 100644 index ..6bf4755d00d9 --- /dev/null +++ b/drivers/cpufreq/sunxi-cpufreq-nvmem.c @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Allwinner CPUFreq nvmem based driver + * + * The sunxi-cpufreq-nvmem driver reads the efuse value from the SoC to + * provide the OPP framework with required information. + * + * Copyright (C) 2019 Yangtao Li + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#define MAX_NAME_LEN 7 + +struct sunxi_cpufreq_soc_data { + u32 (*efuse_xlate)(const struct sunxi_cpufreq_soc_data *soc_data, + u32 efuse); + u32 nvmem_mask; + u32 nvmem_shift; +}; + +static struct platform_device *cpufreq_dt_pdev, *sunxi_cpufreq_pdev; + +static u32 sun50i_efuse_xlate(const struct sunxi_cpufreq_soc_data *soc_data, + u32 efuse) +{ + return (efuse >> soc_data->nvmem_shift) & soc_data->nvmem_mask; +} + +/** + * sunxi_cpufreq_get_efuse() - Parse and return efuse value present on SoC + * @soc_data: Pointer to sunxi_cpufreq_soc_data context + * @versions: Set to the value parsed from efuse + * + * Returns 0 if success. + */ +static int sunxi_cpufreq_get_efuse(const struct sunxi_cpufreq_soc_data *soc_data, + u32 *versions) +{ + struct nvmem_cell *speedbin_nvmem; + struct device_node *np; + struct device *cpu_dev; + u32 *speedbin; + size_t len; + int ret; + + cpu_dev = get_cpu_device(0); + if (!cpu_dev) + return -ENODEV; + + np = dev_pm_opp_of_get_opp_desc_node(cpu_dev); + if (!np) +
[PATCH v3 2/2] dt-bindings: cpufreq: Document allwinner,cpu-operating-points-v2
Allwinner Process Voltage Scaling Tables defines the voltage and frequency value based on the speedbin blown in the efuse combination. The sunxi-cpufreq-nvmem driver reads the efuse value from the SoC to provide the OPP framework with required information. This is used to determine the voltage and frequency value for each OPP of operating-points-v2 table when it is parsed by the OPP framework. The "allwinner,cpu-operating-points-v2" DT extends the "operating-points-v2" with following parameters: - nvmem-cells (NVMEM area containig the speedbin information) - opp-microvolt-: voltage in micro Volts. At runtime, the platform can pick a and matching opp-microvolt- property. HW: : sun50iw-h6 speed0 speed1 speed2 Signed-off-by: Yangtao Li --- .../bindings/opp/sunxi-nvmem-cpufreq.txt | 168 ++ 1 file changed, 168 insertions(+) create mode 100644 Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt diff --git a/Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt b/Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt new file mode 100644 index ..9a1826724b47 --- /dev/null +++ b/Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt @@ -0,0 +1,168 @@ +Allwinner Technologies, Inc. NVMEM CPUFreq and OPP bindings +=== + +For some SoCs, the CPU frequency subset and voltage value of each OPP +varies based on the silicon variant in use. Allwinner Process Voltage +Scaling Tables defines the voltage and frequency value based on the +speedbin blown in the efuse combination. The sunxi-cpufreq-nvmem driver +reads the efuse value from the SoC to provide the OPP framework with +required information. + +Required properties: + +In 'cpus' nodes: +- operating-points-v2: Phandle to the operating-points-v2 table to use. + +In 'operating-points-v2' table: +- compatible: Should be + - 'allwinner,cpu-operating-points-v2'. +- nvmem-cells: A phandle pointing to a nvmem-cells node representing the + efuse registers that has information about the + speedbin that is used to select the right frequency/voltage + value pair. + Please refer the for nvmem-cells + bindings Documentation/devicetree/bindings/nvmem/nvmem.txt + and also examples below. + +In every OPP node: +- opp-microvolt-: Voltage in micro Volts. + At runtime, the platform can pick a and + matching opp-microvolt- property. + [See: opp.txt] + HW: : + sun50iw-h6 speed0 speed1 speed2 + +Example 1: +- + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu2: cpu@2 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <2>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu3: cpu@3 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <3>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; +
[RESEND 1/2] nvmem: sunxi_sid: Support SID on H6
Add support for H6's SID controller. It supports 4K-bit EFUSE, bigger than before. Signed-off-by: Yangtao Li --- drivers/nvmem/sunxi_sid.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index 7013f9cc43c7..a079a80ddf2c 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -188,6 +188,11 @@ static const struct sunxi_sid_cfg sun50i_a64_cfg = { .size = 0x100, }; +static const struct sunxi_sid_cfg sun50i_h6_cfg = { + .value_offset = 0x200, + .size = 0x200, +}; + static const struct of_device_id sunxi_sid_of_match[] = { { .compatible = "allwinner,sun4i-a10-sid", .data = _a10_cfg }, { .compatible = "allwinner,sun7i-a20-sid", .data = _a20_cfg }, @@ -195,6 +200,7 @@ static const struct of_device_id sunxi_sid_of_match[] = { { .compatible = "allwinner,sun8i-h3-sid", .data = _h3_cfg }, { .compatible = "allwinner,sun50i-a64-sid", .data = _a64_cfg }, { .compatible = "allwinner,sun50i-h5-sid", .data = _a64_cfg }, + { .compatible = "allwinner,sun50i-h6-sid", .data = _h6_cfg }, {/* sentinel */}, }; MODULE_DEVICE_TABLE(of, sunxi_sid_of_match); -- 2.17.0
[RESEND 2/2] arm64: dts: sunxi: h6: Add device node for SID
The device tree binding already lists compatible strings for H6 SoCs, so add a device node for iy. Signed-off-by: Yangtao Li --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 5 + 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index c9e861a50a63..cbeb587d2eed 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -192,6 +192,11 @@ #reset-cells = <1>; }; + sid: sid@3006000 { + compatible = "allwinner,sun50i-h6-sid"; + reg = <0x3006000 0x400>; + }; + pio: pinctrl@300b000 { compatible = "allwinner,sun50i-h6-pinctrl"; reg = <0x0300b000 0x400>; -- 2.17.0
[RESEND 0/2] nvmem: sunxi-sid: add SID controller support for H6
Add SID's support for H6. Yangtao Li (2): nvmem: sunxi_sid: Support SID on H6 arm64: dts: sunxi: h6: Add device node for SID arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 5 + drivers/nvmem/sunxi_sid.c| 6 ++ 2 files changed, 11 insertions(+) -- 2.17.0
[RESEND 2/2] arm64: dts: sunxi: h6: Add device node for SID
The device tree binding already lists compatible strings for H6 SoC, so add a device node for it. Signed-off-by: Yangtao Li --- fix typo: iy->it 0x3006000->0x03006000 --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 5 + 1 file changed, 5 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index c9e861a50a63..cbeb587d2eed 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -192,6 +192,11 @@ #reset-cells = <1>; }; + sid: sid@3006000 { + compatible = "allwinner,sun50i-h6-sid"; + reg = <0x03006000 0x400>; + }; + pio: pinctrl@300b000 { compatible = "allwinner,sun50i-h6-pinctrl"; reg = <0x0300b000 0x400>; -- 2.17.0
[PATCH 2/2] dt-bindings: cpufreq: Document operating-points-v2-sunxi-cpu
Allwinner Process Voltage Scaling Tables defines the voltage and frequency value based on the speedbin blown in the efuse combination. The sunxi-cpufreq-nvmem driver reads the efuse value from the SoC to provide the OPP framework with required information. This is used to determine the voltage and frequency value for each OPP of operating-points-v2 table when it is parsed by the OPP framework. This change adds documentation for the DT bindings. The "operating-points-v2-sunxi-cpu" DT extends the "operating-points-v2" with following parameters: - nvmem-cells (NVMEM area containig the speedbin information) - opp-supported-hw: A single 32 bit bitmap value, representing compatible HW: 0: speedbin 0 1: speedbin 1 2: speedbin 2 3-31: unused Signed-off-by: Yangtao Li --- .../bindings/opp/sunxi-nvmem-cpufreq.txt | 235 ++ 1 file changed, 235 insertions(+) create mode 100644 Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt diff --git a/Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt b/Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt new file mode 100644 index ..80201d4e5147 --- /dev/null +++ b/Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt @@ -0,0 +1,235 @@ +Allwinner Technologies, Inc. NVMEM CPUFreq and OPP bindings +=== + +For some SoCs, the CPU frequency subset and voltage value of each OPP +varies based on the silicon variant in use. Allwinner Process Voltage +Scaling Tables defines the voltage and frequency value based on the +speedbin blown in the efuse combination. The sunxi-cpufreq-nvmem driver +reads the efuse value from the SoC to provide the OPP framework with +required information. + +Required properties: + +In 'cpus' nodes: +- operating-points-v2: Phandle to the operating-points-v2 table to use. + +In 'operating-points-v2' table: +- compatible: Should be + - 'operating-points-v2-sunxi-cpu'. +- nvmem-cells: A phandle pointing to a nvmem-cells node representing the + efuse registers that has information about the + speedbin that is used to select the right frequency/voltage + value pair. + Please refer the for nvmem-cells + bindings Documentation/devicetree/bindings/nvmem/nvmem.txt + and also examples below. + +In every OPP node: +- opp-supported-hw: A single 32 bit bitmap value, representing compatible HW. + Bitmap: + 0: speedbin 0 + 1: speedbin 1 + 2: speedbin 2 + 3-31: unused + +Example 1: +- + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu2: cpu@2 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <2>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + + cpu3: cpu@3 { + compatible = "arm,cortex-a53"; + device_type = "cpu"; + reg = <3>; + enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <
[PATCH 0/2] cpufreq: Add sunxi nvmem based CPU scaling driver
Add sunxi nvmem based CPU scaling driver, refers to qcom-cpufreq-kryo. Yangtao Li (2): cpufreq: Add sunxi nvmem based CPU scaling driver dt-bindings: cpufreq: Document operating-points-v2-sunxi-cpu .../bindings/opp/sunxi-nvmem-cpufreq.txt | 235 + MAINTAINERS | 7 + drivers/cpufreq/Kconfig.arm | 10 + drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq-dt-platdev.c | 2 + drivers/cpufreq/sunxi-cpufreq-nvmem.c | 236 ++ 6 files changed, 491 insertions(+) create mode 100644 Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt create mode 100644 drivers/cpufreq/sunxi-cpufreq-nvmem.c -- 2.17.0
[PATCH 1/2] cpufreq: Add sunxi nvmem based CPU scaling driver
For some SoCs, the CPU frequency subset and voltage value of each OPP varies based on the silicon variant in use. Allwinner Process Voltage Scaling Tables defines the voltage and frequency value based on the speedbin blown in the efuse combination. The sunxi-cpufreq-nvmem driver reads the efuse value from the SoC to provide the OPP framework with required information. Signed-off-by: Yangtao Li --- MAINTAINERS | 7 + drivers/cpufreq/Kconfig.arm | 10 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq-dt-platdev.c | 2 + drivers/cpufreq/sunxi-cpufreq-nvmem.c | 236 ++ 5 files changed, 256 insertions(+) create mode 100644 drivers/cpufreq/sunxi-cpufreq-nvmem.c diff --git a/MAINTAINERS b/MAINTAINERS index 391405091c6b..bfd18ba6aa1a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -667,6 +667,13 @@ S: Maintained F: Documentation/i2c/busses/i2c-ali1563 F: drivers/i2c/busses/i2c-ali1563.c +ALLWINNER CPUFREQ DRIVER +M: Yangtao Li +L: linux...@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/opp/sunxi-nvmem-cpufreq.txt +F: drivers/cpufreq/sunxi-cpufreq-nvmem.c + ALLWINNER SECURITY SYSTEM M: Corentin Labbe L: linux-cry...@vger.kernel.org diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 179a1d302f48..25933c4321a7 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -18,6 +18,16 @@ config ACPI_CPPC_CPUFREQ If in doubt, say N. +config ARM_ALLWINNER_CPUFREQ_NVMEM + tristate "Allwinner nvmem based CPUFreq" + depends on ARCH_SUNXI + depends on NVMEM_SUNXI_SID + select PM_OPP + help + This adds the CPUFreq driver for Allwinner nvmem based SoC. + + If in doubt, say N. + config ARM_ARMADA_37XX_CPUFREQ tristate "Armada 37xx CPUFreq support" depends on ARCH_MVEBU && CPUFREQ_DT diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 689b26c6f949..da28de67613c 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_ARM_SCMI_CPUFREQ)+= scmi-cpufreq.o obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ)+= spear-cpufreq.o obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o +obj-$(CONFIG_ARM_ALLWINNER_CPUFREQ_NVMEM) += sunxi-cpufreq-nvmem.o obj-$(CONFIG_ARM_TANGO_CPUFREQ)+= tango-cpufreq.o obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 47729a22c159..50e7810f3a28 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -105,6 +105,8 @@ static const struct of_device_id whitelist[] __initconst = { * platforms using "operating-points-v2" property. */ static const struct of_device_id blacklist[] __initconst = { + { .compatible = "allwinner,sun50i-h6", }, + { .compatible = "calxeda,highbank", }, { .compatible = "calxeda,ecx-2000", }, diff --git a/drivers/cpufreq/sunxi-cpufreq-nvmem.c b/drivers/cpufreq/sunxi-cpufreq-nvmem.c new file mode 100644 index ..e189f94592d5 --- /dev/null +++ b/drivers/cpufreq/sunxi-cpufreq-nvmem.c @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Allwinner CPUFreq nvmem based driver + * + * Copyright (C) 2019 Yangtao Li + */ + +/* + * For some SoCs, the CPU frequency subset and voltage value of each OPP + * varies based on the silicon variant in use. Allwinner Process Voltage + * Scaling Tables defines the voltage and frequency value based on the + * speedbin blown in the efuse combination. The sunxi-cpufreq-nvmem driver + * reads the efuse value from the SoC to provide the OPP framework with + * required information. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +struct sunxi_cpufreq_soc_data { + u32 (*efuse_xlate)(const struct sunxi_cpufreq_soc_data *soc_data, + u32 efuse); + u32 nvmem_mask; + u32 nvmem_shift; +}; + +static struct platform_device *cpufreq_dt_pdev, *sunxi_cpufreq_pdev; + +static u32 sun50i_efuse_xlate(const struct sunxi_cpufreq_soc_data *soc_data, + u32 efuse) +{ + return 1 << (efuse >> soc_data->nvmem_shift) & soc_data->nvmem_mask; +} + +/** + * sunxi_cpufreq_get_efuse() - Parse and return efuse value present on SoC + * @soc_data: pointer to sunxi_cpufreq_soc_data context + * @versions: Set to the value parsed from efuse + * + * Returns 0 if success. + */ +static int sunxi_cpufreq_get_efuse(const struct sunxi_cpufreq_soc_data *soc_data, +
[PATVH v2 2/4] arm64: dts: allwinner: h6: pine: Add CPU supply regulator
The original pine use the dcdca to supply the CPU cores. According to the axp805 spec, the range of dcdca is 0.6 to 1.1v, 1.12 to 1.52v. In order to support more CPU frequency, slightly increase the voltage maximum and minimum. In fact, in sunxi's sdk, the actual minimum and maximum voltage of the cpu is smaller or larger than the datasheet. For some better quality ic, the minimum voltage can be smaller. For some poor quality ic, the maximum voltage needs to be increased a little. Signed-off-by: Yangtao Li --- arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts index bdb8470fc8dc..95c81250c2b3 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts @@ -213,8 +213,8 @@ reg_dcdca: dcdca { regulator-always-on; - regulator-min-microvolt = <81>; - regulator-max-microvolt = <108>; + regulator-min-microvolt = <80>; + regulator-max-microvolt = <116>; regulator-name = "vdd-cpu"; }; @@ -251,6 +251,10 @@ }; }; + { + cpu-supply = <_dcdca>; +}; + { pinctrl-names = "default"; pinctrl-0 = <_ph_pins>; -- 2.17.0
[PATVH v2 4/4] arm64: dts: allwinner: h6: Add CPU Operating Performance Points table
Add an OPP (Operating Performance Points) table for the CPU cores to enable DVFS (Dynamic Voltage & Frequency Scaling) on the H6. This information comes from github. When the four CPUs are running at 1.8 GHz, 100% busy, it is easy to heat up and make the system restart. And currently H6 does not support the thermal driver, can not get the temperature information of the cpu to control the highest frequency. So temporarily remove the opp of 1.8GHz. When the four CPUs operate at 1.4 GHz, 100% busy, the temperature is stable at about 90 degrees, and the system can still operate normally. Signed-off-by: Yangtao Li --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 55 1 file changed, 55 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 723f5d991a74..84fb47062fe6 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -28,6 +28,8 @@ enable-method = "psci"; clocks = < CLK_CPUX>; clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; }; cpu1: cpu@1 { @@ -37,6 +39,8 @@ enable-method = "psci"; clocks = < CLK_CPUX>; clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; }; cpu2: cpu@2 { @@ -46,6 +50,8 @@ enable-method = "psci"; clocks = < CLK_CPUX>; clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; }; cpu3: cpu@3 { @@ -55,6 +61,55 @@ enable-method = "psci"; clocks = < CLK_CPUX>; clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + }; + + cpu_opp_table: opp_table { + compatible = "operating-points-v2"; + opp-shared; + + opp@48000 { + opp-hz = /bits/ 64 <48000>; + opp-microvolt = <80 80 88>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@72000 { + opp-hz = /bits/ 64 <72000>; + opp-microvolt = <80 80 88>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@81600 { + opp-hz = /bits/ 64 <81600>; + opp-microvolt = <80 80 88>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@88800 { + opp-hz = /bits/ 64 <88800>; + opp-microvolt = <80 80 94>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@108000 { + opp-hz = /bits/ 64 <108000>; + opp-microvolt = <84 84 106>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@132000 { + opp-hz = /bits/ 64 <132000>; + opp-microvolt = <90 90 116>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@148800 { + opp-hz = /bits/ 64 <148800>; + opp-microvolt = <96 96 116>; + clock-latency-ns = <244144>; /* 8 32k periods */ }; }; -- 2.17.0
[PATVH v2 1/4] arm64: dts: allwinner: h6: orangepi: Add CPU supply regulator
The original orangepi use the dcdca to supply the CPU cores. According to the axp805 spec, the range of dcdca is 0.6 to 1.1v, 1.12 to 1.52v. In order to support more CPU frequency, slightly increase the voltage maximum and minimum. In fact, in sunxi's sdk, the actual minimum and maximum voltage of the cpu is smaller or larger than the datasheet. For some better quality ic, the minimum voltage can be smaller. For some poor quality ic, the maximum voltage needs to be increased a little. Signed-off-by: Yangtao Li --- arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi index b2526dac2fcf..e7aebaf91ede 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi @@ -159,8 +159,8 @@ reg_dcdca: dcdca { regulator-always-on; - regulator-min-microvolt = <81>; - regulator-max-microvolt = <108>; + regulator-min-microvolt = <80>; + regulator-max-microvolt = <116>; regulator-name = "vdd-cpu"; }; @@ -191,6 +191,10 @@ }; }; + { + cpu-supply = <_dcdca>; +}; + { pinctrl-names = "default"; pinctrl-0 = <_ph_pins>; -- 2.17.0
[PATVH v2 0/4] arm64: dts: allwinner: h6: Enable CPU
Add the cpufreq support of h6, source of information is as follows. h6 cpu opp info: https://github.com/Allwinner-Homlet/H6-BSP4.9-linux/blob/master/arch/arm64/boot/dts/sunxi/sun50iw6p1.dtsi axp805 spec: http://linux-sunxi.org/images/b/bc/AXP805_Datasheet_V1.0_en.pdf Yangtao Li (4): arm64: dts: allwinner: h6: orangepi: Add CPU supply regulator arm64: dts: allwinner: h6: pine: Add CPU supply regulator arm64: dts: allwinner: h6: Add clock to CPU cores arm64: dts: allwinner: h6: Add CPU Operating Performance Points table .../dts/allwinner/sun50i-h6-orangepi.dtsi | 8 ++- .../boot/dts/allwinner/sun50i-h6-pine-h64.dts | 8 ++- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 63 +++ 3 files changed, 75 insertions(+), 4 deletions(-) -- 2.17.0
[PATVH v2 3/4] arm64: dts: allwinner: h6: Add clock to CPU cores
The ARM CPU cores are fed by the CPU clock from the CCU. Add a reference to the clock for each CPU core, along with the clock transition latency. Signed-off-by: Yangtao Li --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 8 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index d93a7add67e7..723f5d991a74 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -26,6 +26,8 @@ device_type = "cpu"; reg = <0>; enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ }; cpu1: cpu@1 { @@ -33,6 +35,8 @@ device_type = "cpu"; reg = <1>; enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ }; cpu2: cpu@2 { @@ -40,6 +44,8 @@ device_type = "cpu"; reg = <2>; enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ }; cpu3: cpu@3 { @@ -47,6 +53,8 @@ device_type = "cpu"; reg = <3>; enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ }; }; -- 2.17.0
[PATCH v3 0/4] arm64: dts: allwinner: h6: Enable CPU DVFS(cpufreq)
Add the cpufreq information of h6 to dts, source of information is as follows. h6 cpu opp info: https://github.com/Allwinner-Homlet/H6-BSP4.9-linux/blob/master/arch/arm64/boot/dts/sunxi/sun50iw6p1.dtsi axp805 spec: http://linux-sunxi.org/images/b/bc/AXP805_Datasheet_V1.0_en.pdf Yangtao Li (4): arm64: dts: allwinner: h6: orangepi: Add CPU supply regulator arm64: dts: allwinner: h6: pine: Add CPU supply regulator arm64: dts: allwinner: h6: Add clock to CPU cores arm64: dts: allwinner: h6: Add CPU Operating Performance Points table --- v3: -only update changelog between version v2: -remove the opp of 1.8GHz -update changelog I tested the opp table on two H6 boards(with the same axp805 pmu), but not the pine board or orangepi board. --- .../dts/allwinner/sun50i-h6-orangepi.dtsi | 8 ++- .../boot/dts/allwinner/sun50i-h6-pine-h64.dts | 8 ++- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 63 +++ 3 files changed, 75 insertions(+), 4 deletions(-) -- 2.17.0
[PATCH v3 1/4] arm64: dts: allwinner: h6: orangepi: Add CPU supply regulator
The original orangepi use the dcdca to supply the CPU cores. According to the axp805 spec, the range of dcdca is 0.6 to 1.1v, 1.12 to 1.52v. In order to support more CPU frequency, slightly increase the voltage maximum and minimum. In fact, in sunxi's sdk, the actual minimum and maximum voltage of the cpu is smaller or larger than the datasheet. For some better quality ic, the minimum voltage can be smaller. For some poor quality ic, the maximum voltage needs to be increased a little. Signed-off-by: Yangtao Li --- arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi index b2526dac2fcf..e7aebaf91ede 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi @@ -159,8 +159,8 @@ reg_dcdca: dcdca { regulator-always-on; - regulator-min-microvolt = <81>; - regulator-max-microvolt = <108>; + regulator-min-microvolt = <80>; + regulator-max-microvolt = <116>; regulator-name = "vdd-cpu"; }; @@ -191,6 +191,10 @@ }; }; + { + cpu-supply = <_dcdca>; +}; + { pinctrl-names = "default"; pinctrl-0 = <_ph_pins>; -- 2.17.0
[PATCH v3 4/4] arm64: dts: allwinner: h6: Add CPU Operating Performance Points table
Add an OPP (Operating Performance Points) table for the CPU cores to enable DVFS (Dynamic Voltage & Frequency Scaling) on the H6. This information comes from github. When the four CPUs are running at 1.8 GHz, 100% busy, it is easy to heat up and make the system restart. And currently H6 does not support the thermal driver, can not get the temperature information of the cpu to control the highest frequency. So temporarily remove the opp of 1.8GHz. When the four CPUs operate at 1.4 GHz, 100% busy, the temperature is stable at about 90 degrees, and the system can still operate normally. Signed-off-by: Yangtao Li --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 55 1 file changed, 55 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 723f5d991a74..84fb47062fe6 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -28,6 +28,8 @@ enable-method = "psci"; clocks = < CLK_CPUX>; clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; }; cpu1: cpu@1 { @@ -37,6 +39,8 @@ enable-method = "psci"; clocks = < CLK_CPUX>; clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; }; cpu2: cpu@2 { @@ -46,6 +50,8 @@ enable-method = "psci"; clocks = < CLK_CPUX>; clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; }; cpu3: cpu@3 { @@ -55,6 +61,55 @@ enable-method = "psci"; clocks = < CLK_CPUX>; clock-latency-ns = <244144>; /* 8 32k periods */ + operating-points-v2 = <_opp_table>; + #cooling-cells = <2>; + }; + }; + + cpu_opp_table: opp_table { + compatible = "operating-points-v2"; + opp-shared; + + opp@48000 { + opp-hz = /bits/ 64 <48000>; + opp-microvolt = <80 80 88>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@72000 { + opp-hz = /bits/ 64 <72000>; + opp-microvolt = <80 80 88>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@81600 { + opp-hz = /bits/ 64 <81600>; + opp-microvolt = <80 80 88>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@88800 { + opp-hz = /bits/ 64 <88800>; + opp-microvolt = <80 80 94>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@108000 { + opp-hz = /bits/ 64 <108000>; + opp-microvolt = <84 84 106>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@132000 { + opp-hz = /bits/ 64 <132000>; + opp-microvolt = <90 90 116>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + opp@148800 { + opp-hz = /bits/ 64 <148800>; + opp-microvolt = <96 96 116>; + clock-latency-ns = <244144>; /* 8 32k periods */ }; }; -- 2.17.0
[PATCH v3 3/4] arm64: dts: allwinner: h6: Add clock to CPU cores
The ARM CPU cores are fed by the CPU clock from the CCU. Add a reference to the clock for each CPU core, along with the clock transition latency. Signed-off-by: Yangtao Li --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 8 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index d93a7add67e7..723f5d991a74 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -26,6 +26,8 @@ device_type = "cpu"; reg = <0>; enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ }; cpu1: cpu@1 { @@ -33,6 +35,8 @@ device_type = "cpu"; reg = <1>; enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ }; cpu2: cpu@2 { @@ -40,6 +44,8 @@ device_type = "cpu"; reg = <2>; enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ }; cpu3: cpu@3 { @@ -47,6 +53,8 @@ device_type = "cpu"; reg = <3>; enable-method = "psci"; + clocks = < CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ }; }; -- 2.17.0
[PATCH v3 2/4] arm64: dts: allwinner: h6: pine: Add CPU supply regulator
The original pine use the dcdca to supply the CPU cores. According to the axp805 spec, the range of dcdca is 0.6 to 1.1v, 1.12 to 1.52v. In order to support more CPU frequency, slightly increase the voltage maximum and minimum. In fact, in sunxi's sdk, the actual minimum and maximum voltage of the cpu is smaller or larger than the datasheet. For some better quality ic, the minimum voltage can be smaller. For some poor quality ic, the maximum voltage needs to be increased a little. Signed-off-by: Yangtao Li --- arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts index bdb8470fc8dc..95c81250c2b3 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts @@ -213,8 +213,8 @@ reg_dcdca: dcdca { regulator-always-on; - regulator-min-microvolt = <81>; - regulator-max-microvolt = <108>; + regulator-min-microvolt = <80>; + regulator-max-microvolt = <116>; regulator-name = "vdd-cpu"; }; @@ -251,6 +251,10 @@ }; }; + { + cpu-supply = <_dcdca>; +}; + { pinctrl-names = "default"; pinctrl-0 = <_ph_pins>; -- 2.17.0
[PATCH 0/3] PM / devfreq: do some cleanup
The informations come from the coccinelle tool. drivers/devfreq/tegra-devfreq.c:577:5-8: Unneeded variable: "ret". Return "0" on line 603 drivers/devfreq/rk3399_dmc.c:325:2-3: Unneeded semicolon drivers/devfreq/event/rockchip-dfi.c:214:2-3: Unneeded semicolon Yangtao Li (3): PM / devfreq: rk3399_dmc: remove unneeded semicolon PM / devfreq: rockchip-dfi: remove unneeded semicolon PM / devfreq: tegra: remove unneeded variable drivers/devfreq/event/rockchip-dfi.c | 2 +- drivers/devfreq/rk3399_dmc.c | 2 +- drivers/devfreq/tegra-devfreq.c | 7 ++- 3 files changed, 4 insertions(+), 7 deletions(-) -- 2.17.0
[PATCH 2/3] PM / devfreq: rockchip-dfi: remove unneeded semicolon
The semicolon is unneeded, so remove it. Signed-off-by: Yangtao Li --- drivers/devfreq/event/rockchip-dfi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c index 22b113363ffc..fcbf76ebf55d 100644 --- a/drivers/devfreq/event/rockchip-dfi.c +++ b/drivers/devfreq/event/rockchip-dfi.c @@ -211,7 +211,7 @@ static int rockchip_dfi_probe(struct platform_device *pdev) if (IS_ERR(data->clk)) { dev_err(dev, "Cannot get the clk dmc_clk\n"); return PTR_ERR(data->clk); - }; + } /* try to find the optional reference to the pmu syscon */ node = of_parse_phandle(np, "rockchip,pmu", 0); -- 2.17.0
[PATCH 1/3] PM / devfreq: rk3399_dmc: remove unneeded semicolon
The semicolon is unneeded, so remove it. Signed-off-by: Yangtao Li --- drivers/devfreq/rk3399_dmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c index e795ad2b3f6b..a228dad2bee4 100644 --- a/drivers/devfreq/rk3399_dmc.c +++ b/drivers/devfreq/rk3399_dmc.c @@ -322,7 +322,7 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev) dev_err(dev, "Cannot get the clk dmc_clk\n"); return PTR_ERR(data->dmc_clk); - }; + } data->edev = devfreq_event_get_edev_by_phandle(dev, 0); if (IS_ERR(data->edev)) -- 2.17.0
[PATCH 3/3] PM / devfreq: tegra: remove unneeded variable
This variable is not used after initialization, so remove it. And in order to unify the code style, move the location where the dev_get_drvdata is called by the way. Signed-off-by: Yangtao Li --- drivers/devfreq/tegra-devfreq.c | 7 ++- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c index c59d2eee5d30..c89ba7b834ff 100644 --- a/drivers/devfreq/tegra-devfreq.c +++ b/drivers/devfreq/tegra-devfreq.c @@ -573,10 +573,7 @@ static int tegra_governor_get_target(struct devfreq *devfreq, static int tegra_governor_event_handler(struct devfreq *devfreq, unsigned int event, void *data) { - struct tegra_devfreq *tegra; - int ret = 0; - - tegra = dev_get_drvdata(devfreq->dev.parent); + struct tegra_devfreq *tegra = dev_get_drvdata(devfreq->dev.parent); switch (event) { case DEVFREQ_GOV_START: @@ -600,7 +597,7 @@ static int tegra_governor_event_handler(struct devfreq *devfreq, break; } - return ret; + return 0; } static struct devfreq_governor tegra_devfreq_governor = { -- 2.17.0
[PATCH 0/2] cpufreq: do some cleanup
The informations come from the coccinelle tool. drivers/cpufreq/longhaul.c:854:2-3: Unneeded semicolon drivers/cpufreq/pcc-cpufreq.c:271:2-3: Unneeded semicolon Yangtao Li (2): cpufreq: pcc-cpufreq: remove unneeded semicolon cpufreq: longhaul: remove unneeded semicolon drivers/cpufreq/longhaul.c| 2 +- drivers/cpufreq/pcc-cpufreq.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) -- 2.17.0
[PATCH 2/2] cpufreq: longhaul: remove unneeded semicolon
The semicolon is unneeded, so remove it. Signed-off-by: Yangtao Li --- drivers/cpufreq/longhaul.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 279bd9e9fa95..fb546e0d0356 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -851,7 +851,7 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy) case TYPE_POWERSAVER: pr_cont("Powersaver supported\n"); break; - }; + } /* Doesn't hurt */ longhaul_setup_southbridge(); -- 2.17.0
[PATCH 1/2] cpufreq: pcc-cpufreq: remove unneeded semicolon
The semicolon is unneeded, so remove it. Signed-off-by: Yangtao Li --- drivers/cpufreq/pcc-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 099a849396f6..1e5e64643c3a 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -268,7 +268,7 @@ static int pcc_get_offset(int cpu) if (!pccp || pccp->type != ACPI_TYPE_PACKAGE) { ret = -ENODEV; goto out_free; - }; + } offset = &(pccp->package.elements[0]); if (!offset || offset->type != ACPI_TYPE_INTEGER) { -- 2.17.0
[PATCH] cpufreq: speedstep: convert BUG() to BUG_ON()
To fix coccinelle WARNING. WARNING: Use BUG_ON instead of if condition followed by BUG. Signed-off-by: Yangtao Li --- drivers/cpufreq/speedstep-ich.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index fbbcb88db061..5d8a09b82efb 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c @@ -243,8 +243,7 @@ static unsigned int speedstep_get(unsigned int cpu) unsigned int speed; /* You're supposed to ensure CPU is online. */ - if (smp_call_function_single(cpu, get_freq_data, , 1) != 0) - BUG(); + BUG_ON(smp_call_function_single(cpu, get_freq_data, , 1)); pr_debug("detected %u kHz as current frequency\n", speed); return speed; -- 2.17.0
[PATCH] cpufreq: scmi: fix use-after-free in scmi_cpufreq_exit()
This issue was detected with the help of Coccinelle. So change the order of function calls to fix it. Fixes: 1690d8bb91e37 (cpufreq: scpi/scmi: Fix freeing of dynamic OPPs) Signed-off-by: Yangtao Li --- drivers/cpufreq/scmi-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c index 242c3370544e..9ed46d188cb5 100644 --- a/drivers/cpufreq/scmi-cpufreq.c +++ b/drivers/cpufreq/scmi-cpufreq.c @@ -187,8 +187,8 @@ static int scmi_cpufreq_exit(struct cpufreq_policy *policy) cpufreq_cooling_unregister(priv->cdev); dev_pm_opp_free_cpufreq_table(priv->cpu_dev, >freq_table); - kfree(priv); dev_pm_opp_remove_all_dynamic(priv->cpu_dev); + kfree(priv); return 0; } -- 2.17.0
[PATCH] cpufreq: powernv: fix missing check of return value in init_powernv_pstates()
kmalloc() could fail, so insert a check of its return value. And if it fails, returns -ENOMEM. And remove (struct pstate_idx_revmap_data *) to fix coccinelle WARNING by the way. WARNING: casting value returned by memory allocation function to (struct pstate_idx_revmap_data *) is useless. Signed-off-by: Yangtao Li --- drivers/cpufreq/powernv-cpufreq.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 7e7ad3879c4e..d2230812fa4b 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -244,6 +244,7 @@ static int init_powernv_pstates(void) u32 len_ids, len_freqs; u32 pstate_min, pstate_max, pstate_nominal; u32 pstate_turbo, pstate_ultra_turbo; + int rc = -ENODEV; power_mgt = of_find_node_by_path("/ibm,opal/power-mgt"); if (!power_mgt) { @@ -327,8 +328,11 @@ static int init_powernv_pstates(void) powernv_freqs[i].frequency = freq * 1000; /* kHz */ powernv_freqs[i].driver_data = id & 0xFF; - revmap_data = (struct pstate_idx_revmap_data *) - kmalloc(sizeof(*revmap_data), GFP_KERNEL); + revmap_data = kmalloc(sizeof(*revmap_data), GFP_KERNEL); + if (!revmap_data) { + rc = -ENOMEM; + goto out; + } revmap_data->pstate_id = id & 0xFF; revmap_data->cpufreq_table_idx = i; @@ -357,7 +361,7 @@ static int init_powernv_pstates(void) return 0; out: of_node_put(power_mgt); - return -ENODEV; + return rc; } /* Returns the CPU frequency corresponding to the pstate_id. */ -- 2.17.0
[PATCH 1/5] nvmem: sunxi-sid: fix wrong description in kernel doc
qfprom->sunxi-sid Signed-off-by: Yangtao Li --- Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt index 99c4ba6a3f61..d37017e343b1 100644 --- a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt +++ b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt @@ -12,7 +12,7 @@ Required properties: - reg: Should contain registers location and length = Data cells = -Are child nodes of qfprom, bindings of which as described in +Are child nodes of sunxi-sid, bindings of which as described in bindings/nvmem/nvmem.txt Example for sun4i: -- 2.17.0
[PATCH 0/5] nvmem: sunxi-sid: add SID controller support for H5 and H6
Add SID controller support for H5 and H6, and do some cleanup without functional changes. Yangtao Li (5): nvmem: sunxi-sid: fix wrong description in kernel doc nvmem: sunxi-sid: add support for H5's SID controller nvmem: sunxi-sid: add binding for H6's SID controller nvmem: sunxi-sid: add support for H6's SID controller nvmem: sunxi-sid: convert to SPDX license tags .../bindings/nvmem/allwinner,sunxi-sid.txt| 3 ++- drivers/nvmem/sunxi_sid.c | 23 +++ 2 files changed, 15 insertions(+), 11 deletions(-) -- 2.17.0
[PATCH 2/5] nvmem: sunxi-sid: add support for H5's SID controller
Add support for H5's SID controller. Signed-off-by: Yangtao Li --- drivers/nvmem/sunxi_sid.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index 570a2e354f30..036029e90921 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -219,11 +219,17 @@ static const struct sunxi_sid_cfg sun50i_a64_cfg = { .size = 0x100, }; +static const struct sunxi_sid_cfg sun50i_h5_cfg = { + .value_offset = 0x200, + .size = 0x100, +}; + static const struct of_device_id sunxi_sid_of_match[] = { { .compatible = "allwinner,sun4i-a10-sid", .data = _a10_cfg }, { .compatible = "allwinner,sun7i-a20-sid", .data = _a20_cfg }, { .compatible = "allwinner,sun8i-h3-sid", .data = _h3_cfg }, { .compatible = "allwinner,sun50i-a64-sid", .data = _a64_cfg }, + { .compatible = "allwinner,sun50i-h5-sid", .data = _h5_cfg }, {/* sentinel */}, }; MODULE_DEVICE_TABLE(of, sunxi_sid_of_match); -- 2.17.0
[PATCH 5/5] nvmem: sunxi-sid: convert to SPDX license tags
Updates license to use SPDX-License-Identifier. Signed-off-by: Yangtao Li --- drivers/nvmem/sunxi_sid.c | 11 +-- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index 8692b58d76ce..f56c9f713cb4 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -1,18 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Allwinner sunXi SoCs Security ID support. * * Copyright (c) 2013 Oliver Schinagl * Copyright (C) 2014 Maxime Ripard - * - * 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 -- 2.17.0
[PATCH 3/5] nvmem: sunxi-sid: add binding for H6's SID controller
Add a binding for H6's SID controller. Signed-off-by: Yangtao Li --- Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt index d37017e343b1..cfb18b4ef8f7 100644 --- a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt +++ b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt @@ -8,6 +8,7 @@ Required properties: "allwinner,sun8i-h3-sid" "allwinner,sun50i-a64-sid" "allwinner,sun50i-h5-sid" + "allwinner,sun50i-h6-sid" - reg: Should contain registers location and length -- 2.17.0
[PATCH 4/5] nvmem: sunxi-sid: add support for H6's SID controller
Add support for H6's SID controller. It supports 4K-bit EFUSE, bigger than before. Signed-off-by: Yangtao Li --- drivers/nvmem/sunxi_sid.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index 036029e90921..8692b58d76ce 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -224,12 +224,18 @@ static const struct sunxi_sid_cfg sun50i_h5_cfg = { .size = 0x100, }; +static const struct sunxi_sid_cfg sun50i_h6_cfg = { + .value_offset = 0x200, + .size = 0x200, +}; + static const struct of_device_id sunxi_sid_of_match[] = { { .compatible = "allwinner,sun4i-a10-sid", .data = _a10_cfg }, { .compatible = "allwinner,sun7i-a20-sid", .data = _a20_cfg }, { .compatible = "allwinner,sun8i-h3-sid", .data = _h3_cfg }, { .compatible = "allwinner,sun50i-a64-sid", .data = _a64_cfg }, { .compatible = "allwinner,sun50i-h5-sid", .data = _h5_cfg }, + { .compatible = "allwinner,sun50i-h6-sid", .data = _h6_cfg }, {/* sentinel */}, }; MODULE_DEVICE_TABLE(of, sunxi_sid_of_match); -- 2.17.0
[PATCH] clocksource: arm_arch_timer: remove unneeded pr_fmt macro
After this commit ded24019b6b6f(clocksource: arm_arch_timer: clean up printk usage), the previous macro is redundant, so delete it. And move the new macro to the previous position. Signed-off-by: Yangtao Li --- drivers/clocksource/arm_arch_timer.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 9a7d4dc00b6e..675243eb8cd4 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -9,7 +9,7 @@ * published by the Free Software Foundation. */ -#define pr_fmt(fmt)"arm_arch_timer: " fmt +#define pr_fmt(fmt)"arch_timer: " fmt #include #include @@ -33,9 +33,6 @@ #include -#undef pr_fmt -#define pr_fmt(fmt) "arch_timer: " fmt - #define CNTTIDR0x08 #define CNTTIDR_VIRT(n)(BIT(1) << ((n) * 4)) -- 2.17.0
[PATCH] of: thermal: Improve print information
Define pr_fmt macro to add a prefix to the message, this can make the thermal log better recognized. Before: [0.602672] nfc: nfc_init: NFC Core ver 0.1 [0.602828] NET: Registered protocol family 39 [0.603435] clocksource: Switched to clocksource mct-frc [0.746216] failed to build thermal zone cpu-thermal: -22 [0.746451] NET: Registered protocol family 2 After: [0.602804] NET: Registered protocol family 39 [0.603463] clocksource: Switched to clocksource mct-frc [0.746309] thermal_sys: failed to build thermal zone cpu-thermal: -22 [0.746545] NET: Registered protocol family 2 Signed-off-by: Yangtao Li --- drivers/thermal/of-thermal.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c index 4bfdb4a1e47d..02b5e78f027b 100644 --- a/drivers/thermal/of-thermal.c +++ b/drivers/thermal/of-thermal.c @@ -5,6 +5,9 @@ * Copyright (C) 2013 Texas Instruments * Copyright (C) 2013 Eduardo Valentin */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include -- 2.17.0
[PATCH] cpuidle: fix description of exit latency in cpuidle.rst
Exit latency is the time from exiting the idle state to execute the first instruction. This place may be a typo , so fix it. Signed-off-by: Yangtao Li --- Documentation/admin-guide/pm/cpuidle.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/admin-guide/pm/cpuidle.rst b/Documentation/admin-guide/pm/cpuidle.rst index 106379e2619f..3ca2ca60ff91 100644 --- a/Documentation/admin-guide/pm/cpuidle.rst +++ b/Documentation/admin-guide/pm/cpuidle.rst @@ -134,7 +134,7 @@ substantial), in order to save more energy than it would save by entering one of the shallower idle states instead. [The "depth" of an idle state roughly corresponds to the power drawn by the processor in that state.] The exit latency, in turn, is the maximum time it will take a CPU asking the processor -hardware to enter an idle state to start executing the first instruction after a +hardware to exit an idle state to start executing the first instruction after a wakeup from that state. Note that in general the exit latency also must cover the time needed to enter the given state in case the wakeup occurs when the hardware is entering it and it must be entered completely to be exited in an -- 2.17.0
[PATCH] PM / wakeup: fix comment of pm_wakeup_dev_event()
This brings the kernel doc in line with the function signature. Signed-off-by: Yangtao Li --- drivers/base/power/wakeup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 5fa1898755a3..f1fee72ed970 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -783,7 +783,7 @@ void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard) EXPORT_SYMBOL_GPL(pm_wakeup_ws_event); /** - * pm_wakeup_event - Notify the PM core of a wakeup event. + * pm_wakeup_dev_event - Notify the PM core of a wakeup event. * @dev: Device the wakeup event is related to. * @msec: Anticipated event processing time (in milliseconds). * @hard: If set, abort suspends in progress and wake up from suspend-to-idle. -- 2.17.0
[PATCH] PM / devfreq: fix mem leak and missing check of return value in devfreq_add_device()
'devfreq' is malloced in devfreq_add_device() and should be freed in the error handling cases, otherwise it will cause memory leak. devm_kzalloc() could fail, so insert a check of its return value. And if it fails, returns -ENOMEM. Signed-off-by: Yangtao Li --- drivers/devfreq/devfreq.c | 33 ++--- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 0ae3de76833b..fe6c157cb7e0 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -651,7 +651,7 @@ struct devfreq *devfreq_add_device(struct device *dev, mutex_unlock(>lock); err = set_freq_table(devfreq); if (err < 0) - goto err_out; + goto err_dev; mutex_lock(>lock); } @@ -683,16 +683,27 @@ struct devfreq *devfreq_add_device(struct device *dev, goto err_out; } - devfreq->trans_table = - devm_kzalloc(>dev, -array3_size(sizeof(unsigned int), -devfreq->profile->max_state, -devfreq->profile->max_state), -GFP_KERNEL); + devfreq->trans_table = devm_kzalloc(>dev, + array3_size(sizeof(unsigned int), + devfreq->profile->max_state, + devfreq->profile->max_state), + GFP_KERNEL); + if (!devfreq->trans_table) { + mutex_unlock(>lock); + err = -ENOMEM; + goto err_devfreq; + } + devfreq->time_in_state = devm_kcalloc(>dev, - devfreq->profile->max_state, - sizeof(unsigned long), - GFP_KERNEL); + devfreq->profile->max_state, + sizeof(unsigned long), + GFP_KERNEL); + if (!devfreq->time_in_state) { + mutex_unlock(>lock); + err = -ENOMEM; + goto err_devfreq; + } + devfreq->last_stat_updated = jiffies; srcu_init_notifier_head(>transition_notifier_list); @@ -726,7 +737,7 @@ struct devfreq *devfreq_add_device(struct device *dev, err_init: mutex_unlock(_list_lock); - +err_devfreq: devfreq_remove_device(devfreq); devfreq = NULL; err_dev: -- 2.17.0
[PATCH 2/3] PM / devfreq: fix missing check of return value in devfreq_add_device()
devm_kzalloc() could fail, so insert a check of its return value. And if it fails, returns -ENOMEM. Signed-off-by: Yangtao Li --- drivers/devfreq/devfreq.c | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 076b1c2f40a4..923889229a0b 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -688,10 +688,22 @@ struct devfreq *devfreq_add_device(struct device *dev, devfreq->profile->max_state, devfreq->profile->max_state), GFP_KERNEL); + if (!devfreq->trans_table) { + mutex_unlock(>lock); + err = -ENOMEM; + goto err_devfreq; + } + devfreq->time_in_state = devm_kcalloc(>dev, devfreq->profile->max_state, sizeof(unsigned long), GFP_KERNEL); + if (!devfreq->time_in_state) { + mutex_unlock(>lock); + err = -ENOMEM; + goto err_devfreq; + } + devfreq->last_stat_updated = jiffies; srcu_init_notifier_head(>transition_notifier_list); @@ -725,7 +737,7 @@ struct devfreq *devfreq_add_device(struct device *dev, err_init: mutex_unlock(_list_lock); - +err_devfreq: devfreq_remove_device(devfreq); devfreq = NULL; err_dev: -- 2.17.0
[PATCH 1/3] PM / devfreq: fix indentation in devfreq_add_device()
To beautify the code format. Signed-off-by: Yangtao Li --- drivers/devfreq/devfreq.c | 17 - 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 0ae3de76833b..076b1c2f40a4 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -683,16 +683,15 @@ struct devfreq *devfreq_add_device(struct device *dev, goto err_out; } - devfreq->trans_table = - devm_kzalloc(>dev, -array3_size(sizeof(unsigned int), -devfreq->profile->max_state, -devfreq->profile->max_state), -GFP_KERNEL); + devfreq->trans_table = devm_kzalloc(>dev, + array3_size(sizeof(unsigned int), + devfreq->profile->max_state, + devfreq->profile->max_state), + GFP_KERNEL); devfreq->time_in_state = devm_kcalloc(>dev, - devfreq->profile->max_state, - sizeof(unsigned long), - GFP_KERNEL); + devfreq->profile->max_state, + sizeof(unsigned long), + GFP_KERNEL); devfreq->last_stat_updated = jiffies; srcu_init_notifier_head(>transition_notifier_list); -- 2.17.0
[PATCH 3/3] PM / devfreq: fix mem leak in devfreq_add_device()
'devfreq' is malloced in devfreq_add_device() and should be freed in the error handling cases, otherwise it will cause memory leak. Signed-off-by: Yangtao Li --- drivers/devfreq/devfreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 923889229a0b..fe6c157cb7e0 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -651,7 +651,7 @@ struct devfreq *devfreq_add_device(struct device *dev, mutex_unlock(>lock); err = set_freq_table(devfreq); if (err < 0) - goto err_out; + goto err_dev; mutex_lock(>lock); } -- 2.17.0
[PATCH] clockevents: decrement reference count when device_register() fail
device_register() may fail, use put_device() giving up the refconut to avoid refcount leak. Signed-off-by: Yangtao Li --- kernel/time/clockevents.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 5e77662dd2d9..7b691dc97349 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -719,7 +719,9 @@ static __init int tick_broadcast_init_sysfs(void) { int err = device_register(_bc_dev); - if (!err) + if (err) + put_device(_bc_dev); + else err = device_create_file(_bc_dev, _attr_current_device); return err; } @@ -746,8 +748,10 @@ static int __init tick_init_sysfs(void) err = device_create_file(dev, _attr_current_device); if (!err) err = device_create_file(dev, _attr_unbind_device); - if (err) + if (err) { + put_device(dev); return err; + } } return tick_broadcast_init_sysfs(); } -- 2.17.0
[PATCH] clocksource: decrement reference count when device_register() fail
device_register() may fail, use put_device() giving up the refconut to avoid refcount leak. Signed-off-by: Yangtao Li --- kernel/time/clocksource.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 3bcc19ceb073..0a830fedc7ef 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -1183,8 +1183,11 @@ static int __init init_clocksource_sysfs(void) { int error = subsys_system_register(_subsys, NULL); - if (!error) + if (!error) { error = device_register(_clocksource); + if (error) + put_device(_clocksource); + } return error; } -- 2.17.0
[PATCH] dmaengine: remove DBGFS_FUNC_DECL()
We already have the DEFINE_SHOW_ATTRIBUTE,There is no need to define such a macro,so remove DBGFS_FUNC_DECL.Also use macro to simplify some code. Signed-off-by: Yangtao Li --- drivers/dma/amba-pl08x.c | 14 ++ drivers/dma/mic_x100_dma.c | 22 +++--- drivers/dma/pxa_dma.c| 24 drivers/dma/qcom/hidma_dbg.c | 33 ++--- 4 files changed, 23 insertions(+), 70 deletions(-) diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 97483df1f82e..fc8c2bab563c 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -2505,24 +2505,14 @@ static int pl08x_debugfs_show(struct seq_file *s, void *data) return 0; } -static int pl08x_debugfs_open(struct inode *inode, struct file *file) -{ - return single_open(file, pl08x_debugfs_show, inode->i_private); -} - -static const struct file_operations pl08x_debugfs_operations = { - .open = pl08x_debugfs_open, - .read = seq_read, - .llseek = seq_lseek, - .release= single_release, -}; +DEFINE_SHOW_ATTRIBUTE(pl08x_debugfs); static void init_pl08x_debugfs(struct pl08x_driver_data *pl08x) { /* Expose a simple debugfs interface to view all clocks */ (void) debugfs_create_file(dev_name(>adev->dev), S_IFREG | S_IRUGO, NULL, pl08x, - _debugfs_operations); + _debugfs_fops); } #else diff --git a/drivers/dma/mic_x100_dma.c b/drivers/dma/mic_x100_dma.c index adfd316db1a8..6a91e28d537d 100644 --- a/drivers/dma/mic_x100_dma.c +++ b/drivers/dma/mic_x100_dma.c @@ -676,7 +676,7 @@ static void mic_dma_dev_unreg(struct mic_dma_device *mic_dma_dev) } /* DEBUGFS CODE */ -static int mic_dma_reg_seq_show(struct seq_file *s, void *pos) +static int mic_dma_reg_show(struct seq_file *s, void *pos) { struct mic_dma_device *mic_dma_dev = s->private; int i, chan_num, first_chan = mic_dma_dev->start_ch; @@ -707,23 +707,7 @@ static int mic_dma_reg_seq_show(struct seq_file *s, void *pos) return 0; } -static int mic_dma_reg_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, mic_dma_reg_seq_show, inode->i_private); -} - -static int mic_dma_reg_debug_release(struct inode *inode, struct file *file) -{ - return single_release(inode, file); -} - -static const struct file_operations mic_dma_reg_ops = { - .owner = THIS_MODULE, - .open= mic_dma_reg_debug_open, - .read= seq_read, - .llseek = seq_lseek, - .release = mic_dma_reg_debug_release -}; +DEFINE_SHOW_ATTRIBUTE(mic_dma_reg); /* Debugfs parent dir */ static struct dentry *mic_dma_dbg; @@ -747,7 +731,7 @@ static int mic_dma_driver_probe(struct mbus_device *mbdev) if (mic_dma_dev->dbg_dir) debugfs_create_file("mic_dma_reg", 0444, mic_dma_dev->dbg_dir, mic_dma_dev, - _dma_reg_ops); + _dma_reg_fops); } return 0; } diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c index 825725057e00..8e1e1b07d32f 100644 --- a/drivers/dma/pxa_dma.c +++ b/drivers/dma/pxa_dma.c @@ -189,7 +189,7 @@ bool pxad_filter_fn(struct dma_chan *chan, void *param); #include #include -static int dbg_show_requester_chan(struct seq_file *s, void *p) +static int requester_chan_show(struct seq_file *s, void *p) { struct pxad_phy *phy = s->private; int i; @@ -220,7 +220,7 @@ static int is_phys_valid(unsigned long addr) #define PXA_DCSR_STR(flag) (dcsr & PXA_DCSR_##flag ? #flag" " : "") #define PXA_DCMD_STR(flag) (dcmd & PXA_DCMD_##flag ? #flag" " : "") -static int dbg_show_descriptors(struct seq_file *s, void *p) +static int descriptors_show(struct seq_file *s, void *p) { struct pxad_phy *phy = s->private; int i, max_show = 20, burst, width; @@ -263,7 +263,7 @@ static int dbg_show_descriptors(struct seq_file *s, void *p) return 0; } -static int dbg_show_chan_state(struct seq_file *s, void *p) +static int chan_state_show(struct seq_file *s, void *p) { struct pxad_phy *phy = s->private; u32 dcsr, dcmd; @@ -306,7 +306,7 @@ static int dbg_show_chan_state(struct seq_file *s, void *p) return 0; } -static int dbg_show_state(struct seq_file *s, void *p) +static int state_show(struct seq_file *s, void *p) { struct pxad_device *pdev = s->private; @@ -329,10 +329,10 @@ static const struct file_operations dbg_fops_##name = { \ .release= single_release, \ } -DBGFS_FUNC_DECL(state); -DBGFS_FUNC_DECL(chan_state); -DBGFS_FUNC_DECL(descriptors); -DBGFS_FUNC_DECL(requester_chan); +DEFINE_SHOW_ATTRIBUTE(state); +
[PATCH] gpio: ks8695: Change to use DEFINE_SHOW_ATTRIBUTE macro
Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Yangtao Li --- drivers/gpio/gpio-ks8695.c | 15 +++ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-ks8695.c b/drivers/gpio/gpio-ks8695.c index 55d562e1278e..d6d6140ffc40 100644 --- a/drivers/gpio/gpio-ks8695.c +++ b/drivers/gpio/gpio-ks8695.c @@ -282,22 +282,13 @@ static int ks8695_gpio_show(struct seq_file *s, void *unused) return 0; } -static int ks8695_gpio_open(struct inode *inode, struct file *file) -{ - return single_open(file, ks8695_gpio_show, NULL); -} - -static const struct file_operations ks8695_gpio_operations = { - .open = ks8695_gpio_open, - .read = seq_read, - .llseek = seq_lseek, - .release= single_release, -}; +DEFINE_SHOW_ATTRIBUTE(ks8695_gpio); static int __init ks8695_gpio_debugfs_init(void) { /* /sys/kernel/debug/ks8695_gpio */ - (void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, _gpio_operations); + debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, + _gpio_fops); return 0; } postcore_initcall(ks8695_gpio_debugfs_init); -- 2.17.0
[PATCH] pinctrl: Change to use DEFINE_SHOW_ATTRIBUTE macro
Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Yangtao Li --- drivers/pinctrl/pinconf.c | 29 - drivers/pinctrl/pinmux.c | 29 - 2 files changed, 8 insertions(+), 50 deletions(-) diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index d3fe14394b73..2c7229380f08 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -366,29 +366,8 @@ static int pinconf_groups_show(struct seq_file *s, void *what) return 0; } -static int pinconf_pins_open(struct inode *inode, struct file *file) -{ - return single_open(file, pinconf_pins_show, inode->i_private); -} - -static int pinconf_groups_open(struct inode *inode, struct file *file) -{ - return single_open(file, pinconf_groups_show, inode->i_private); -} - -static const struct file_operations pinconf_pins_ops = { - .open = pinconf_pins_open, - .read = seq_read, - .llseek = seq_lseek, - .release= single_release, -}; - -static const struct file_operations pinconf_groups_ops = { - .open = pinconf_groups_open, - .read = seq_read, - .llseek = seq_lseek, - .release= single_release, -}; +DEFINE_SHOW_ATTRIBUTE(pinconf_pins); +DEFINE_SHOW_ATTRIBUTE(pinconf_groups); #define MAX_NAME_LEN 15 @@ -613,9 +592,9 @@ void pinconf_init_device_debugfs(struct dentry *devroot, struct pinctrl_dev *pctldev) { debugfs_create_file("pinconf-pins", S_IFREG | S_IRUGO, - devroot, pctldev, _pins_ops); + devroot, pctldev, _pins_fops); debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO, - devroot, pctldev, _groups_ops); + devroot, pctldev, _groups_fops); debugfs_create_file("pinconf-config", (S_IRUGO | S_IWUSR | S_IWGRP), devroot, pctldev, _dbg_pinconfig_fops); } diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 5780442c068b..4d0cc1889dd9 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -644,37 +644,16 @@ void pinmux_show_setting(struct seq_file *s, setting->data.mux.func); } -static int pinmux_functions_open(struct inode *inode, struct file *file) -{ - return single_open(file, pinmux_functions_show, inode->i_private); -} - -static int pinmux_pins_open(struct inode *inode, struct file *file) -{ - return single_open(file, pinmux_pins_show, inode->i_private); -} - -static const struct file_operations pinmux_functions_ops = { - .open = pinmux_functions_open, - .read = seq_read, - .llseek = seq_lseek, - .release= single_release, -}; - -static const struct file_operations pinmux_pins_ops = { - .open = pinmux_pins_open, - .read = seq_read, - .llseek = seq_lseek, - .release= single_release, -}; +DEFINE_SHOW_ATTRIBUTE(pinmux_functions); +DEFINE_SHOW_ATTRIBUTE(pinmux_pins); void pinmux_init_device_debugfs(struct dentry *devroot, struct pinctrl_dev *pctldev) { debugfs_create_file("pinmux-functions", S_IFREG | S_IRUGO, - devroot, pctldev, _functions_ops); + devroot, pctldev, _functions_fops); debugfs_create_file("pinmux-pins", S_IFREG | S_IRUGO, - devroot, pctldev, _pins_ops); + devroot, pctldev, _pins_fops); } #endif /* CONFIG_DEBUG_FS */ -- 2.17.0
[PATCH] ACPI, APEI, EINJ: Change to use DEFINE_SHOW_ATTRIBUTE macro
Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Yangtao Li --- drivers/acpi/apei/einj.c | 12 +--- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index b38737c83a24..fcccbfdbdd1a 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -607,17 +607,7 @@ static int available_error_type_show(struct seq_file *m, void *v) return 0; } -static int available_error_type_open(struct inode *inode, struct file *file) -{ - return single_open(file, available_error_type_show, NULL); -} - -static const struct file_operations available_error_type_fops = { - .open = available_error_type_open, - .read = seq_read, - .llseek = seq_lseek, - .release= single_release, -}; +DEFINE_SHOW_ATTRIBUTE(available_error_type); static int error_type_get(void *data, u64 *val) { -- 2.17.0
[PATCH] binder: remove BINDER_DEBUG_ENTRY()
We already have the DEFINE_SHOW_ATTRIBUTE.There is no need to define such a macro,so remove BINDER_DEBUG_ENTRY. Signed-off-by: Yangtao Li --- drivers/android/binder.c | 48 ++-- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index cb30a524d16d..5496b8e07234 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -94,22 +94,8 @@ static struct dentry *binder_debugfs_dir_entry_root; static struct dentry *binder_debugfs_dir_entry_proc; static atomic_t binder_last_id; -#define BINDER_DEBUG_ENTRY(name) \ -static int binder_##name##_open(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, binder_##name##_show, inode->i_private); \ -} \ -\ -static const struct file_operations binder_##name##_fops = { \ - .owner = THIS_MODULE, \ - .open = binder_##name##_open, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .release = single_release, \ -} - -static int binder_proc_show(struct seq_file *m, void *unused); -BINDER_DEBUG_ENTRY(proc); +static int proc_show(struct seq_file *m, void *unused); +DEFINE_SHOW_ATTRIBUTE(proc); /* This is only defined in include/asm-arm/sizes.h */ #ifndef SZ_1K @@ -4964,7 +4950,7 @@ static int binder_open(struct inode *nodp, struct file *filp) proc->debugfs_entry = debugfs_create_file(strbuf, 0444, binder_debugfs_dir_entry_proc, (void *)(unsigned long)proc->pid, - _proc_fops); + _fops); } return 0; @@ -5592,7 +5578,7 @@ static void print_binder_proc_stats(struct seq_file *m, } -static int binder_state_show(struct seq_file *m, void *unused) +static int state_show(struct seq_file *m, void *unused) { struct binder_proc *proc; struct binder_node *node; @@ -5631,7 +5617,7 @@ static int binder_state_show(struct seq_file *m, void *unused) return 0; } -static int binder_stats_show(struct seq_file *m, void *unused) +static int stats_show(struct seq_file *m, void *unused) { struct binder_proc *proc; @@ -5647,7 +5633,7 @@ static int binder_stats_show(struct seq_file *m, void *unused) return 0; } -static int binder_transactions_show(struct seq_file *m, void *unused) +static int transactions_show(struct seq_file *m, void *unused) { struct binder_proc *proc; @@ -5660,7 +5646,7 @@ static int binder_transactions_show(struct seq_file *m, void *unused) return 0; } -static int binder_proc_show(struct seq_file *m, void *unused) +static int proc_show(struct seq_file *m, void *unused) { struct binder_proc *itr; int pid = (unsigned long)m->private; @@ -5703,7 +5689,7 @@ static void print_binder_transaction_log_entry(struct seq_file *m, "\n" : " (incomplete)\n"); } -static int binder_transaction_log_show(struct seq_file *m, void *unused) +static int transaction_log_show(struct seq_file *m, void *unused) { struct binder_transaction_log *log = m->private; unsigned int log_cur = atomic_read(>cur); @@ -5735,10 +5721,10 @@ static const struct file_operations binder_fops = { .release = binder_release, }; -BINDER_DEBUG_ENTRY(state); -BINDER_DEBUG_ENTRY(stats); -BINDER_DEBUG_ENTRY(transactions); -BINDER_DEBUG_ENTRY(transaction_log); +DEFINE_SHOW_ATTRIBUTE(state); +DEFINE_SHOW_ATTRIBUTE(stats); +DEFINE_SHOW_ATTRIBUTE(transactions); +DEFINE_SHOW_ATTRIBUTE(transaction_log); static int __init init_binder_device(const char *name) { @@ -5792,27 +5778,27 @@ static int __init binder_init(void) 0444, binder_debugfs_dir_entry_root, NULL, - _state_fops); + _fops); debugfs_create_file("stats", 0444, binder_debugfs_dir_entry_root, NULL, - _stats_fops); + _fops); debugfs_create_file("transactions", 0444, binder_debugfs_dir_entry_root, NULL, - _transactions_fops); + _fops); debugfs_create_file("transaction_log", 0444, binder_debugfs_dir_entry_root, _transaction_log, - _transaction_log_fops); + _log_fops); debugfs_create_fil
[PATCH] driver core: remove define_genpd_open_function() and define_genpd_debugfs_fops()
We already have the DEFINE_SHOW_ATTRIBUTE,There is no need to define such a macro,so remove define_genpd_open_function and define_genpd_debugfs_fops. Also use DEFINE_SHOW_ATTRIBUTE to simplify somecode. Signed-off-by: Yangtao Li --- drivers/base/component.c | 12 + drivers/base/power/domain.c | 71 +-- drivers/base/regmap/regcache-rbtree.c | 12 + drivers/base/regmap/regmap-debugfs.c | 12 + 4 files changed, 27 insertions(+), 80 deletions(-) diff --git a/drivers/base/component.c b/drivers/base/component.c index e8d676fad0c9..ddcea8739c12 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -85,17 +85,7 @@ static int component_devices_show(struct seq_file *s, void *data) return 0; } -static int component_devices_open(struct inode *inode, struct file *file) -{ - return single_open(file, component_devices_show, inode->i_private); -} - -static const struct file_operations component_devices_fops = { - .open = component_devices_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(component_devices); static int __init component_debug_init(void) { diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 7f38a92b444a..10a61d6147d0 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2671,7 +2671,7 @@ static int genpd_summary_one(struct seq_file *s, return 0; } -static int genpd_summary_show(struct seq_file *s, void *data) +static int summary_show(struct seq_file *s, void *data) { struct generic_pm_domain *genpd; int ret = 0; @@ -2694,7 +2694,7 @@ static int genpd_summary_show(struct seq_file *s, void *data) return ret; } -static int genpd_status_show(struct seq_file *s, void *data) +static int status_show(struct seq_file *s, void *data) { static const char * const status_lookup[] = { [GPD_STATE_ACTIVE] = "on", @@ -2721,7 +2721,7 @@ static int genpd_status_show(struct seq_file *s, void *data) return ret; } -static int genpd_sub_domains_show(struct seq_file *s, void *data) +static int sub_domains_show(struct seq_file *s, void *data) { struct generic_pm_domain *genpd = s->private; struct gpd_link *link; @@ -2738,7 +2738,7 @@ static int genpd_sub_domains_show(struct seq_file *s, void *data) return ret; } -static int genpd_idle_states_show(struct seq_file *s, void *data) +static int idle_states_show(struct seq_file *s, void *data) { struct generic_pm_domain *genpd = s->private; unsigned int i; @@ -2767,7 +2767,7 @@ static int genpd_idle_states_show(struct seq_file *s, void *data) return ret; } -static int genpd_active_time_show(struct seq_file *s, void *data) +static int active_time_show(struct seq_file *s, void *data) { struct generic_pm_domain *genpd = s->private; ktime_t delta = 0; @@ -2787,7 +2787,7 @@ static int genpd_active_time_show(struct seq_file *s, void *data) return ret; } -static int genpd_total_idle_time_show(struct seq_file *s, void *data) +static int total_idle_time_show(struct seq_file *s, void *data) { struct generic_pm_domain *genpd = s->private; ktime_t delta = 0, total = 0; @@ -2815,7 +2815,7 @@ static int genpd_total_idle_time_show(struct seq_file *s, void *data) } -static int genpd_devices_show(struct seq_file *s, void *data) +static int devices_show(struct seq_file *s, void *data) { struct generic_pm_domain *genpd = s->private; struct pm_domain_data *pm_data; @@ -2841,7 +2841,7 @@ static int genpd_devices_show(struct seq_file *s, void *data) return ret; } -static int genpd_perf_state_show(struct seq_file *s, void *data) +static int perf_state_show(struct seq_file *s, void *data) { struct generic_pm_domain *genpd = s->private; @@ -2854,37 +2854,14 @@ static int genpd_perf_state_show(struct seq_file *s, void *data) return 0; } -#define define_genpd_open_function(name) \ -static int genpd_##name##_open(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, genpd_##name##_show, inode->i_private); \ -} - -define_genpd_open_function(summary); -define_genpd_open_function(status); -define_genpd_open_function(sub_domains); -define_genpd_open_function(idle_states); -define_genpd_open_function(active_time); -define_genpd_open_function(total_idle_time); -define_genpd_open_function(devices); -define_genpd_open_function(perf_state); - -#define define_genpd_debugfs_fops(name) \ -static const struct file_operations genpd_##name##_fops = { \ - .open = genpd_##name##_open, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .release = single_release, \ -} - -define_genpd_debugfs_fops(summary); -define_genpd_debugfs_fops(status); -define_genpd_debugfs_fops(sub_domains); -def
[PATCH] drivers/fmc: Change to use DEFINE_SHOW_ATTRIBUTE macro
Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Yangtao Li --- drivers/fmc/fmc-debug.c | 21 +++-- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/drivers/fmc/fmc-debug.c b/drivers/fmc/fmc-debug.c index 32930722770c..c923d076c807 100644 --- a/drivers/fmc/fmc-debug.c +++ b/drivers/fmc/fmc-debug.c @@ -114,7 +114,7 @@ static void fmc_sdb_dump_recursive(struct fmc_device *fmc, struct seq_file *s, } } -static int fmc_sdb_dump(struct seq_file *s, void *offset) +static int fmc_sdb_dump_show(struct seq_file *s, void *offset) { struct fmc_device *fmc = s->private; @@ -131,22 +131,7 @@ static int fmc_sdb_dump(struct seq_file *s, void *offset) return 0; } - -static int fmc_sdb_dump_open(struct inode *inode, struct file *file) -{ - struct fmc_device *fmc = inode->i_private; - - return single_open(file, fmc_sdb_dump, fmc); -} - - -const struct file_operations fmc_dbgfs_sdb_dump = { - .owner = THIS_MODULE, - .open = fmc_sdb_dump_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(fmc_sdb_dump); int fmc_debug_init(struct fmc_device *fmc) { @@ -158,7 +143,7 @@ int fmc_debug_init(struct fmc_device *fmc) fmc->dbg_sdb_dump = debugfs_create_file(FMC_DBG_SDB_DUMP, 0444, fmc->dbg_dir, fmc, - _dbgfs_sdb_dump); + _sdb_dump_fops); if (IS_ERR_OR_NULL(fmc->dbg_sdb_dump)) pr_err("FMC: Cannot create debugfs file %s\n", FMC_DBG_SDB_DUMP); -- 2.17.0
[PATCH] bus: mvebu-mbus: Change to use DEFINE_SHOW_ATTRIBUTE macro
Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Yangtao Li --- drivers/bus/mvebu-mbus.c | 24 ++-- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 5b2a11a88951..3aaaf484857f 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -470,17 +470,7 @@ static int mvebu_sdram_debug_show(struct seq_file *seq, void *v) return mbus->soc->show_cpu_target(mbus, seq, v); } -static int mvebu_sdram_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, mvebu_sdram_debug_show, inode->i_private); -} - -static const struct file_operations mvebu_sdram_debug_fops = { - .open = mvebu_sdram_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(mvebu_sdram_debug); static int mvebu_devs_debug_show(struct seq_file *seq, void *v) { @@ -520,17 +510,7 @@ static int mvebu_devs_debug_show(struct seq_file *seq, void *v) return 0; } -static int mvebu_devs_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, mvebu_devs_debug_show, inode->i_private); -} - -static const struct file_operations mvebu_devs_debug_fops = { - .open = mvebu_devs_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(mvebu_devs_debug); /* * SoC-specific functions and definitions -- 2.17.0