* Re: [PATCH v7 1/7] clocksource/drivers/clksrc-evt-probe: Describe with the DT both the clocksource and the clockevent
From: Daniel Lezcano @ 2017-03-29 9:22 UTC (permalink / raw)
To: Rob Herring
Cc: Alexander Kochetkov, Heiko Stuebner,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Thomas Gleixner,
Mark Rutland, Russell King, Caesar Wang, Huang Tao
In-Reply-To: <20170329015146.ey5rlptzsnnynpnt@rob-hp-laptop>
On Tue, Mar 28, 2017 at 08:51:46PM -0500, Rob Herring wrote:
> On Wed, Mar 22, 2017 at 06:48:28PM +0300, Alexander Kochetkov wrote:
> > From: Daniel Lezcano <daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> >
> > The CLOCKSOURCE_OF_DECLARE() was introduced before the
> > CLOCKEVENT_OF_DECLARE() and that resulted in some abuse where the
> > clockevent and the clocksource are both initialized in the same init
> > routine.
> >
> > With the introduction of the CLOCKEVENT_OF_DECLARE(), the driver can
> > now split the clocksource and the clockevent init code. However, the
> > device tree may specify a single node, so the same node will be passed
> > to the clockevent/clocksource's init function, with the same base
> > address.
> >
> > with this patch it is possible to specify an attribute to the timer's node to
> > specify if it is a clocksource or a clockevent and define two timers node.
>
> Daniel and I discussed and agreed against this a while back. What
> changed?
Hi Rob,
> > For example:
> >
> > timer: timer@98400000 {
> > compatible = "moxa,moxart-timer";
> > reg = <0x98400000 0x42>;
>
> This overlaps the next node. You can change this to 0x10, but are these
> really 2 independent h/w blocks? Don't design the nodes around the
> current needs of Linux.
Mmh, thanks for raising this. Conceptually speaking there are two (or more)
different entities, the clocksource and the clockevents but they share the same
IP block.
In the driver timer-sp804.c there is a fragile mechanism with the timer
counting assuming the timers are declared in a specific order in the DT
(integratorcp.dts). There are multiple nodes, which are IIUC overlapping like
what you are describing.
I'm a bit puzzled with how this should be done.
Do you have a suggestion ?
> > interrupts = <19 1>;
> > clocks = <&coreclk>;
> > clockevent;
>
> This is not needed. The presence of "interrupts" is enough to say use
> this timer for clockevent.
Yes, that is true if no drivers was already taking CLOCKSOURCE_OF and
initializing the clockevent. The driver will pass through the clocksource_probe
function, check the interrupt and bail out because there is an interrupt
declared and assume it is a clockevent, so no initialization for the driver.
IOW, it is not backward compatible.
We need this attribute somehow in order to separate clearly a clocksource or a
clockevent with a new implementation.
> > };
> >
> > timer: timer@98400010 {
> > compatible = "moxa,moxart-timer";
> > reg = <0x98400010 0x42>;
> > clocks = <&coreclk>;
> > clocksource;
>
> Likewise.
>
> > };
> >
> > With this approach, we allow a mechanism to clearly define a clocksource or a
> > clockevent without aerobatics we can find around in some drivers:
> > timer-sp804.c, arc-timer.c, dw_apb_timer_of.c, mps2-timer.c,
> > renesas-ostm.c, time-efm32.c, time-lpc32xx.c.
>
> These all already have bindings and work. What problem are you trying to
> solve other than restructuring Linux?
Yes, there is already the bindings, but that force to do some hackish
initialization.
I would like to give the opportunity to declare separately a clocksource and a
clockevent, in order to have full control of how this is initialized.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/1] of: Move OF property and graph API from base.c to property.c
From: Sakari Ailus @ 2017-03-29 9:14 UTC (permalink / raw)
To: Frank Rowand, linux-acpi, devicetree, robh
Cc: sudeep.holla, lorenzo.pieralisi, mika.westerberg, rafael,
mark.rutland, broonie, ahs3
In-Reply-To: <58DAF70E.9000305@gmail.com>
Hi Frank,
Thank you for the review.
Frank Rowand wrote:
> Hi Sakari,
>
> On 03/24/17 03:59, Sakari Ailus wrote:
>> base.c contains both core OF functions and increasingly other
>> functionality such as accessing properties and graphs, including
>> convenience functions. In the near future this would also include OF
>> specific implementation of the fwnode property and graph APIs. Prepare for
>> this by moving the functionality to property.c.
>
> For future me, for when I look back and read this commit, please add something
> to the effect of:
>
> Create driver/of/property.c to contain procedures for accessing and
> interpreting device tree properties. The procedures are moved from
> drivers/of/base.c, with no changes other than copying only the
> includes required by the moved procedures.
How about this as the commit message combining the two and dropping the
last sentence from the original description:
base.c contains both core OF functions and increasingly other
functionality such as accessing properties and graphs, including
convenience functions. In the near future this would also include OF
specific implementation of the fwnode property and graph APIs.
Create driver/of/property.c to contain procedures for accessing and
interpreting device tree properties. The procedures are moved from
drivers/of/base.c, with no changes other than copying only the
includes required by the moved procedures.
...
>> diff --git a/drivers/of/property.c b/drivers/of/property.c
>> new file mode 100644
>> index 0000000..afcf00a
>> --- /dev/null
>> +++ b/drivers/of/property.c
>> @@ -0,0 +1,727 @@
>> +/*
>> + * drivers/of/property.c - Devicetree properties and graphs.
>
> * drivers/of/property.c - Procedures for accessing and interpreting
> * Devicetree properties and graphs.
> *
> * Initially created by copying procedures from drivers/of/base.c
>
> The reference to base.c provides a documentation trail to all of the
> earlier git commits that created and modified the procedures.
I'll add that.
>
> It would also be useful to say what procedures do and do not belong
> in this file. My understanding is that the intent is for
> drivers/of/property.c and drivers/acpi/property.c to provide the
> respective functionality that is used by drivers/base/property.c
> and that drivers also may directly access the procedures in
> drivers/of/property.c.
I'll add something along those lines. The fwnode op struct and the
operations in that will be in this file as well.
--
Kind regards,
Sakari Ailus
sakari.ailus@linux.intel.com
^ permalink raw reply
* Re: [PATCH V6 4/7] mfd: da9061: MFD core support
From: Geert Uytterhoeven @ 2017-03-29 9:12 UTC (permalink / raw)
To: Lee Jones
Cc: Steve Twiss, kbuild test robot,
kbuild-all-JC7UmRfGjtg@public.gmane.org, LINUX-KERNEL, DEVICETREE,
Dmitry Torokhov, Eduardo Valentin, Guenter Roeck, LINUX-INPUT,
LINUX-PM, LINUX-WATCHDOG, Liam Girdwood, Mark Brown, Mark Rutland,
Rob Herring, Support Opensource, Wim Van Sebroeck, Zhang Rui
In-Reply-To: <20170329083058.6pcslbsq3qnifwjv@dell>
Hi Lee,
On Wed, Mar 29, 2017 at 10:30 AM, Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> On Tue, 28 Mar 2017, Geert Uytterhoeven wrote:
>> On Tue, Mar 28, 2017 at 12:42 PM, Steve Twiss
>> <stwiss.opensource-WBD+wuPFNBhBDgjK7y7TUQ@public.gmane.org> wrote:
>> > On 28 March 2017 09:37, Geert Uytterhoeven wrote:
>> >> Subject: Re: [PATCH V6 4/7] mfd: da9061: MFD core support
>> >> On Tue, Mar 28, 2017 at 10:21 AM, Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
>> >> >> [auto build test WARNING on ljones-mfd/for-mfd-next]
>> >> >> [also build test WARNING on v4.11-rc4 next-20170327]
>> >> >> base: https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
>> >> >> config: x86_64-randconfig-x009-201713 (attached as .config)
>> >> >> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
>> >> >> reproduce:
>> >> >> # save the attached .config to linux build tree
>> >> >> make ARCH=x86_64
>> >> >>
>> >> >> All warnings (new ones prefixed by >>):
>> >> >>
>> >> >> drivers//mfd/da9062-core.c: In function 'da9062_i2c_probe':
>> >> >> >> drivers//mfd/da9062-core.c:845:21: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
>> >> >> chip->chip_type = (int)match->data;
>> >> >> ^
>> >> >
>> >> > Please use longs or enums.
>> >>
>> >> Enums would still give a warning on 64-bit.
>> >> The simple fix is change the cast from (int) to (uintptr_t).
>> >
>> > Hi Lee and Geert,
>> >
>> > How about this? Fix by redefining the enum chip_type to be an int.
>> > Then, just use substitution:
>> > #define COMPAT_TYPE_DA9061 1
>> > #define COMPAT_TYPE_DA9062 2
>> >
>> > That would be simple.
>> > Are there any reasons this would not be acceptable?
>>
>> I don't see how that can help.
>> The warning is caused by casting the "void *" (which is either 32-bit or
>> 64-bit) in of_device_if.data to an integer or enum (which is always 32-bit).
>>
>> The right fix is to cast it to uintptr_t intead of int, like other drivers do.
>
> That's a hack though, isn't it? chip->chip_type is not of type
> uintptr_t, so all you're doing here is making the compiler happy.
It's a hack, in the sense that using casts is usually a hack :-)
(I would love for C to have casts you can easily grep for, like C++ has)
In this case, it's not really a hack, as the void * is intended to store
arbitrary data, both pointers and integers.
> I see people using (int)(uintptr_t), which I guess keeps the
> compiler happy in the first instance and actually culminates in a
> correct cast to the right type.
The cast to int isn't really needed.
> So how about something like (enum da9062_compatible_types)(long)?
"uintptr_t" is the proper C standard type for conversion between pointers and
integers. The cast to the enum isn't really needed, so I'd remove it (the
less number of casts, the better!).
Long is the hack that works on ILP32 and LP64 platforms only ;-)
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2] clk: stm32h7: Add stm32h743 clock driver
From: gabriel.fernandez @ 2017-03-29 9:08 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Russell King, Maxime Coquelin,
Alexandre Torgue, Michael Turquette, Stephen Boyd, Nicolas Pitre,
Arnd Bergmann, daniel.thompson, andrea.merello, radoslaw.pietrzyk,
Lee Jones
Cc: devicetree, amelie.delaunay, olivier.bideau, linux-kernel,
linux-clk, linux-arm-kernel, gabriel.fernandez, ludovic.barre
From: Gabriel Fernandez <gabriel.fernandez@st.com>
This patch enables clocks for STM32H743 boards.
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
Just for the MFD changes:
Acked-by: Lee Jones <lee.jones@linaro.org>
v2:
- rename compatible string "stm32,pll" into "stm32h7-pll"
- suppress "st,pllrge" property
- suppress "st, frac-status" property
- change management of "st,frac" property
0 : enable 0 pll integer mode
other values : enable pll in fractional mode (value is
the fractional factor)
---
.../devicetree/bindings/clock/st,stm32h7-rcc.txt | 151 ++
drivers/clk/Makefile | 1 +
drivers/clk/clk-stm32h7.c | 1610 ++++++++++++++++++++
include/dt-bindings/clock/stm32h7-clks.h | 165 ++
include/dt-bindings/mfd/stm32h7-rcc.h | 137 ++
5 files changed, 2064 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt
create mode 100644 drivers/clk/clk-stm32h7.c
create mode 100644 include/dt-bindings/clock/stm32h7-clks.h
create mode 100644 include/dt-bindings/mfd/stm32h7-rcc.h
diff --git a/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt
new file mode 100644
index 0000000..5f54f64
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt
@@ -0,0 +1,151 @@
+STMicroelectronics STM32H7 Reset and Clock Controller
+=====================================================
+
+The RCC IP is both a reset and a clock controller.
+
+Please refer to clock-bindings.txt for common clock controller binding usage.
+Please also refer to reset.txt for common reset controller binding usage.
+
+Required properties:
+- compatible: Should be:
+ "st,stm32h743-rcc"
+
+- reg: should be register base and length as documented in the
+ datasheet
+
+- #reset-cells: 1, see below
+
+- #clock-cells : from common clock binding; shall be set to 1
+
+- clocks: External oscillator clock phandle
+ - high speed external clock signal (HSE)
+ - low speed external clock signal (LSE)
+ - external I2S clock (I2S_CKIN)
+
+- st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain
+ write protection (RTC clock).
+
+- pll x node: Allow to register a pll with specific parameters.
+ Please see PLL section below.
+
+Example:
+
+ rcc: rcc@58024400 {
+ #reset-cells = <1>;
+ #clock-cells = <2>
+ compatible = "st,stm32h743-rcc", "st,stm32-rcc";
+ reg = <0x58024400 0x400>;
+ clocks = <&clk_hse>, <&clk_lse>, <&clk_i2s_ckin>;
+
+ st,syscfg = <&pwrcfg>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vco1@0 {
+ #clock-cells = <0>;
+ compatible = "stm32h7-pll";
+ reg = <0>;
+ };
+
+ vco2@1 {
+ #clock-cells = <0>;
+ compatible = "stm32h7-pll";
+ reg = <1>;
+ st,clock-div = <2>;
+ st,clock-mult = <40>;
+ st,frac = <0>;
+ st,vcosel = <1>;
+ };
+ vco3@2 {
+ #clock-cells = <0>;
+ compatible = "stm32h7-pll";
+ reg = <2>;
+ st,clock-div = <2>;
+ st,clock-mult = <40>;
+ st,frac = <1024>;
+ st,vcosel = <1>;
+ };
+ };
+
+
+STM32H7 PLL
+-----------
+
+The VCO of STM32 PLL could be reprensented like this:
+
+ Vref --------- --------
+ ---->| / DIVM |---->| x DIVN | ------> VCO
+ --------- --------
+ ^
+ |
+ -------
+ | FRACN |
+ -------
+
+When the PLL is configured in integer mode:
+- VCO = ( Vref / DIVM ) * DIVN
+
+When the PLL is configured in fractional mode:
+- VCO = ( Vref / DIVM ) * ( DIVN + FRACN / 2^13)
+
+
+Required properties for pll node:
+- compatible: Should be:
+ "stm32h7-pll"
+
+- #clock-cells: from common clock binding; shall be set to 0
+- reg: Should be the pll number.
+
+Optional properties:
+- st,clock-div: DIVM division factor : <1..63>
+- st,clock-mult: DIVN multiplication factor : <4..512>
+
+- st,frac:
+ - 0 Pll is configured in integer mode
+ - <1..8191> Pll is configure in fractional mode and the value is
+ the part of the multiplication factor.
+
+- st,vcosel: VCO selection
+ - 0: Wide VCO range:192 to 836 MHz
+ - 1: Medium VCO range:150 to 420 MHz
+
+The peripheral clock consumer should specify the desired clock by
+having the clock ID in its "clocks" phandle cell.
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/stm32h7-clks.h header and can be used in device
+tree sources.
+
+Example:
+
+ timer5: timer@40000c00 {
+ compatible = "st,stm32-timer";
+ reg = <0x40000c00 0x400>;
+ interrupts = <50>;
+ clocks = <&rcc TIM5_CK>;
+
+ };
+
+Specifying softreset control of devices
+=======================================
+
+Device nodes should specify the reset channel required in their "resets"
+property, containing a phandle to the reset device node and an index specifying
+which channel to use.
+The index is the bit number within the RCC registers bank, starting from RCC
+base address.
+It is calculated as: index = register_offset / 4 * 32 + bit_offset.
+Where bit_offset is the bit offset within the register.
+
+For example, for CRC reset:
+ crc = AHB4RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x88 / 4 * 32 + 19 = 1107
+
+All available preprocessor macros for reset are defined dt-bindings//mfd/stm32h7-rcc.h
+header and can be used in device tree sources.
+
+example:
+
+ timer2 {
+ resets = <&rcc STM32H7_APB1L_RESET(TIM2)>;
+ };
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 92c12b8..734aa02 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o
+obj-$(CONFIG_ARCH_STM32) += clk-stm32h7.o
obj-$(CONFIG_ARCH_TANGO) += clk-tango4.o
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
obj-$(CONFIG_ARCH_U300) += clk-u300.o
diff --git a/drivers/clk/clk-stm32h7.c b/drivers/clk/clk-stm32h7.c
new file mode 100644
index 0000000..3699a55
--- /dev/null
+++ b/drivers/clk/clk-stm32h7.c
@@ -0,0 +1,1610 @@
+/*
+ * Copyright (C) Gabriel Fernandez 2017
+ * Author: Gabriel Fernandez <gabriel.fernandez@st.com>
+ *
+ * License terms: GPL V2.0.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/stm32h7-clks.h>
+
+/* Reset Clock Control Registers */
+#define RCC_CR 0x00
+#define RCC_CFGR 0x10
+#define RCC_D1CFGR 0x18
+#define RCC_D2CFGR 0x1C
+#define RCC_D3CFGR 0x20
+#define RCC_PLLCKSELR 0x28
+#define RCC_PLLCFGR 0x2C
+#define RCC_PLL1DIVR 0x30
+#define RCC_PLL1FRACR 0x34
+#define RCC_PLL2DIVR 0x38
+#define RCC_PLL2FRACR 0x3C
+#define RCC_PLL3DIVR 0x40
+#define RCC_PLL3FRACR 0x44
+#define RCC_D1CCIPR 0x4C
+#define RCC_D2CCIP1R 0x50
+#define RCC_D2CCIP2R 0x54
+#define RCC_D3CCIPR 0x58
+#define RCC_BDCR 0x70
+#define RCC_CSR 0x74
+#define RCC_AHB3ENR 0xD4
+#define RCC_AHB1ENR 0xD8
+#define RCC_AHB2ENR 0xDC
+#define RCC_AHB4ENR 0xE0
+#define RCC_APB3ENR 0xE4
+#define RCC_APB1LENR 0xE8
+#define RCC_APB1HENR 0xEC
+#define RCC_APB2ENR 0xF0
+#define RCC_APB4ENR 0xF4
+
+static DEFINE_SPINLOCK(rlock);
+
+static void __iomem *base;
+static struct regmap *pdrm;
+static struct clk_hw **hws;
+
+/* System clock parent */
+static const char * const sys_src[] = {
+ "hsi_ck", "csi_ck", "hse_ck", "pll1_p" };
+
+static const char * const tracein_src[] = {
+ "hsi_ck", "csi_ck", "hse_ck", "pll1_r" };
+
+static const char * const per_src[] = {
+ "hsi_ker", "csi_ker", "hse_ck", "disabled" };
+
+static const char * const pll_src[] = {
+ "hsi_ck", "csi_ck", "hse_ck", "no clock" };
+
+static const char * const sdmmc_src[] = { "pll1_q", "pll2_r" };
+
+static const char * const dsi_src[] = { "ck_dsi_phy", "pll2_q" };
+
+static const char * const qspi_src[] = {
+ "hclk", "pll1_q", "pll2_r", "per_ck" };
+
+static const char * const fmc_src[] = {
+ "hclk", "pll1_q", "pll2_r", "per_ck" };
+
+/* Kernel clock parent */
+static const char * const swp_src[] = { "pclk1", "hsi_ker" };
+
+static const char * const fdcan_src[] = { "hse_ck", "pll1_q", "pll2_q" };
+
+static const char * const dfsdm1_src[] = { "pclk2", "sys_ck" };
+
+static const char * const spdifrx_src[] = {
+ "pll1_q", "pll2_r", "pll3_r", "hsi_ker" };
+
+static const char *spi_src1[5] = {
+ "pll1_q", "pll2_p", "pll3_p", NULL, "per_ck" };
+
+static const char * const spi_src2[] = {
+ "pclk2", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "hse_ck" };
+
+static const char * const spi_src3[] = {
+ "pclk4", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "hse_ck" };
+
+static const char * const lptim_src1[] = {
+ "pclk1", "pll2_p", "pll3_r", "lse_ck", "lsi_ck", "per_ck" };
+
+static const char * const lptim_src2[] = {
+ "pclk4", "pll2_p", "pll3_r", "lse_ck", "lsi_ck", "per_ck" };
+
+static const char * const cec_src[] = {"lse_ck", "lsi_ck", "csi_ker_div122" };
+
+static const char * const usbotg_src[] = {"pll1_q", "pll3_q", "rc48_ck" };
+
+/* i2c 1,2,3 src */
+static const char * const i2c_src1[] = {
+ "pclk1", "pll3_r", "hsi_ker", "csi_ker" };
+
+static const char * const i2c_src2[] = {
+ "pclk4", "pll3_r", "hsi_ker", "csi_ker" };
+
+static const char * const rng_src[] = {
+ "rc48_ck", "pll1_q", "lse_ck", "lsi_ck" };
+
+/* usart 1,6 src */
+static const char * const usart_src1[] = {
+ "pclk2", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "lse_ck" };
+
+/* usart 2,3,4,5,7,8 src */
+static const char * const usart_src2[] = {
+ "pclk1", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "lse_ck" };
+
+static const char *sai_src[5] = {
+ "pll1_q", "pll2_p", "pll3_p", NULL, "per_ck" };
+
+static const char * const adc_src[] = { "pll2_p", "pll3_r", "per_ck" };
+
+/* lptim 2,3,4,5 src */
+static const char * const lpuart1_src[] = {
+ "pclk3", "pll2_q", "pll3_q", "csi_ker", "lse_ck" };
+
+static const char * const hrtim_src[] = { "tim2_ker", "d1cpre" };
+
+/* RTC clock parent */
+static const char * const rtc_src[] = { "off", "lse_ck", "lsi_ck", "hse_1M" };
+
+/* Micro-controller output clock parent */
+static const char * const mco_src1[] = {
+ "hsi_ck", "lse_ck", "hse_ck", "pll1_q", "rc48_ck" };
+
+static const char * const mco_src2[] = {
+ "sys_ck", "pll2_p", "hse_ck", "pll1_p", "csi", "lsi_ck" };
+
+/* LCD clock */
+static const char * const ltdc_src[] = {"pll3_r"};
+
+/* Power domain helper */
+static inline void disable_power_domain_write_protection(void)
+{
+ if (pdrm)
+ regmap_update_bits(pdrm, 0x00, (1 << 8), (1 << 8));
+}
+
+static inline void enable_power_domain_write_protection(void)
+{
+ if (pdrm)
+ regmap_update_bits(pdrm, 0x00, (1 << 8), (0 << 8));
+}
+
+static inline int is_enable_power_domain_write_protection(void)
+{
+ if (pdrm) {
+ u32 val;
+
+ regmap_read(pdrm, 0x00, &val);
+
+ return !(val & 0x100);
+ }
+ return -1;
+}
+
+/* Gate clock with ready bit and backup domain management */
+struct stm32_ready_gate {
+ struct clk_gate gate;
+ u8 bit_rdy;
+ u8 backup_domain;
+};
+
+#define to_ready_gate_clk(_rgate) container_of(_rgate, struct stm32_ready_gate,\
+ gate)
+
+#define RGATE_TIMEOUT 10000
+
+static int ready_gate_clk_is_enabled(struct clk_hw *hw)
+{
+ return clk_gate_ops.is_enabled(hw);
+}
+
+static int ready_gate_clk_enable(struct clk_hw *hw)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ struct stm32_ready_gate *rgate = to_ready_gate_clk(gate);
+ int dbp_status;
+ int bit_status;
+ unsigned int timeout = RGATE_TIMEOUT;
+
+ if (clk_gate_ops.is_enabled(hw))
+ return 0;
+
+ dbp_status = is_enable_power_domain_write_protection();
+
+ if (rgate->backup_domain && dbp_status)
+ disable_power_domain_write_protection();
+
+ clk_gate_ops.enable(hw);
+
+ do {
+ bit_status = !(readl(gate->reg) & BIT(rgate->bit_rdy));
+
+ if (bit_status)
+ udelay(100);
+
+ } while (bit_status && --timeout);
+
+ if (rgate->backup_domain && dbp_status)
+ enable_power_domain_write_protection();
+
+ return bit_status;
+}
+
+static void ready_gate_clk_disable(struct clk_hw *hw)
+{
+ clk_gate_ops.disable(hw);
+}
+
+static const struct clk_ops ready_gate_clk_ops = {
+ .enable = ready_gate_clk_enable,
+ .disable = ready_gate_clk_disable,
+ .is_enabled = ready_gate_clk_is_enabled,
+};
+
+static struct clk_hw *clk_register_ready_gate(struct device *dev,
+ const char *name, const char *parent_name,
+ void __iomem *reg, u8 bit_idx, u8 bit_rdy,
+ u8 backup_domain, unsigned long flags, spinlock_t *lock)
+{
+ struct stm32_ready_gate *rgate;
+ struct clk_init_data init = { NULL };
+ struct clk_hw *hw;
+ int ret;
+
+ rgate = kzalloc(sizeof(*rgate), GFP_KERNEL);
+ if (!rgate)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &ready_gate_clk_ops;
+ init.flags = flags;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ rgate->bit_rdy = bit_rdy;
+ rgate->backup_domain = backup_domain;
+
+ rgate->gate.lock = lock;
+ rgate->gate.reg = reg;
+ rgate->gate.bit_idx = bit_idx;
+ rgate->gate.hw.init = &init;
+
+ hw = &rgate->gate.hw;
+ ret = clk_hw_register(dev, hw);
+ if (ret) {
+ kfree(rgate);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
+
+struct gate_cfg {
+ u32 offset;
+ u8 bit_idx;
+};
+
+struct muxdiv_cfg {
+ u32 offset;
+ u8 shift;
+ u8 width;
+};
+
+struct composite_clk_cfg {
+ struct gate_cfg *gate;
+ struct muxdiv_cfg *mux;
+ struct muxdiv_cfg *div;
+ const char *name;
+ const char * const *parent_name;
+ int num_parents;
+ u32 flags;
+};
+
+struct composite_clk_gcfg_t {
+ u8 flags;
+ const struct clk_ops *ops;
+};
+
+/*
+ * General config definition of a composite clock (only clock diviser for rate)
+ */
+struct composite_clk_gcfg {
+ struct composite_clk_gcfg_t *mux;
+ struct composite_clk_gcfg_t *div;
+ struct composite_clk_gcfg_t *gate;
+};
+
+#define M_CFG_MUX(_mux_ops, _mux_flags)\
+ .mux = &(struct composite_clk_gcfg_t) { _mux_flags, _mux_ops}
+
+#define M_CFG_DIV(_rate_ops, _rate_flags)\
+ .div = &(struct composite_clk_gcfg_t) {_rate_flags, _rate_ops}
+
+#define M_CFG_GATE(_gate_ops, _gate_flags)\
+ .gate = &(struct composite_clk_gcfg_t) { _gate_flags, _gate_ops}
+
+static struct clk_mux *_get_cmux(void __iomem *reg, u8 shift, u8 width,
+ u32 flags, spinlock_t *lock)
+{
+ struct clk_mux *mux;
+
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ return ERR_PTR(-ENOMEM);
+
+ mux->reg = reg;
+ mux->shift = shift;
+ mux->mask = (1 << width) - 1;
+ mux->flags = flags;
+ mux->lock = lock;
+
+ return mux;
+}
+
+static struct clk_divider *_get_cdiv(void __iomem *reg, u8 shift, u8 width,
+ u32 flags, spinlock_t *lock)
+{
+ struct clk_divider *div;
+
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ div->reg = reg;
+ div->shift = shift;
+ div->width = width;
+ div->flags = flags;
+ div->lock = lock;
+
+ return div;
+}
+
+static struct clk_gate *_get_cgate(void __iomem *reg, u8 bit_idx, u32 flags,
+ spinlock_t *lock)
+{
+ struct clk_gate *gate;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
+ return ERR_PTR(-ENOMEM);
+
+ gate->reg = reg;
+ gate->bit_idx = bit_idx;
+ gate->flags = flags;
+ gate->lock = lock;
+
+ return gate;
+}
+
+struct composite_cfg {
+ struct clk_hw *mux_hw;
+ struct clk_hw *div_hw;
+ struct clk_hw *gate_hw;
+
+ const struct clk_ops *mux_ops;
+ const struct clk_ops *div_ops;
+ const struct clk_ops *gate_ops;
+};
+
+static void get_cfg_composite_div(const struct composite_clk_gcfg *gcfg,
+ const struct composite_clk_cfg *cfg,
+ struct composite_cfg *composite, spinlock_t *lock)
+{
+ struct clk_mux *mux = NULL;
+ struct clk_divider *div = NULL;
+ struct clk_gate *gate = NULL;
+ const struct clk_ops *mux_ops, *div_ops, *gate_ops;
+ struct clk_hw *mux_hw;
+ struct clk_hw *div_hw;
+ struct clk_hw *gate_hw;
+
+ mux_ops = div_ops = gate_ops = NULL;
+ mux_hw = div_hw = gate_hw = NULL;
+
+ if (gcfg->mux) {
+ mux = _get_cmux(base + cfg->mux->offset,
+ cfg->mux->shift,
+ cfg->mux->width,
+ gcfg->mux->flags, lock);
+
+ if (!IS_ERR(mux)) {
+ mux_hw = &mux->hw;
+ mux_ops = gcfg->mux->ops ?
+ gcfg->mux->ops : &clk_mux_ops;
+ }
+ }
+
+ if (gcfg->div) {
+ div = _get_cdiv(base + cfg->div->offset,
+ cfg->div->shift,
+ cfg->div->width,
+ gcfg->div->flags, lock);
+
+ if (!IS_ERR(div)) {
+ div_hw = &div->hw;
+ div_ops = gcfg->div->ops ?
+ gcfg->div->ops : &clk_divider_ops;
+ }
+
+ }
+
+ if (gcfg->gate) {
+ gate = _get_cgate(base + cfg->gate->offset,
+ cfg->gate->bit_idx,
+ gcfg->gate->flags, lock);
+
+ if (!IS_ERR(gate)) {
+ gate_hw = &gate->hw;
+ gate_ops = gcfg->gate->ops ?
+ gcfg->gate->ops : &clk_gate_ops;
+ }
+
+ }
+
+ composite->mux_hw = mux_hw;
+ composite->mux_ops = mux_ops;
+
+ composite->div_hw = div_hw;
+ composite->div_ops = div_ops;
+
+ composite->gate_hw = gate_hw;
+ composite->gate_ops = gate_ops;
+}
+
+/* Kernel Timer */
+struct timer_ker {
+ u8 dppre_shift;
+ struct clk_hw hw;
+ spinlock_t *lock;
+};
+
+#define to_timer_ker(_hw) container_of(_hw, struct timer_ker, hw)
+
+static unsigned long timer_ker_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct timer_ker *clk_elem = to_timer_ker(hw);
+ u32 timpre;
+ u32 dppre_shift = clk_elem->dppre_shift;
+ u32 prescaler;
+ u32 mul;
+
+ timpre = (readl(base + RCC_CFGR) >> 15) & 0x01;
+
+ prescaler = (readl(base + RCC_D2CFGR) >> dppre_shift) & 0x03;
+
+ mul = 2;
+
+ if (prescaler < 4)
+ mul = 1;
+
+ else if (timpre && prescaler > 4)
+ mul = 4;
+
+ return parent_rate * mul;
+}
+
+static const struct clk_ops timer_ker_ops = {
+ .recalc_rate = timer_ker_recalc_rate,
+};
+
+static struct clk_hw *clk_register_stm32_timer_ker(struct device *dev,
+ const char *name, const char *parent_name,
+ unsigned long flags,
+ u8 dppre_shift,
+ spinlock_t lock)
+{
+ struct timer_ker *element;
+ struct clk_init_data init;
+ struct clk_hw *hw;
+ int err;
+
+ element = kzalloc(sizeof(*element), GFP_KERNEL);
+ if (!element)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &timer_ker_ops;
+ init.flags = flags;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ element->hw.init = &init;
+ element->lock = &lock;
+ element->dppre_shift = dppre_shift;
+
+ hw = &element->hw;
+ err = clk_hw_register(dev, hw);
+
+ if (err) {
+ kfree(element);
+ return ERR_PTR(err);
+ }
+
+ return hw;
+}
+
+static const struct clk_div_table d1cpre_div_table[] = {
+ { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1},
+ { 4, 1 }, { 5, 1 }, { 6, 1 }, { 7, 1},
+ { 8, 2 }, { 9, 4 }, { 10, 8 }, { 11, 16 },
+ { 12, 64 }, { 13, 128 }, { 14, 256 },
+ { 15, 512 },
+ { 0 },
+};
+
+static const struct clk_div_table ppre_div_table[] = {
+ { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1},
+ { 4, 2 }, { 5, 4 }, { 6, 8 }, { 7, 16 },
+ { 0 },
+};
+
+static void register_core_and_bus_clocks(void)
+{
+ /* CORE AND BUS */
+ hws[SYS_D1CPRE] = clk_hw_register_divider_table(NULL, "d1cpre",
+ "sys_ck", CLK_IGNORE_UNUSED, base + RCC_D1CFGR, 8, 4, 0,
+ d1cpre_div_table, &rlock);
+
+ hws[HCLK] = clk_hw_register_divider_table(NULL, "hclk", "d1cpre",
+ CLK_IGNORE_UNUSED, base + RCC_D1CFGR, 0, 4, 0,
+ d1cpre_div_table, &rlock);
+
+ /* D1 DOMAIN */
+ /* * CPU Systick */
+ hws[CPU_SYSTICK] = clk_hw_register_fixed_factor(NULL, "systick",
+ "d1cpre", 0, 1, 8);
+
+ /* * APB3 peripheral */
+ hws[PCLK3] = clk_hw_register_divider_table(NULL, "pclk3", "hclk", 0,
+ base + RCC_D1CFGR, 4, 3, 0,
+ ppre_div_table, &rlock);
+
+ /* D2 DOMAIN */
+ /* * APB1 peripheral */
+ hws[PCLK1] = clk_hw_register_divider_table(NULL, "pclk1", "hclk", 0,
+ base + RCC_D2CFGR, 4, 3, 0,
+ ppre_div_table, &rlock);
+
+ /* Timers prescaler clocks */
+ clk_register_stm32_timer_ker(NULL, "tim1_ker", "pclk1", 0,
+ 4, rlock);
+
+ /* * APB2 peripheral */
+ hws[PCLK2] = clk_hw_register_divider_table(NULL, "pclk2", "hclk", 0,
+ base + RCC_D2CFGR, 8, 3, 0, ppre_div_table, &rlock);
+
+ clk_register_stm32_timer_ker(NULL, "tim2_ker", "pclk2", 0, 8, rlock);
+
+ /* D3 DOMAIN */
+ /* * APB4 peripheral */
+ hws[PCLK4] = clk_hw_register_divider_table(NULL, "pclk4", "hclk", 0,
+ base + RCC_D3CFGR, 4, 3, 0,
+ ppre_div_table, &rlock);
+}
+
+/* MUX clock configuration */
+struct stm32_mux_clk {
+ const char *name;
+ const char * const *parents;
+ u8 num_parents;
+ u32 offset;
+ u8 shift;
+ u8 width;
+ u32 flags;
+};
+
+#define M_MCLOCF(_name, _parents, _mux_offset, _mux_shift, _mux_width, _flags)\
+{\
+ .name = _name,\
+ .parents = _parents,\
+ .num_parents = ARRAY_SIZE(_parents),\
+ .offset = _mux_offset,\
+ .shift = _mux_shift,\
+ .width = _mux_width,\
+ .flags = _flags,\
+}
+#define M_MCLOC(_name, _parents, _mux_offset, _mux_shift, _mux_width)\
+ M_MCLOCF(_name, _parents, _mux_offset, _mux_shift, _mux_width, 0)\
+
+static const struct stm32_mux_clk stm32_mclk[] __initconst = {
+ M_MCLOC("per_ck", per_src, RCC_D1CCIPR, 28, 3),
+ M_MCLOC("pllsrc", pll_src, RCC_PLLCKSELR, 0, 3),
+ M_MCLOC("sys_ck", sys_src, RCC_CFGR, 0, 3),
+ M_MCLOC("tracein_ck", tracein_src, RCC_CFGR, 0, 3),
+};
+
+/* Oscillary clock configuration */
+struct stm32_osc_clk {
+ const char *name;
+ const char *parent;
+ u32 gate_offset;
+ u8 bit_idx;
+ u8 bit_rdy;
+ u32 flags;
+};
+
+#define OSC_CLKF(_name, _parent, _gate_offset, _bit_idx, _bit_rdy, _flags)\
+{\
+ .name = _name,\
+ .parent = _parent,\
+ .gate_offset = _gate_offset,\
+ .bit_idx = _bit_idx,\
+ .bit_rdy = _bit_rdy,\
+ .flags = _flags,\
+}
+#define OSC_CLK(_name, _parent, _gate_offset, _bit_idx, _bit_rdy)\
+ OSC_CLKF(_name, _parent, _gate_offset, _bit_idx, _bit_rdy, 0)
+
+static const struct stm32_osc_clk stm32_oclk[] __initconst = {
+ OSC_CLKF("hsi_ck", "hsidiv", RCC_CR, 0, 2, CLK_IGNORE_UNUSED),
+ OSC_CLKF("hsi_ker", "hsidiv", RCC_CR, 1, 2, CLK_IGNORE_UNUSED),
+ OSC_CLKF("csi_ck", "clk-csi", RCC_CR, 7, 8, CLK_IGNORE_UNUSED),
+ OSC_CLKF("csi_ker", "clk-csi", RCC_CR, 9, 8, CLK_IGNORE_UNUSED),
+ OSC_CLKF("rc48_ck", "clk-rc48", RCC_CR, 12, 13, CLK_IGNORE_UNUSED),
+ OSC_CLKF("lsi_ck", "clk-lsi", RCC_CSR, 0, 1, CLK_IGNORE_UNUSED),
+};
+
+/* PLL configuration */
+struct st32h7_pll_cfg {
+ u8 bit_idx;
+ u32 offset_divr;
+ u8 bit_frac_en;
+ u32 offset_frac;
+ u8 divm;
+};
+
+struct stm32_pll_data {
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ const struct st32h7_pll_cfg *cfg;
+};
+
+static const struct st32h7_pll_cfg stm32h7_pll1 = {
+ .bit_idx = 24,
+ .offset_divr = RCC_PLL1DIVR,
+ .bit_frac_en = 0,
+ .offset_frac = RCC_PLL1FRACR,
+ .divm = 4,
+};
+
+static const struct st32h7_pll_cfg stm32h7_pll2 = {
+ .bit_idx = 26,
+ .offset_divr = RCC_PLL2DIVR,
+ .bit_frac_en = 4,
+ .offset_frac = RCC_PLL2FRACR,
+ .divm = 12,
+};
+
+static const struct st32h7_pll_cfg stm32h7_pll3 = {
+ .bit_idx = 28,
+ .offset_divr = RCC_PLL3DIVR,
+ .bit_frac_en = 8,
+ .offset_frac = RCC_PLL3FRACR,
+ .divm = 20,
+};
+
+static const struct stm32_pll_data stm32_pll[] = {
+ { "vco1", "pllsrc", 0, &stm32h7_pll1 },
+ { "vco2", "pllsrc", 0, &stm32h7_pll2 },
+ { "vco3", "pllsrc", 0, &stm32h7_pll3 },
+};
+
+struct stm32_fractional_divider {
+ void __iomem *mreg;
+ u8 mshift;
+ u8 mwidth;
+ u32 mmask;
+
+ void __iomem *nreg;
+ u8 nshift;
+ u8 nwidth;
+
+ void __iomem *freg_status;
+ u8 freg_bit;
+ void __iomem *freg_value;
+ u8 fshift;
+ u8 fwidth;
+
+ u8 flags;
+ struct clk_hw hw;
+ spinlock_t *lock;
+};
+
+struct stm32_pll_obj {
+ spinlock_t *lock;
+ struct stm32_fractional_divider div;
+ struct stm32_ready_gate rgate;
+ struct clk_hw hw;
+};
+
+#define to_pll(_hw) container_of(_hw, struct stm32_pll_obj, hw)
+
+static int pll_is_enabled(struct clk_hw *hw)
+{
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
+ struct clk_hw *_hw = &clk_elem->rgate.gate.hw;
+
+ __clk_hw_set_clk(_hw, hw);
+
+ return ready_gate_clk_ops.is_enabled(_hw);
+}
+
+static int pll_enable(struct clk_hw *hw)
+{
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
+ struct clk_hw *_hw = &clk_elem->rgate.gate.hw;
+
+ __clk_hw_set_clk(_hw, hw);
+
+ return ready_gate_clk_ops.enable(_hw);
+}
+
+static void pll_disable(struct clk_hw *hw)
+{
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
+ struct clk_hw *_hw = &clk_elem->rgate.gate.hw;
+
+ __clk_hw_set_clk(_hw, hw);
+
+ ready_gate_clk_ops.disable(_hw);
+}
+
+static int pll_frac_is_enabled(struct clk_hw *hw)
+{
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
+ struct stm32_fractional_divider *fd = &clk_elem->div;
+
+ return (readl(fd->freg_status) >> fd->freg_bit) & 0x01;
+}
+
+static unsigned long pll_read_frac(struct clk_hw *hw)
+{
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
+ struct stm32_fractional_divider *fd = &clk_elem->div;
+
+ return (readl(fd->freg_value) >> fd->fshift) &
+ GENMASK(fd->fwidth - 1, 0);
+}
+
+static unsigned long pll_fd_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
+ struct stm32_fractional_divider *fd = &clk_elem->div;
+ unsigned long m, n;
+ u32 val, mask;
+ u64 rate, rate1 = 0;
+
+ val = clk_readl(fd->mreg);
+ mask = (GENMASK(fd->mwidth - 1, 0) << fd->mshift);
+ m = (val & mask) >> fd->mshift;
+
+ val = clk_readl(fd->nreg);
+ mask = (GENMASK(fd->nwidth - 1, 0) << fd->nshift);
+ n = ((val & mask) >> fd->nshift) + 1;
+
+ if (!n || !m)
+ return parent_rate;
+
+ rate = (u64)parent_rate * n;
+ do_div(rate, m);
+
+ if (pll_frac_is_enabled(hw)) {
+ val = pll_read_frac(hw);
+ rate1 = (u64) parent_rate * (u64) val;
+ do_div(rate1, (m * 8191));
+ }
+
+ return rate + rate1;
+}
+
+static const struct clk_ops pll_ops = {
+ .enable = pll_enable,
+ .disable = pll_disable,
+ .is_enabled = pll_is_enabled,
+ .recalc_rate = pll_fd_recalc_rate,
+};
+
+static struct clk_hw *clk_register_stm32_pll(struct device *dev,
+ const char *name,
+ const char *parent,
+ unsigned long flags,
+ const struct st32h7_pll_cfg *cfg,
+ spinlock_t *lock)
+{
+
+ struct stm32_pll_obj *pll;
+ struct clk_init_data init = { NULL };
+ struct clk_hw *hw;
+ int ret;
+ struct stm32_fractional_divider *div = NULL;
+ struct stm32_ready_gate *rgate;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &pll_ops;
+ init.flags = flags;
+ init.parent_names = &parent;
+ init.num_parents = 1;
+ pll->hw.init = &init;
+
+ hw = &pll->hw;
+ rgate = &pll->rgate;
+
+ rgate->bit_rdy = cfg->bit_idx + 1;
+ rgate->gate.lock = lock;
+ rgate->gate.reg = base + RCC_CR;
+ rgate->gate.bit_idx = cfg->bit_idx;
+
+ div = &pll->div;
+ div->flags = 0;
+ div->mreg = base + RCC_PLLCKSELR;
+ div->mshift = cfg->divm;
+ div->mwidth = 6;
+ div->nreg = base + cfg->offset_divr;
+ div->nshift = 0;
+ div->nwidth = 9;
+
+ div->freg_status = base + RCC_PLLCFGR;
+ div->freg_bit = cfg->bit_frac_en;
+ div->freg_value = base + cfg->offset_frac;
+ div->fshift = 3;
+ div->fwidth = 13;
+
+ div->lock = lock;
+
+ ret = clk_hw_register(dev, hw);
+ if (ret) {
+ kfree(pll);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
+
+/* ODF CLOCKS */
+static unsigned long odf_divider_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return clk_divider_ops.recalc_rate(hw, parent_rate);
+}
+
+static long odf_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ return clk_divider_ops.round_rate(hw, rate, prate);
+}
+
+static int odf_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_hw *hwp;
+ int pll_status;
+ int ret;
+
+ hwp = clk_hw_get_parent(hw);
+
+ pll_status = pll_is_enabled(hwp);
+
+ if (pll_status)
+ pll_disable(hwp);
+
+ ret = clk_divider_ops.set_rate(hw, rate, parent_rate);
+
+ if (pll_status)
+ pll_enable(hwp);
+
+ return ret;
+}
+
+static const struct clk_ops odf_divider_ops = {
+ .recalc_rate = odf_divider_recalc_rate,
+ .round_rate = odf_divider_round_rate,
+ .set_rate = odf_divider_set_rate,
+};
+
+static int odf_gate_enable(struct clk_hw *hw)
+{
+ struct clk_hw *hwp;
+ int pll_status;
+ int ret;
+
+ hwp = clk_hw_get_parent(hw);
+
+ pll_status = pll_is_enabled(hwp);
+
+ if (pll_status)
+ pll_disable(hwp);
+
+ ret = clk_gate_ops.enable(hw);
+
+ if (pll_status)
+ pll_enable(hwp);
+
+ return ret;
+}
+
+static void odf_gate_disable(struct clk_hw *hw)
+{
+ clk_gate_ops.disable(hw);
+}
+
+static int odf_gate_is_enabled(struct clk_hw *hw)
+{
+ return clk_gate_ops.is_enabled(hw);
+}
+
+static const struct clk_ops odf_gate_ops = {
+ .enable = odf_gate_enable,
+ .disable = odf_gate_disable,
+ .is_enabled = odf_gate_is_enabled,
+};
+
+static struct composite_clk_gcfg odf_clk_gcfg = {
+ M_CFG_DIV(&odf_divider_ops, 0),
+ M_CFG_GATE(&odf_gate_ops, 0),
+};
+
+#define M_ODF_F(_name, _parent, _gate_offset, _bit_idx, _rate_offset,\
+ _rate_shift, _rate_width, _flags)\
+{\
+ .mux = NULL,\
+ .div = &(struct muxdiv_cfg) {_rate_offset, _rate_shift, _rate_width},\
+ .gate = &(struct gate_cfg) {_gate_offset, _bit_idx },\
+ .name = _name,\
+ .parent_name = &(const char *) {_parent},\
+ .num_parents = 1,\
+ .flags = _flags,\
+}
+
+#define M_ODF(_name, _parent, _gate_offset, _bit_idx, _rate_offset,\
+ _rate_shift, _rate_width)\
+M_ODF_F(_name, _parent, _gate_offset, _bit_idx, _rate_offset,\
+ _rate_shift, _rate_width, 0)\
+
+static const struct composite_clk_cfg stm32_odf[3][3] = {
+ {
+ M_ODF("pll1_p", "vco1", RCC_PLLCFGR, 16, RCC_PLL1DIVR, 9, 7),
+ M_ODF("pll1_q", "vco1", RCC_PLLCFGR, 17, RCC_PLL1DIVR, 16, 7),
+ M_ODF("pll1_r", "vco1", RCC_PLLCFGR, 18, RCC_PLL1DIVR, 24, 7),
+ },
+
+ {
+ M_ODF("pll2_p", "vco2", RCC_PLLCFGR, 19, RCC_PLL2DIVR, 9, 7),
+ M_ODF("pll2_q", "vco2", RCC_PLLCFGR, 20, RCC_PLL2DIVR, 16, 7),
+ M_ODF("pll2_r", "vco2", RCC_PLLCFGR, 21, RCC_PLL2DIVR, 24, 7),
+ },
+ {
+ M_ODF("pll3_p", "vco3", RCC_PLLCFGR, 22, RCC_PLL3DIVR, 9, 7),
+ M_ODF("pll3_q", "vco3", RCC_PLLCFGR, 23, RCC_PLL3DIVR, 16, 7),
+ M_ODF("pll3_r", "vco3", RCC_PLLCFGR, 24, RCC_PLL3DIVR, 24, 7),
+ }
+};
+
+/* PLL config structure from DT */
+struct pll_param {
+ u32 index;
+ u32 mult;
+ u32 div;
+ u32 frac;
+ u32 vcosel;
+};
+
+static int of_get_stm32_pll(struct device_node *np, struct pll_param *param)
+{
+ if (of_property_read_u32(np, "reg", ¶m->index) ||
+ param->index >= ARRAY_SIZE(stm32_pll))
+ return -EINVAL;
+
+ of_property_read_u32(np, "st,clock-div", ¶m->div);
+
+ of_property_read_u32(np, "st,clock-mult", ¶m->mult);
+
+ param->frac = ~0;
+ of_property_read_u32(np, "st,frac", ¶m->frac);
+
+ param->vcosel = ~0;
+ of_property_read_u32(np, "st,vcosel", ¶m->vcosel);
+
+ return 0;
+}
+
+
+static void stm32_pll_save_param(struct pll_param *pll_dt_cfg,
+ const struct st32h7_pll_cfg *cfg)
+{
+ unsigned long m, n;
+ u32 val, mask;
+ int idx = pll_dt_cfg->index;
+ int pll_status, pllrge;
+ unsigned long ref_ck;
+
+
+ /* Save PLL parameters from DT if needed */
+ m = pll_dt_cfg->div;
+ n = pll_dt_cfg->mult;
+ if (!(n || m || pll_dt_cfg->frac != ~0 ||
+ pll_dt_cfg->vcosel != ~0))
+ return;
+
+ /* We have to disable pll before modify pll register */
+ val = clk_readl(base + RCC_CR);
+ pll_status = val & BIT(cfg->bit_idx);
+ if (pll_status) {
+ val &= ~BIT(cfg->bit_idx);
+ writel(val, base + RCC_CR);
+ }
+
+ /* Save DIVM division factor */
+ val = clk_readl(base + RCC_PLLCKSELR);
+ mask = 0x3f << cfg->divm;
+ if (m) {
+ val &= ~mask;
+ val |= (m << cfg->divm);
+ writel(val, base + RCC_PLLCKSELR);
+ } else
+ m = (val & mask) >> cfg->divm ?: 1;
+
+ /* Save DIVN multiplication factor */
+ if (n) {
+ val = clk_readl(base + cfg->offset_divr);
+ val &= ~0x1ff;
+ val |= (n - 1);
+ writel(val, base + cfg->offset_divr);
+ }
+
+ /* If there is a "st,frac" property */
+ if (pll_dt_cfg->frac != ~0) {
+ u32 val_status;
+ int status = 0;
+
+ /* 0: pll is configured in integer mode */
+ /* else is configured in fractional mode */
+ if (pll_dt_cfg->frac)
+ status = 1;
+
+ /* clear frac status before */
+ val_status = readl(base + RCC_PLLCFGR);
+ val_status &= ~BIT(cfg->bit_frac_en);
+ writel(val_status, base + RCC_PLLCFGR);
+
+ /* Save the fractional factor */
+ if (status) {
+ /* write frac value */
+ val = clk_readl(base + cfg->offset_frac);
+ val &= ~(0x1fff << 3);
+ val |= ((pll_dt_cfg->frac) << 3);
+ writel(val, base + cfg->offset_frac);
+
+ /* Enable fractional mode */
+ val_status |= status << cfg->bit_frac_en;
+ writel(val_status, base + RCC_PLLCFGR);
+ }
+ }
+
+ /* Save VCO frequency range */
+ if (pll_dt_cfg->vcosel != ~0) {
+ val = readl(base + RCC_PLLCFGR);
+ val &= ~BIT(cfg->bit_frac_en + 1);
+ val |= (pll_dt_cfg->vcosel & 0x01) << (cfg->bit_frac_en + 1);
+ writel(val, base + RCC_PLLCFGR);
+ }
+
+ /* Update PLLRGE */
+ ref_ck = clk_get_rate(__clk_lookup(stm32_pll[idx].parent_name)) / m;
+
+ pllrge = 3;
+ if (ref_ck < 2000000)
+ pllrge = 0;
+ else if (ref_ck < 4000000)
+ pllrge = 1;
+ else if (ref_ck < 8000000)
+ pllrge = 2;
+
+ /* Write reference frequency range */
+ val = readl(base + RCC_PLLCFGR);
+ val &= ~(0x3 << (cfg->bit_frac_en + 2));
+ val |= (pllrge & 0x3) << (cfg->bit_frac_en + 2);
+ writel(val, base + RCC_PLLCFGR);
+
+ /* Restore pll status */
+ if (pll_status) {
+ val = clk_readl(base + RCC_CR);
+ val |= BIT(cfg->bit_idx);
+ writel(val, base + RCC_CR);
+ }
+}
+
+static void stm32_h7_pll_init(struct device_node *np)
+{
+ struct pll_param pll_dt_cfg = { };
+ struct clk_hw *hw;
+ int idx, n;
+
+ if (of_get_stm32_pll(np, &pll_dt_cfg))
+ return;
+
+ idx = pll_dt_cfg.index;
+
+ stm32_pll_save_param(&pll_dt_cfg, stm32_pll[idx].cfg);
+
+ /* Register the VCO */
+ hw = clk_register_stm32_pll(NULL, stm32_pll[idx].name,
+ stm32_pll[idx].parent_name, stm32_pll[idx].flags,
+ stm32_pll[idx].cfg,
+ &rlock);
+
+ /* Register the 3 output dividers */
+ for (n = 0; n < 3; n++) {
+ struct composite_cfg c_cfg;
+
+ get_cfg_composite_div(&odf_clk_gcfg, &stm32_odf[idx][n],
+ &c_cfg, &rlock);
+
+ hws[ODF_BANK + (idx * 3) + n] = clk_hw_register_composite(NULL,
+ stm32_odf[idx][n].name,
+ stm32_odf[idx][n].parent_name,
+ stm32_odf[idx][n].num_parents,
+ c_cfg.mux_hw, c_cfg.mux_ops,
+ c_cfg.div_hw, c_cfg.div_ops,
+ c_cfg.gate_hw, c_cfg.gate_ops,
+ stm32_odf[idx][n].flags);
+ }
+}
+
+/* PERIF CLOCKS */
+struct pclk_t {
+ u32 gate_offset;
+ u8 bit_idx;
+ const char *name;
+ const char *parent;
+ u32 flags;
+};
+
+#define PER_CLKF(_gate_offset, _bit_idx, _name, _parent, _flags)\
+{\
+ .gate_offset = _gate_offset,\
+ .bit_idx = _bit_idx,\
+ .name = _name,\
+ .parent = _parent,\
+ .flags = _flags,\
+}
+#define PER_CLK(_gate_offset, _bit_idx, _name, _parent)\
+ PER_CLKF(_gate_offset, _bit_idx, _name, _parent, 0)
+
+static const struct pclk_t pclk[] = {
+ PER_CLK(RCC_AHB3ENR, 31, "d1sram1", "hclk"),
+ PER_CLK(RCC_AHB3ENR, 30, "itcm", "hclk"),
+ PER_CLK(RCC_AHB3ENR, 29, "dtcm2", "hclk"),
+ PER_CLK(RCC_AHB3ENR, 28, "dtcm1", "hclk"),
+ PER_CLK(RCC_AHB3ENR, 8, "flitf", "hclk"),
+ PER_CLK(RCC_AHB3ENR, 5, "jpgdec", "hclk"),
+ PER_CLK(RCC_AHB3ENR, 4, "dma2d", "hclk"),
+ PER_CLK(RCC_AHB3ENR, 0, "mdma", "hclk"),
+ PER_CLK(RCC_AHB1ENR, 28, "usb2ulpi", "hclk"),
+ PER_CLK(RCC_AHB1ENR, 26, "usb1ulpi", "hclk"),
+ PER_CLK(RCC_AHB1ENR, 17, "eth1rx", "hclk"),
+ PER_CLK(RCC_AHB1ENR, 16, "eth1tx", "hclk"),
+ PER_CLK(RCC_AHB1ENR, 15, "eth1mac", "hclk"),
+ PER_CLK(RCC_AHB1ENR, 14, "art", "hclk"),
+ PER_CLK(RCC_AHB1ENR, 1, "dma2", "hclk"),
+ PER_CLK(RCC_AHB1ENR, 0, "dma1", "hclk"),
+ PER_CLK(RCC_AHB2ENR, 31, "d2sram3", "hclk"),
+ PER_CLK(RCC_AHB2ENR, 30, "d2sram2", "hclk"),
+ PER_CLK(RCC_AHB2ENR, 29, "d2sram1", "hclk"),
+ PER_CLK(RCC_AHB2ENR, 5, "hash", "hclk"),
+ PER_CLK(RCC_AHB2ENR, 4, "crypt", "hclk"),
+ PER_CLK(RCC_AHB2ENR, 0, "camitf", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 28, "bkpram", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 25, "hsem", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 21, "bdma", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 19, "crc", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 10, "gpiok", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 9, "gpioj", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 8, "gpioi", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 7, "gpioh", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 6, "gpiog", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 5, "gpiof", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 4, "gpioe", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 3, "gpiod", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 2, "gpioc", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 1, "gpiob", "hclk"),
+ PER_CLK(RCC_AHB4ENR, 0, "gpioa", "hclk"),
+ PER_CLK(RCC_APB3ENR, 6, "wwdg1", "pclk3"),
+ PER_CLK(RCC_APB1LENR, 29, "dac12", "pclk1"),
+ PER_CLK(RCC_APB1LENR, 11, "wwdg2", "pclk1"),
+ PER_CLK(RCC_APB1LENR, 8, "tim14", "pclk1"),
+ PER_CLK(RCC_APB1LENR, 7, "tim13", "pclk1"),
+ PER_CLK(RCC_APB1LENR, 6, "tim12", "pclk1"),
+ PER_CLK(RCC_APB1LENR, 5, "tim7", "pclk1"),
+ PER_CLK(RCC_APB1LENR, 4, "tim6", "pclk1"),
+ PER_CLK(RCC_APB1LENR, 3, "tim5", "pclk1"),
+ PER_CLK(RCC_APB1LENR, 2, "tim4", "pclk1"),
+ PER_CLK(RCC_APB1LENR, 1, "tim3", "pclk1"),
+ PER_CLK(RCC_APB1LENR, 0, "tim2", "pclk1"),
+ PER_CLK(RCC_APB1HENR, 5, "mdios", "pclk1"),
+ PER_CLK(RCC_APB1HENR, 4, "opamp", "pclk1"),
+ PER_CLK(RCC_APB1HENR, 1, "crs", "pclk1"),
+ PER_CLK(RCC_APB2ENR, 18, "tim17", "pclk2"),
+ PER_CLK(RCC_APB2ENR, 17, "tim16", "pclk2"),
+ PER_CLK(RCC_APB2ENR, 16, "tim15", "pclk2"),
+ PER_CLK(RCC_APB2ENR, 1, "tim8", "pclk2"),
+ PER_CLK(RCC_APB2ENR, 0, "tim1", "pclk2"),
+ PER_CLK(RCC_APB4ENR, 26, "tmpsens", "pclk4"),
+ PER_CLK(RCC_APB4ENR, 16, "rtcapb", "pclk4"),
+ PER_CLK(RCC_APB4ENR, 15, "vref", "pclk4"),
+ PER_CLK(RCC_APB4ENR, 14, "comp12", "pclk4"),
+ PER_CLK(RCC_APB4ENR, 1, "syscfg", "pclk4"),
+};
+
+/* KERNEL CLOCKS */
+#define KER_CLKF(_gate_offset, _bit_idx,\
+ _mux_offset, _mux_shift, _mux_width,\
+ _name, _parent_name,\
+ _flags) \
+{ \
+ .gate = &(struct gate_cfg) {_gate_offset, _bit_idx},\
+ .mux = &(struct muxdiv_cfg) {_mux_offset, _mux_shift, _mux_width },\
+ .name = _name, \
+ .parent_name = _parent_name, \
+ .num_parents = ARRAY_SIZE(_parent_name),\
+ .flags = _flags,\
+}
+#define KER_CLK(_gate_offset, _bit_idx, _mux_offset, _mux_shift, _mux_width,\
+ _name, _parent_name) \
+KER_CLKF(_gate_offset, _bit_idx, _mux_offset, _mux_shift, _mux_width,\
+ _name, _parent_name, 0)\
+
+#define KER_CLKF_NOMUX(_gate_offset, _bit_idx,\
+ _name, _parent_name,\
+ _flags) \
+{ \
+ .gate = &(struct gate_cfg) {_gate_offset, _bit_idx},\
+ .mux = NULL,\
+ .name = _name, \
+ .parent_name = _parent_name, \
+ .num_parents = 1,\
+ .flags = _flags,\
+}
+
+static const struct composite_clk_cfg kclk[] = {
+ KER_CLK(RCC_AHB3ENR, 16, RCC_D1CCIPR, 16, 1, "sdmmc1", sdmmc_src),
+ KER_CLKF(RCC_AHB3ENR, 14, RCC_D1CCIPR, 4, 2, "quadspi", qspi_src,
+ CLK_IGNORE_UNUSED),
+ KER_CLKF(RCC_AHB3ENR, 12, RCC_D1CCIPR, 0, 2, "fmc", fmc_src,
+ CLK_IGNORE_UNUSED),
+ KER_CLK(RCC_AHB1ENR, 27, RCC_D2CCIP2R, 20, 2, "usb2otg", usbotg_src),
+ KER_CLK(RCC_AHB1ENR, 25, RCC_D2CCIP2R, 20, 2, "usb1otg", usbotg_src),
+ KER_CLK(RCC_AHB1ENR, 5, RCC_D3CCIPR, 16, 2, "adc12", adc_src),
+ KER_CLK(RCC_AHB2ENR, 9, RCC_D1CCIPR, 16, 1, "sdmmc2", sdmmc_src),
+ KER_CLK(RCC_AHB2ENR, 6, RCC_D2CCIP2R, 8, 2, "rng", rng_src),
+ KER_CLK(RCC_AHB4ENR, 24, RCC_D3CCIPR, 16, 2, "adc3", adc_src),
+ KER_CLK(RCC_APB3ENR, 4, RCC_D1CCIPR, 8, 1, "dsi", dsi_src),
+ KER_CLKF_NOMUX(RCC_APB3ENR, 3, "ltdc", ltdc_src, 0),
+ KER_CLK(RCC_APB1LENR, 31, RCC_D2CCIP2R, 0, 3, "usart8", usart_src2),
+ KER_CLK(RCC_APB1LENR, 30, RCC_D2CCIP2R, 0, 3, "usart7", usart_src2),
+ KER_CLK(RCC_APB1LENR, 27, RCC_D2CCIP2R, 22, 2, "hdmicec", cec_src),
+ KER_CLK(RCC_APB1LENR, 23, RCC_D2CCIP2R, 12, 2, "i2c3", i2c_src1),
+ KER_CLK(RCC_APB1LENR, 22, RCC_D2CCIP2R, 12, 2, "i2c2", i2c_src1),
+ KER_CLK(RCC_APB1LENR, 21, RCC_D2CCIP2R, 12, 2, "i2c1", i2c_src1),
+ KER_CLK(RCC_APB1LENR, 20, RCC_D2CCIP2R, 0, 3, "uart5", usart_src2),
+ KER_CLK(RCC_APB1LENR, 19, RCC_D2CCIP2R, 0, 3, "uart4", usart_src2),
+ KER_CLK(RCC_APB1LENR, 18, RCC_D2CCIP2R, 0, 3, "usart3", usart_src2),
+ KER_CLK(RCC_APB1LENR, 17, RCC_D2CCIP2R, 0, 3, "usart2", usart_src2),
+ KER_CLK(RCC_APB1LENR, 16, RCC_D2CCIP1R, 20, 2, "spdifrx", spdifrx_src),
+ KER_CLK(RCC_APB1LENR, 15, RCC_D2CCIP1R, 16, 3, "spi3", spi_src1),
+ KER_CLK(RCC_APB1LENR, 14, RCC_D2CCIP1R, 16, 3, "spi2", spi_src1),
+ KER_CLK(RCC_APB1LENR, 9, RCC_D2CCIP2R, 28, 3, "lptim1", lptim_src1),
+ KER_CLK(RCC_APB1HENR, 8, RCC_D2CCIP1R, 28, 2, "fdcan", fdcan_src),
+ KER_CLK(RCC_APB1HENR, 2, RCC_D2CCIP1R, 31, 1, "swp", swp_src),
+ KER_CLK(RCC_APB2ENR, 29, RCC_CFGR, 14, 1, "hrtim", hrtim_src),
+ KER_CLK(RCC_APB2ENR, 28, RCC_D2CCIP1R, 24, 1, "dfsdm1", dfsdm1_src),
+ KER_CLK(RCC_APB2ENR, 24, RCC_D2CCIP1R, 6, 3, "sai3", sai_src),
+ KER_CLK(RCC_APB2ENR, 23, RCC_D2CCIP1R, 6, 3, "sai2", sai_src),
+ KER_CLK(RCC_APB2ENR, 22, RCC_D2CCIP1R, 0, 3, "sai1", sai_src),
+ KER_CLK(RCC_APB2ENR, 20, RCC_D2CCIP1R, 16, 3, "spi5", spi_src2),
+ KER_CLK(RCC_APB2ENR, 13, RCC_D2CCIP1R, 16, 3, "spi4", spi_src2),
+ KER_CLK(RCC_APB2ENR, 12, RCC_D2CCIP1R, 16, 3, "spi1", spi_src1),
+ KER_CLK(RCC_APB2ENR, 5, RCC_D2CCIP2R, 3, 3, "usart6", usart_src1),
+ KER_CLK(RCC_APB2ENR, 4, RCC_D2CCIP2R, 3, 3, "usart1", usart_src1),
+ KER_CLK(RCC_APB4ENR, 21, RCC_D3CCIPR, 24, 3, "sai4b", sai_src),
+ KER_CLK(RCC_APB4ENR, 21, RCC_D3CCIPR, 21, 3, "sai4a", sai_src),
+ KER_CLK(RCC_APB4ENR, 12, RCC_D3CCIPR, 13, 3, "lptim5", lptim_src2),
+ KER_CLK(RCC_APB4ENR, 11, RCC_D3CCIPR, 13, 3, "lptim4", lptim_src2),
+ KER_CLK(RCC_APB4ENR, 10, RCC_D3CCIPR, 13, 3, "lptim3", lptim_src2),
+ KER_CLK(RCC_APB4ENR, 9, RCC_D3CCIPR, 10, 3, "lptim2", lptim_src2),
+ KER_CLK(RCC_APB4ENR, 7, RCC_D3CCIPR, 8, 2, "i2c4", i2c_src2),
+ KER_CLK(RCC_APB4ENR, 5, RCC_D3CCIPR, 28, 3, "spi6", spi_src3),
+ KER_CLK(RCC_APB4ENR, 3, RCC_D3CCIPR, 0, 3, "lpuart1", lpuart1_src),
+};
+
+static struct composite_clk_gcfg kernel_clk_cfg = {
+ M_CFG_MUX(NULL, 0),
+ M_CFG_GATE(NULL, 0),
+};
+
+/* RTC clock */
+static u8 rtc_mux_get_parent(struct clk_hw *hw)
+{
+ return clk_mux_ops.get_parent(hw);
+}
+
+static int rtc_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ int dbp_status;
+ int err;
+
+ dbp_status = is_enable_power_domain_write_protection();
+
+ if (dbp_status)
+ disable_power_domain_write_protection();
+
+ err = clk_mux_ops.set_parent(hw, index);
+
+ if (dbp_status)
+ enable_power_domain_write_protection();
+
+ return err;
+}
+
+static int rtc_mux_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ return clk_mux_ops.determine_rate(hw, req);
+}
+
+static const struct clk_ops rtc_mux_ops = {
+ .get_parent = rtc_mux_get_parent,
+ .set_parent = rtc_mux_set_parent,
+ .determine_rate = rtc_mux_determine_rate,
+};
+
+/* Clock gate with backup domain protection management */
+static int bd_gate_enable(struct clk_hw *hw)
+{
+ int dbp_status;
+ int err;
+
+ dbp_status = is_enable_power_domain_write_protection();
+
+ if (dbp_status)
+ disable_power_domain_write_protection();
+
+ err = clk_gate_ops.enable(hw);
+
+ if (dbp_status)
+ enable_power_domain_write_protection();
+
+ return err;
+}
+
+static void bd_gate_disable(struct clk_hw *hw)
+{
+ clk_gate_ops.disable(hw);
+}
+
+static int bd_gate_is_enabled(struct clk_hw *hw)
+{
+ return clk_gate_ops.is_enabled(hw);
+}
+
+static const struct clk_ops bd_gate_ops = {
+ .enable = bd_gate_enable,
+ .disable = bd_gate_disable,
+ .is_enabled = bd_gate_is_enabled,
+};
+
+static struct composite_clk_gcfg rtc_clk_cfg = {
+ M_CFG_MUX(&rtc_mux_ops, 0),
+ M_CFG_GATE(&bd_gate_ops, 0),
+};
+
+static const struct composite_clk_cfg rtc_clk =
+ KER_CLK(RCC_BDCR, 15, RCC_BDCR, 8, 2, "rtc_ck", rtc_src);
+
+/* Micro-controller output clock */
+static struct composite_clk_gcfg mco_clk_cfg = {
+ M_CFG_MUX(NULL, 0),
+ M_CFG_DIV(NULL, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
+};
+
+#define M_MCO_F(_name, _parents, _mux_offset, _mux_shift, _mux_width,\
+ _rate_offset, _rate_shift, _rate_width,\
+ _flags)\
+{\
+ .mux = &(struct muxdiv_cfg) {_mux_offset, _mux_shift, _mux_width },\
+ .div = &(struct muxdiv_cfg) {_rate_offset, _rate_shift, _rate_width},\
+ .gate = NULL,\
+ .name = _name,\
+ .parent_name = _parents,\
+ .num_parents = ARRAY_SIZE(_parents),\
+ .flags = _flags,\
+}
+
+static const struct composite_clk_cfg mco_clk[] = {
+ M_MCO_F("mco1", mco_src1, RCC_CFGR, 22, 4, RCC_CFGR, 18, 4, 0),
+ M_MCO_F("mco2", mco_src2, RCC_CFGR, 29, 3, RCC_CFGR, 25, 4, 0),
+};
+
+static void __init stm32h7_rcc_init(struct device_node *np)
+{
+ struct clk_hw_onecell_data *clk_data;
+ struct device_node *node;
+ struct composite_cfg c_cfg;
+ int n;
+ const char *hse_clk, *lse_clk, *i2s_clk;
+
+ clk_data = kzalloc(sizeof(*clk_data) +
+ sizeof(*clk_data->hws) * STM32H7_MAX_CLKS,
+ GFP_KERNEL);
+ if (!clk_data)
+ return;
+
+ clk_data->num = STM32H7_MAX_CLKS;
+
+ hws = clk_data->hws;
+
+ for (n = 0; n < STM32H7_MAX_CLKS; n++)
+ hws[n] = ERR_PTR(-ENOENT);
+
+ /* get RCC base @ from DT */
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_err("%s: unable to map resource", np->name);
+ goto err_free_clks;
+ }
+
+ pdrm = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+ if (IS_ERR(pdrm)) {
+ pdrm = NULL;
+ pr_warn("%s: Unable to get syscfg\n", __func__);
+ }
+
+ /* Put parent names from DT */
+ hse_clk = of_clk_get_parent_name(np, 0);
+ lse_clk = of_clk_get_parent_name(np, 1);
+ i2s_clk = of_clk_get_parent_name(np, 2);
+
+ sai_src[3] = i2s_clk;
+ spi_src1[3] = i2s_clk;
+
+ /* Register Internal oscillators */
+ clk_hw_register_fixed_rate(NULL, "clk-hsi", NULL, 0, 64000000);
+ clk_hw_register_fixed_rate(NULL, "clk-csi", NULL, 0, 4000000);
+ clk_hw_register_fixed_rate(NULL, "clk-lsi", NULL, 0, 32000);
+ clk_hw_register_fixed_rate(NULL, "clk-rc48", NULL, 0, 48000);
+
+ /* This clock is coming from outside. Frequencies unknown */
+ hws[CK_DSI_PHY] = clk_hw_register_fixed_rate(NULL, "ck_dsi_phy", NULL,
+ 0, 0);
+
+ hws[HSI_DIV] = clk_hw_register_divider(NULL, "hsidiv", "clk-hsi", 0,
+ base + RCC_CR, 3, 2, CLK_DIVIDER_POWER_OF_TWO,
+ &rlock);
+
+ hws[HSE_1M] = clk_hw_register_divider(NULL, "hse_1M", "hse_ck", 0,
+ base + RCC_CFGR, 8, 6, CLK_DIVIDER_ONE_BASED |
+ CLK_DIVIDER_ALLOW_ZERO,
+ &rlock);
+
+ /* Mux system clocks */
+ for (n = 0; n < ARRAY_SIZE(stm32_mclk); n++)
+ hws[MCLK_BANK + n] = clk_hw_register_mux(NULL,
+ stm32_mclk[n].name,
+ stm32_mclk[n].parents,
+ stm32_mclk[n].num_parents,
+ stm32_mclk[n].flags,
+ stm32_mclk[n].offset + base,
+ stm32_mclk[n].shift,
+ stm32_mclk[n].width,
+ 0,
+ &rlock);
+
+ register_core_and_bus_clocks();
+
+ /* Oscillary clocks */
+ for (n = 0; n < ARRAY_SIZE(stm32_oclk); n++)
+ hws[OSC_BANK + n] = clk_register_ready_gate(NULL,
+ stm32_oclk[n].name,
+ stm32_oclk[n].parent,
+ stm32_oclk[n].gate_offset + base,
+ stm32_oclk[n].bit_idx,
+ stm32_oclk[n].bit_rdy,
+ 0,
+ stm32_oclk[n].flags,
+ &rlock);
+
+ hws[HSE_CK] = clk_register_ready_gate(NULL,
+ "hse_ck",
+ hse_clk,
+ RCC_CR + base,
+ 16, 17,
+ 0,
+ 0,
+ &rlock);
+
+ hws[LSE_CK] = clk_register_ready_gate(NULL,
+ "lse_ck",
+ lse_clk,
+ RCC_BDCR + base,
+ 0, 1,
+ 1,
+ 0,
+ &rlock);
+
+ hws[CSI_KER_DIV122 + n] = clk_hw_register_fixed_factor(NULL,
+ "csi_ker_div122", "csi_ker", 0, 1, 122);
+
+ /* PLLs */
+ for_each_compatible_node(node, NULL, "stm32h7-pll")
+ stm32_h7_pll_init(node);
+
+ /* Peripheral clocks */
+ for (n = 0; n < ARRAY_SIZE(pclk); n++)
+ hws[PERIF_BANK + n] = clk_hw_register_gate(NULL, pclk[n].name,
+ pclk[n].parent,
+ pclk[n].flags, base + pclk[n].gate_offset,
+ pclk[n].bit_idx, pclk[n].flags, &rlock);
+
+ /* Kernel clocks */
+ for (n = 0; n < ARRAY_SIZE(kclk); n++) {
+ get_cfg_composite_div(&kernel_clk_cfg, &kclk[n], &c_cfg,
+ &rlock);
+
+ hws[KERN_BANK + n] = clk_hw_register_composite(NULL,
+ kclk[n].name,
+ kclk[n].parent_name,
+ kclk[n].num_parents,
+ c_cfg.mux_hw, c_cfg.mux_ops,
+ c_cfg.div_hw, c_cfg.div_ops,
+ c_cfg.gate_hw, c_cfg.gate_ops,
+ kclk[n].flags);
+ }
+
+ /* RTC clock (default state is off) */
+ clk_hw_register_fixed_rate(NULL, "off", NULL, 0, 0);
+
+ get_cfg_composite_div(&rtc_clk_cfg, &rtc_clk, &c_cfg, &rlock);
+
+ hws[RTC_CK] = clk_hw_register_composite(NULL,
+ rtc_clk.name,
+ rtc_clk.parent_name,
+ rtc_clk.num_parents,
+ c_cfg.mux_hw, c_cfg.mux_ops,
+ c_cfg.div_hw, c_cfg.div_ops,
+ c_cfg.gate_hw, c_cfg.gate_ops,
+ rtc_clk.flags);
+
+ /* Micro-controller clocks */
+ for (n = 0; n < ARRAY_SIZE(mco_clk); n++) {
+ get_cfg_composite_div(&mco_clk_cfg, &mco_clk[n], &c_cfg,
+ &rlock);
+
+ hws[MCO_BANK + n] = clk_hw_register_composite(NULL,
+ mco_clk[n].name,
+ mco_clk[n].parent_name,
+ mco_clk[n].num_parents,
+ c_cfg.mux_hw, c_cfg.mux_ops,
+ c_cfg.div_hw, c_cfg.div_ops,
+ c_cfg.gate_hw, c_cfg.gate_ops,
+ mco_clk[n].flags);
+ }
+
+ of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
+
+ return;
+
+err_free_clks:
+ kfree(clk_data);
+}
+CLK_OF_DECLARE_DRIVER(stm32h7_rcc, "st,stm32h743-rcc", stm32h7_rcc_init);
diff --git a/include/dt-bindings/clock/stm32h7-clks.h b/include/dt-bindings/clock/stm32h7-clks.h
new file mode 100644
index 0000000..6637272
--- /dev/null
+++ b/include/dt-bindings/clock/stm32h7-clks.h
@@ -0,0 +1,165 @@
+/* SYS, CORE AND BUS CLOCKS */
+#define SYS_D1CPRE 0
+#define HCLK 1
+#define PCLK1 2
+#define PCLK2 3
+#define PCLK3 4
+#define PCLK4 5
+#define HSI_DIV 6
+#define HSE_1M 7
+#define I2S_CKIN 8
+#define CK_DSI_PHY 9
+#define HSE_CK 10
+#define LSE_CK 11
+#define CSI_KER_DIV122 12
+#define RTC_CK 13
+#define CPU_SYSTICK 14
+
+/* OSCILLATOR BANK */
+#define OSC_BANK 18
+#define HSI_CK 18
+#define HSI_KER_CK 19
+#define CSI_CK 20
+#define CSI_KER_CK 21
+#define RC48_CK 22
+#define LSI_CK 23
+
+/* MCLOCK BANK */
+#define MCLK_BANK 28
+#define PER_CK 28
+#define PLLSRC 29
+#define SYS_CK 30
+#define TRACEIN_CK 31
+
+/* ODF BANK */
+#define ODF_BANK 32
+#define PLL1_P 32
+#define PLL1_Q 33
+#define PLL1_R 34
+#define PLL2_P 35
+#define PLL2_Q 36
+#define PLL2_R 37
+#define PLL3_P 38
+#define PLL3_Q 39
+#define PLL3_R 40
+
+/* MCO BANK */
+#define MCO_BANK 41
+#define MCO1 41
+#define MCO2 42
+
+/* PERIF BANK */
+#define PERIF_BANK 50
+#define D1SRAM1_CK 50
+#define ITCM_CK 51
+#define DTCM2_CK 52
+#define DTCM1_CK 53
+#define FLITF_CK 54
+#define JPGDEC_CK 55
+#define DMA2D_CK 56
+#define MDMA_CK 57
+#define USB2ULPI_CK 58
+#define USB1ULPI_CK 59
+#define ETH1RX_CK 60
+#define ETH1TX_CK 61
+#define ETH1MAC_CK 62
+#define ART_CK 63
+#define DMA2_CK 64
+#define DMA1_CK 65
+#define D2SRAM3_CK 66
+#define D2SRAM2_CK 67
+#define D2SRAM1_CK 68
+#define HASH_CK 69
+#define CRYPT_CK 70
+#define CAMITF_CK 71
+#define BKPRAM_CK 72
+#define HSEM_CK 73
+#define BDMA_CK 74
+#define CRC_CK 75
+#define GPIOK_CK 76
+#define GPIOJ_CK 77
+#define GPIOI_CK 78
+#define GPIOH_CK 79
+#define GPIOG_CK 80
+#define GPIOF_CK 81
+#define GPIOE_CK 82
+#define GPIOD_CK 83
+#define GPIOC_CK 84
+#define GPIOB_CK 85
+#define GPIOA_CK 86
+#define WWDG1_CK 87
+#define DAC12_CK 88
+#define WWDG2_CK 89
+#define TIM14_CK 90
+#define TIM13_CK 91
+#define TIM12_CK 92
+#define TIM7_CK 93
+#define TIM6_CK 94
+#define TIM5_CK 95
+#define TIM4_CK 96
+#define TIM3_CK 97
+#define TIM2_CK 98
+#define MDIOS_CK 99
+#define OPAMP_CK 100
+#define CRS_CK 101
+#define TIM17_CK 102
+#define TIM16_CK 103
+#define TIM15_CK 104
+#define TIM8_CK 105
+#define TIM1_CK 106
+#define TMPSENS_CK 107
+#define RTCAPB_CK 108
+#define VREF_CK 109
+#define COMP12_CK 110
+#define SYSCFG_CK 111
+
+/* KERNEL BANK */
+#define KERN_BANK 120
+#define SDMMC1_CK 120
+#define QUADSPI_CK 121
+#define FMC_CK 122
+#define USB2OTG_CK 123
+#define USB1OTG_CK 124
+#define ADC12_CK 125
+#define SDMMC2_CK 126
+#define RNG_CK 127
+#define ADC3_CK 128
+#define DSI_CK 129
+#define LTDC_CK 130
+#define USART8_CK 131
+#define USART7_CK 132
+#define HDMICEC_CK 133
+#define I2C3_CK 134
+#define I2C2_CK 135
+#define I2C1_CK 136
+#define UART5_CK 137
+#define UART4_CK 138
+#define USART3_CK 139
+#define USART2_CK 140
+#define SPDIFRX_CK 141
+#define SPI3_CK 142
+#define SPI2_CK 143
+#define LPTIM1_CK 144
+#define FDCAN_CK 145
+#define SWP_CK 146
+#define HRTIM_CK 147
+#define DFSDM1_CK 148
+#define SAI3_CK 149
+#define SAI2_CK 150
+#define SAI1_CK 151
+#define SPI5_CK 152
+#define SPI4_CK 153
+#define SPI1_CK 154
+#define USART6_CK 155
+#define USART1_CK 156
+#define SAI4B_CK 157
+#define SAI4A_CK 158
+#define LPTIM5_CK 159
+#define LPTIM4_CK 160
+#define LPTIM3_CK 161
+#define LPTIM2_CK 162
+#define I2C4_CK 163
+#define SPI6_CK 164
+#define LPUART1_CK 165
+
+#define STM32H7_MAX_CLKS 166
diff --git a/include/dt-bindings/mfd/stm32h7-rcc.h b/include/dt-bindings/mfd/stm32h7-rcc.h
new file mode 100644
index 0000000..3af6a65
--- /dev/null
+++ b/include/dt-bindings/mfd/stm32h7-rcc.h
@@ -0,0 +1,137 @@
+/*
+ * This header provides constants for the STM32H7 RCC IP
+ */
+
+#ifndef _DT_BINDINGS_MFD_STM32H7_RCC_H
+#define _DT_BINDINGS_MFD_STM32H7_RCC_H
+
+/* AHB3 */
+#define STM32H7_RCC_AHB3_MDMA 0
+#define STM32H7_RCC_AHB3_DMA2D 4
+#define STM32H7_RCC_AHB3_JPGDEC 5
+#define STM32H7_RCC_AHB3_FMC 12
+#define STM32H7_RCC_AHB3_QUADSPI 14
+#define STM32H7_RCC_AHB3_SDMMC1 16
+#define STM32H7_RCC_AHB3_CPU 31
+
+#define STM32H7_AHB3_RESET(bit) (STM32H7_RCC_AHB3_##bit + (0x7C * 8))
+
+/* AHB1 */
+#define STM32H7_RCC_AHB1_DMA1 0
+#define STM32H7_RCC_AHB1_DMA2 1
+#define STM32H7_RCC_AHB1_ADC12 5
+#define STM32H7_RCC_AHB1_ART 14
+#define STM32H7_RCC_AHB1_ETH1MAC 15
+#define STM32H7_RCC_AHB1_USB1OTG 25
+#define STM32H7_RCC_AHB1_USB2OTG 27
+
+#define STM32H7_AHB1_RESET(bit) (STM32H7_RCC_AHB1_##bit + (0x80 * 8))
+
+/* AHB2 */
+#define STM32H7_RCC_AHB2_CAMITF 0
+#define STM32H7_RCC_AHB2_CRYPT 4
+#define STM32H7_RCC_AHB2_HASH 5
+#define STM32H7_RCC_AHB2_RNG 6
+#define STM32H7_RCC_AHB2_SDMMC2 9
+
+#define STM32H7_AHB2_RESET(bit) (STM32H7_RCC_AHB2_##bit + (0x84 * 8))
+
+/* AHB4 */
+#define STM32H7_RCC_AHB4_GPIOA 0
+#define STM32H7_RCC_AHB4_GPIOB 1
+#define STM32H7_RCC_AHB4_GPIOC 2
+#define STM32H7_RCC_AHB4_GPIOD 3
+#define STM32H7_RCC_AHB4_GPIOE 4
+#define STM32H7_RCC_AHB4_GPIOF 5
+#define STM32H7_RCC_AHB4_GPIOG 6
+#define STM32H7_RCC_AHB4_GPIOH 7
+#define STM32H7_RCC_AHB4_GPIOI 8
+#define STM32H7_RCC_AHB4_GPIOJ 9
+#define STM32H7_RCC_AHB4_GPIOK 10
+#define STM32H7_RCC_AHB4_CRC 19
+#define STM32H7_RCC_AHB4_BDMA 21
+#define STM32H7_RCC_AHB4_ADC3 24
+#define STM32H7_RCC_AHB4_HSEM 25
+
+#define STM32H7_AHB4_RESET(bit) (STM32H7_RCC_AHB4_##bit + (0x88 * 8))
+
+
+/* APB3 */
+#define STM32H7_RCC_APB3_LTDC 3
+#define STM32H7_RCC_APB3_DSI 4
+
+#define STM32H7_APB3_RESET(bit) (STM32H7_RCC_APB3_##bit + (0x8C * 8))
+
+/* APB1L */
+#define STM32H7_RCC_APB1L_TIM2 0
+#define STM32H7_RCC_APB1L_TIM3 1
+#define STM32H7_RCC_APB1L_TIM4 2
+#define STM32H7_RCC_APB1L_TIM5 3
+#define STM32H7_RCC_APB1L_TIM6 4
+#define STM32H7_RCC_APB1L_TIM7 5
+#define STM32H7_RCC_APB1L_TIM12 6
+#define STM32H7_RCC_APB1L_TIM13 7
+#define STM32H7_RCC_APB1L_TIM14 8
+#define STM32H7_RCC_APB1L_LPTIM1 9
+#define STM32H7_RCC_APB1L_SPI2 14
+#define STM32H7_RCC_APB1L_SPI3 15
+#define STM32H7_RCC_APB1L_SPDIF_RX 16
+#define STM32H7_RCC_APB1L_USART2 17
+#define STM32H7_RCC_APB1L_USART3 18
+#define STM32H7_RCC_APB1L_UART4 19
+#define STM32H7_RCC_APB1L_UART5 20
+#define STM32H7_RCC_APB1L_I2C1 21
+#define STM32H7_RCC_APB1L_I2C2 22
+#define STM32H7_RCC_APB1L_I2C3 23
+#define STM32H7_RCC_APB1L_HDMICEC 27
+#define STM32H7_RCC_APB1L_DAC12 29
+#define STM32H7_RCC_APB1L_USART7 30
+#define STM32H7_RCC_APB1L_USART8 31
+
+#define STM32H7_APB1L_RESET(bit) (STM32H7_RCC_APB1L_##bit + (0x90 * 8))
+
+/* APB1H */
+#define STM32H7_RCC_APB1H_CRS 1
+#define STM32H7_RCC_APB1H_SWP 2
+#define STM32H7_RCC_APB1H_OPAMP 4
+#define STM32H7_RCC_APB1H_MDIOS 5
+#define STM32H7_RCC_APB1H_FDCAN 8
+
+#define STM32H7_APB1H_RESET(bit) (STM32H7_RCC_APB1H_##bit + (0x94 * 8))
+
+/* APB2 */
+#define STM32H7_RCC_APB2_TIM1 0
+#define STM32H7_RCC_APB2_TIM8 1
+#define STM32H7_RCC_APB2_USART1 4
+#define STM32H7_RCC_APB2_USART6 5
+#define STM32H7_RCC_APB2_SPI1 12
+#define STM32H7_RCC_APB2_SPI4 13
+#define STM32H7_RCC_APB2_TIM15 16
+#define STM32H7_RCC_APB2_TIM16 17
+#define STM32H7_RCC_APB2_TIM17 18
+#define STM32H7_RCC_APB2_SPI5 20
+#define STM32H7_RCC_APB2_SAI1 22
+#define STM32H7_RCC_APB2_SAI2 23
+#define STM32H7_RCC_APB2_SAI3 24
+#define STM32H7_RCC_APB2_DFSDM1 28
+#define STM32H7_RCC_APB2_HRTIM 29
+
+#define STM32H7_APB2_RESET(bit) (STM32H7_RCC_APB2_##bit + (0x98 * 8))
+
+/* APB4 */
+#define STM32H7_RCC_APB4_SYSCFG 1
+#define STM32H7_RCC_APB4_LPUART1 3
+#define STM32H7_RCC_APB4_SPI6 5
+#define STM32H7_RCC_APB4_I2C4 7
+#define STM32H7_RCC_APB4_LPTIM2 9
+#define STM32H7_RCC_APB4_LPTIM3 10
+#define STM32H7_RCC_APB4_LPTIM4 11
+#define STM32H7_RCC_APB4_LPTIM5 12
+#define STM32H7_RCC_APB4_COMP12 14
+#define STM32H7_RCC_APB4_VREF 15
+#define STM32H7_RCC_APB4_SAI4 21
+#define STM32H7_RCC_APB4_TMPSENS 26
+
+#define STM32H7_APB4_RESET(bit) (STM32H7_RCC_APB4_##bit + (0x9C * 8))
+
+#endif /* _DT_BINDINGS_MFD_STM32H7_RCC_H */
--
1.9.1
^ permalink raw reply related
* Re: [PATCH v5 6/9] coresight: add support for CPU debug module
From: Suzuki K Poulose @ 2017-03-29 9:07 UTC (permalink / raw)
To: Leo Yan
Cc: Jonathan Corbet, Rob Herring, Mark Rutland, Wei Xu,
Catalin Marinas, Will Deacon, Andy Gross, David Brown,
Michael Turquette, Stephen Boyd, Mathieu Poirier, Guodong Xu,
John Stultz, linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
linux-soc-u79uwXL29TY76Z2rM5mHXA,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
mike.leach-QSEj5FYQhm4dnm+yROfE0A, sudeep.holla-5wv7dgnIgG8
In-Reply-To: <20170329030735.GA23889@leoy-linaro>
On 29/03/17 04:07, Leo Yan wrote:
> Hi Suzuki,
>
> On Mon, Mar 27, 2017 at 05:34:57PM +0100, Suzuki K Poulose wrote:
>> On 25/03/17 18:23, Leo Yan wrote:
>
> [...]
>
>> Leo,
>>
>> Thanks a lot for the quick rework. I don't fully understand (yet!) why we need the
>> idle_constraint. I will leave it for Sudeep to comment on it, as he is the expert
>> in that area. Some minor comments below.
>
> Thanks a lot for quick reviewing :)
>
>>> Signed-off-by: Leo Yan <leo.yan-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>> ---
>>> drivers/hwtracing/coresight/Kconfig | 11 +
>>> drivers/hwtracing/coresight/Makefile | 1 +
>>> drivers/hwtracing/coresight/coresight-cpu-debug.c | 704 ++++++++++++++++++++++
>>> 3 files changed, 716 insertions(+)
>>> create mode 100644 drivers/hwtracing/coresight/coresight-cpu-debug.c
>>>
>>> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
>>> index 130cb21..18d7931 100644
>>> --- a/drivers/hwtracing/coresight/Kconfig
>>> +++ b/drivers/hwtracing/coresight/Kconfig
>>> @@ -89,4 +89,15 @@ config CORESIGHT_STM
>>> logging useful software events or data coming from various entities
>>> in the system, possibly running different OSs
>>>
>>> +config CORESIGHT_CPU_DEBUG
>>> + tristate "CoreSight CPU Debug driver"
>>> + depends on ARM || ARM64
>>> + depends on DEBUG_FS
>>> + help
>>> + This driver provides support for coresight debugging module. This
>>> + is primarily used to dump sample-based profiling registers when
>>> + system triggers panic, the driver will parse context registers so
>>> + can quickly get to know program counter (PC), secure state,
>>> + exception level, etc.
>>
>> May be we should mention/warn the user about the possible caveats of using
>> this feature to help him make a better decision ? And / Or we should add a documentation
>> for it. We have collected some real good information over the discussions and
>> it is a good idea to capture it somewhere.
>
> Sure, I will add a documentation for this.
>
> [...]
>
>>> +static struct pm_qos_request debug_qos_req;
>>> +static int idle_constraint = PM_QOS_DEFAULT_VALUE;
>>> +module_param(idle_constraint, int, 0600);
>>> +MODULE_PARM_DESC(idle_constraint, "Latency requirement in microseconds for CPU "
>>> + "idle states (default is -1, which means have no limiation "
>>> + "to CPU idle states; 0 means disabling all idle states; user "
>>> + "can choose other platform dependent values so can disable "
>>> + "specific idle states for the platform)");
>>
>> Correct me if I am wrong,
>>
>> All we want to do is disable the CPUIdle explicitly if the user knows that this
>> could be a problem to use CPU debug on his platform. So, in effect, we should
>> only be using idle_constraint = 0 or -1.
>>
>> In which case, we could make it easier for the user to tell us, either
>>
>> 0 - Don't do anything with CPUIdle (default)
>> 1 - Disable CPUIdle for me as I know the platform has issues with CPU debug and CPUidle.
>
> The reason for not using bool flag is: usually SoC may have many idle
> states, so if user wants to partially enable some states then can set
> the latency to constraint.
>
> But of course, we can change this to binary value as you suggested,
> this means turn on of turn off all states. The only one reason to use
> latency value is it is more friendly for hardware design, e.g. some
> platforms can enable partial states to save power and avoid overheat
> after using this driver.
>
> If you guys think this is a bit over design, I will follow up your
> suggestion. I also have some replying in Mathieu's reviewing, please
> help review as well.
>
>> than explaining the miscrosecond latency etc and make the appropriate calls underneath.
>> something like (not necessarily the same name) :
>>
>> module_param(broken_with_cpuidle, bool, 0600);
>> MODULE_PARAM_DESC(broken_with_cpuidle, "Specifies whether the CPU debug has issues with CPUIdle on"
>> " the platform. Non-zero value implies CPUIdle has to be"
>> " explicitly disabled.",);
>
> [...]
>
>>> + /*
>>> + * Unfortunately the CPU cannot be powered up, so return
>>> + * back and later has no permission to access other
>>> + * registers. For this case, should set 'idle_constraint'
>>> + * to ensure CPU power domain is enabled!
>>> + */
>>> + if (!(drvdata->edprsr & EDPRSR_PU)) {
>>> + pr_err("%s: power up request for CPU%d failed\n",
>>> + __func__, drvdata->cpu);
>>> + goto out;
>>> + }
>>> +
>>> +out_powered_up:
>>> + debug_os_unlock(drvdata);
>>
>> Question: Do we need a matching debug_os_lock() once we are done ?
>
> I have checked ARM ARMv8, but there have no detailed description for
> this. I refered coresight-etmv4 code and Mike's pseudo code, ther have
> no debug_os_lock() related operations.
>
> Mike, Mathieu, could you also help confirm this?
>
> [...]
>
>>> +static void debug_init_arch_data(void *info)
>>> +{
>>> + struct debug_drvdata *drvdata = info;
>>> + u32 mode, pcsr_offset;
>>> +
>>> + CS_UNLOCK(drvdata->base);
>>> +
>>> + debug_os_unlock(drvdata);
>>> +
>>> + /* Read device info */
>>> + drvdata->eddevid = readl_relaxed(drvdata->base + EDDEVID);
>>> + drvdata->eddevid1 = readl_relaxed(drvdata->base + EDDEVID1);
>>
>> As mentioned above, both of these registers are only need at init time to
>> figure out the flags we set here. So we could remove them.
>>
>>> +
>>> + CS_LOCK(drvdata->base);
>>> +
>>> + /* Parse implementation feature */
>>> + mode = drvdata->eddevid & EDDEVID_PCSAMPLE_MODE;
>>> + pcsr_offset = drvdata->eddevid1 & EDDEVID1_PCSR_OFFSET_MASK;
>>
>>
>>> +
>>> + if (mode == EDDEVID_IMPL_NONE) {
>>> + drvdata->edpcsr_present = false;
>>> + drvdata->edcidsr_present = false;
>>> + drvdata->edvidsr_present = false;
>>> + } else if (mode == EDDEVID_IMPL_EDPCSR) {
>>> + drvdata->edpcsr_present = true;
>>> + drvdata->edcidsr_present = false;
>>> + drvdata->edvidsr_present = false;
>>> + } else if (mode == EDDEVID_IMPL_EDPCSR_EDCIDSR) {
>>> + if (!IS_ENABLED(CONFIG_64BIT) &&
>>> + (pcsr_offset == EDDEVID1_PCSR_NO_OFFSET_DIS_AARCH32))
>>> + drvdata->edpcsr_present = false;
>>> + else
>>> + drvdata->edpcsr_present = true;
>>
>> Sorry, I forgot why we do this check only in this mode. Shouldn't this be
>> common to all modes (of course which implies PCSR is present) ?
>
> No. PCSROffset is defined differently in ARMv7 and ARMv8; So finally we
> simplize PCSROffset value :
> 0000 - Sample offset applies based on the instruction state (indicated by PCSR[0])
> 0001 - No offset applies.
> 0010 - No offset applies, but do not use in AArch32 mode!
>
> So we need handle the corner case is when CPU runs AArch32 mode and
> PCSRoffset = 'b0010. Other cases the pcsr should be present.
I understand that reasoning. But my question is, why do we check for PCSROffset
only when mode == EDDEVID_IMPL_EDPCSR_EDCIDSR and not for say mode == EDDEVID_IMPL_EDPCSR or
any other mode where PCSR is present.
Suzuki
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] iio/adc/ltc2497: Driver for Linear Technology LTC2497 ADC
From: Michael Hennerich @ 2017-03-29 8:51 UTC (permalink / raw)
To: Lars-Peter Clausen, jic23-DgEjT+Ai2ygdnm+yROfE0A,
knaack.h-Mmb7MZpHnFY, pmeerw-jW+XmwGofnusTnJN9+BGXg,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8
Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <6774c073-7fe4-e259-306e-3cf4621f7c69-Qo5EllUWu/uELgA04lAiVw@public.gmane.org>
On 23.03.2017 12:05, Lars-Peter Clausen wrote:
Sorry - I missed some of this review feedback ...
>> +
>> +static int ltc2497_wait_conv(struct ltc2497_st *st)
>> +{
>> + s64 time_elapsed;
>> +
>> + time_elapsed = ktime_ms_delta(ktime_get(), st->time_prev);
>> +
>> + if (time_elapsed < LTC2497_CONVERSION_TIME_MS) {
>> + /* delay if conversion time not passed
>> + * since last read or write
>> + */
>> + msleep(LTC2497_CONVERSION_TIME_MS - time_elapsed);
>
> Considering how long this sleeps msleep_interruptible() might be the better
> choice.
Wondering what should be the outcome of this?
We can't simply replace it. Actually I've seen cases here in drivers/iio
where the delay is essential, but the return value of
msleep_interruptible() is not being checked.
Thus causing a malicious access, in case a signal is received.
We must delay here. If we switch to msleep_interruptible() the only
reason for this would be to cancel the read and return -EINTR to the user.
Also there is another msleep below which would also need this kind of
handling.
>
>> + return 0;
>> + }
>> +
>> + if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) {
>> + /* We're in automatic mode -
>> + * so the last reading is stil not outdated
>> + */
>> + return 0;
>> + }
>> +
>> + return -ETIMEDOUT;
>> +}
>> +
>> +static int ltc2497_read(struct ltc2497_st *st, u8 address, int *val)
>> +{
>> + struct i2c_client *client = st->client;
>> + __be32 buf = 0;
>
> transfer buffers must not be on the stack to avoid issues if the controller
> should use DMA.
>
>> + int ret;
>> +
>> + ret = ltc2497_wait_conv(st);
>> + if (ret < 0 || st->addr_prev != address) {
>> + ret = i2c_smbus_write_byte(st->client, 0xA0 | address);
>> + if (ret < 0)
>> + return ret;
>> + st->addr_prev = address;
>> + msleep(LTC2497_CONVERSION_TIME_MS);
>> + }
>> + ret = i2c_master_recv(client, (char *)&buf, 3);
>> + if (ret < 0) {
>> + dev_err(&client->dev, "i2c_master_recv failed\n");
>> + return ret;
>> + }
>> + st->time_prev = ktime_get();
>> + *val = (be32_to_cpu(buf) >> 14) - (1 << 17);
>> +
>> + return ret;
>> +}
> [...]
>
--
Greetings,
Michael
--
Analog Devices GmbH Otl-Aicher Strasse 60-64 80807 München
Sitz der Gesellschaft München, Registergericht München HRB 40368,
Geschäftsführer: Peter Kolberg, Ali Raza Husain, Eileen Wynne
^ permalink raw reply
* Re: [PATCH/RFC v2 1/2] arm64: dts: r8a7795: Add support for R-Car H3 ES2.0
From: Simon Horman @ 2017-03-29 8:45 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Laurent Pinchart, Geert Uytterhoeven, Magnus Damm,
Yoshihiro Shimoda, Kuninori Morimoto, Wolfram Sang, Rob Herring,
Mark Rutland, Linux-Renesas, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <CAMuHMdWvR71V_JyR6273KmdtGfrrT_vaU2vcDTpNt2MAG0WdLg@mail.gmail.com>
On Wed, Mar 29, 2017 at 10:31:02AM +0200, Geert Uytterhoeven wrote:
> Hi Simon,
>
> On Wed, Mar 29, 2017 at 10:13 AM, Simon Horman <horms@verge.net.au> wrote:
> > On Mon, Mar 27, 2017 at 11:48:12AM +0300, Laurent Pinchart wrote:
> >> On Friday 24 Mar 2017 14:37:44 Geert Uytterhoeven wrote:
> >> > Update r8a7795.dtsi so it corresponds to R-Car H3 ES2.0 or later:
> >> > - The following devices no longer exist on ES2.0, and are thus removed:
> >> > fcpf2, fcpvd3, fcpvi2, fdp1-2, usb3-if1, vspd3, vspi2.
> >> > - The DU <-> VSPD topology is different on ES2.0, hence remove the
> >> > "vsps" property from the DU node until the driver can handle this.
> >>
> >> I think I'll need a different compatible string between ES1.x and ES2 for the
> >> DU. It could make sense to move the whole DU node to *-es1.dtsi. We can decide
> >> about that later when I'll have a DU driver prototype ready.
> >
> > That makes sense to me.
> >
> > Geert, will you respin this?
>
> Sure. The DTS parts are definitely not v4.12 material.
> - For ES2.0, they depend on clk/pfc/rcar-sysc updates.
> - For ES1.x, I don't want to break people's setup (scripts copying
> r8a7795-salvator-x.dtb) prematurely.
Ok.
^ permalink raw reply
* [REPOST PATCH] ARM: dts: imx6qp-nitrogen6_som2: add Quad Plus variant of the SOM
From: Gary Bisson @ 2017-03-29 8:45 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, fabio.estevam-3arQi8VN3Tc,
shawnguo-DgEjT+Ai2ygdnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
Gary Bisson
In-Reply-To: <20170327160601.12871-1-gary.bisson-Q5RJGjKts06CY9SHAMCTRUEOCMrvLtNR@public.gmane.org>
https://boundarydevices.com/product/nit6x-som-v2/
Reviewed-by: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>
Signed-off-by: Gary Bisson <gary.bisson-Q5RJGjKts06CY9SHAMCTRUEOCMrvLtNR@public.gmane.org>
---
Hi,
This is just a re-post to LAKML as suggested by Shawn [1].
Also include the Review tag from Fabio [2].
Regards,
Gary
[1] http://www.spinics.net/lists/devicetree/msg170732.html
[2] http://www.spinics.net/lists/devicetree/msg170354.html
---
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/imx6qp-nitrogen6_som2.dts | 55 +++++++++++++++++++++++++++++
2 files changed, 56 insertions(+)
create mode 100644 arch/arm/boot/dts/imx6qp-nitrogen6_som2.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 011808490fed..6190afe94371 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -426,6 +426,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6q-wandboard.dtb \
imx6q-wandboard-revb1.dtb \
imx6qp-nitrogen6_max.dtb \
+ imx6qp-nitrogen6_som2.dtb \
imx6qp-sabreauto.dtb \
imx6qp-sabresd.dtb
dtb-$(CONFIG_SOC_IMX6SL) += \
diff --git a/arch/arm/boot/dts/imx6qp-nitrogen6_som2.dts b/arch/arm/boot/dts/imx6qp-nitrogen6_som2.dts
new file mode 100644
index 000000000000..011726c836cd
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qp-nitrogen6_som2.dts
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017 Boundary Devices, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file 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 file 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.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "imx6qp.dtsi"
+#include "imx6qdl-nitrogen6_som2.dtsi"
+
+/ {
+ model = "Boundary Devices i.MX6 Quad Plus Nitrogen6_SOM2 Board";
+ compatible = "boundary,imx6qp-nitrogen6_som2", "fsl,imx6qp";
+};
+
+&sata {
+ status = "okay";
+};
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH v6 02/39] [media] dt-bindings: Add bindings for i.MX media driver
From: Russell King - ARM Linux @ 2017-03-29 8:39 UTC (permalink / raw)
To: Rob Herring
Cc: Steve Longerbeam, Mark Rutland, Shawn Guo,
kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org, Fabio Estevam,
Mauro Carvalho Chehab, Hans Verkuil, Nick Dyer,
markus.heiser-m1Uo1GnMJf0b1SvskN2V4Q, Philipp Zabel,
Laurent Pinchart, Benoit Parrot, Geert Uytterhoeven,
Arnd Bergmann, Sudip Mukherjee, Minghsiu Tsai, tiffany lin,
Jean-Christophe Trotin, Simon Horman <horms+renesas@
In-Reply-To: <CAL_JsqJm_JjuVPcOBERCqsnjTDdNoKr9xRE9MXMO4ivxGath2Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Tue, Mar 28, 2017 at 07:21:34PM -0500, Rob Herring wrote:
> On Mon, Mar 27, 2017 at 7:40 PM, Steve Longerbeam <slongerbeam-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> > Add bindings documentation for the i.MX media driver.
> >
> > Signed-off-by: Steve Longerbeam <steve_longerbeam-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
> > ---
> > Documentation/devicetree/bindings/media/imx.txt | 74 +++++++++++++++++++++++++
> > 1 file changed, 74 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/media/imx.txt
> >
> > diff --git a/Documentation/devicetree/bindings/media/imx.txt b/Documentation/devicetree/bindings/media/imx.txt
> > new file mode 100644
> > index 0000000..3059c06
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/media/imx.txt
> > @@ -0,0 +1,74 @@
> > +Freescale i.MX Media Video Device
> > +=================================
> > +
> > +Video Media Controller node
> > +---------------------------
> > +
> > +This is the media controller node for video capture support. It is a
> > +virtual device that lists the camera serial interface nodes that the
> > +media device will control.
> > +
> > +Required properties:
> > +- compatible : "fsl,imx-capture-subsystem";
> > +- ports : Should contain a list of phandles pointing to camera
> > + sensor interface ports of IPU devices
> > +
> > +example:
> > +
> > +capture-subsystem {
> > + compatible = "fsl,imx-capture-subsystem";
> > + ports = <&ipu1_csi0>, <&ipu1_csi1>;
> > +};
> > +
> > +fim child node
> > +--------------
> > +
> > +This is an optional child node of the ipu_csi port nodes. If present and
> > +available, it enables the Frame Interval Monitor. Its properties can be
> > +used to modify the method in which the FIM measures frame intervals.
> > +Refer to Documentation/media/v4l-drivers/imx.rst for more info on the
> > +Frame Interval Monitor.
> > +
> > +Optional properties:
> > +- fsl,input-capture-channel: an input capture channel and channel flags,
> > + specified as <chan flags>. The channel number
> > + must be 0 or 1. The flags can be
> > + IRQ_TYPE_EDGE_RISING, IRQ_TYPE_EDGE_FALLING, or
> > + IRQ_TYPE_EDGE_BOTH, and specify which input
> > + capture signal edge will trigger the input
> > + capture event. If an input capture channel is
> > + specified, the FIM will use this method to
> > + measure frame intervals instead of via the EOF
> > + interrupt. The input capture method is much
> > + preferred over EOF as it is not subject to
> > + interrupt latency errors. However it requires
> > + routing the VSYNC or FIELD output signals of
> > + the camera sensor to one of the i.MX input
> > + capture pads (SD1_DAT0, SD1_DAT1), which also
> > + gives up support for SD1.
> > +
> > +
> > +mipi_csi2 node
> > +--------------
> > +
> > +This is the device node for the MIPI CSI-2 Receiver, required for MIPI
> > +CSI-2 sensors.
> > +
> > +Required properties:
> > +- compatible : "fsl,imx6-mipi-csi2", "snps,dw-mipi-csi2";
>
> As I mentioned in v5, there's a DW CSI2 binding in progress. This
> needs to be based on that.
Maybe someone can provide some kind of reference to it, and it's
associated driver?
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH/RFC v2 1/2] arm64: dts: r8a7795: Add support for R-Car H3 ES2.0
From: Geert Uytterhoeven @ 2017-03-29 8:31 UTC (permalink / raw)
To: Simon Horman
Cc: Laurent Pinchart, Geert Uytterhoeven, Magnus Damm,
Yoshihiro Shimoda, Kuninori Morimoto, Wolfram Sang, Rob Herring,
Mark Rutland, Linux-Renesas, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <20170329081352.GF6512@verge.net.au>
Hi Simon,
On Wed, Mar 29, 2017 at 10:13 AM, Simon Horman <horms@verge.net.au> wrote:
> On Mon, Mar 27, 2017 at 11:48:12AM +0300, Laurent Pinchart wrote:
>> On Friday 24 Mar 2017 14:37:44 Geert Uytterhoeven wrote:
>> > Update r8a7795.dtsi so it corresponds to R-Car H3 ES2.0 or later:
>> > - The following devices no longer exist on ES2.0, and are thus removed:
>> > fcpf2, fcpvd3, fcpvi2, fdp1-2, usb3-if1, vspd3, vspi2.
>> > - The DU <-> VSPD topology is different on ES2.0, hence remove the
>> > "vsps" property from the DU node until the driver can handle this.
>>
>> I think I'll need a different compatible string between ES1.x and ES2 for the
>> DU. It could make sense to move the whole DU node to *-es1.dtsi. We can decide
>> about that later when I'll have a DU driver prototype ready.
>
> That makes sense to me.
>
> Geert, will you respin this?
Sure. The DTS parts are definitely not v4.12 material.
- For ES2.0, they depend on clk/pfc/rcar-sysc updates.
- For ES1.x, I don't want to break people's setup (scripts copying
r8a7795-salvator-x.dtb) prematurely.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH V6 4/7] mfd: da9061: MFD core support
From: Lee Jones @ 2017-03-29 8:30 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Steve Twiss, kbuild test robot,
kbuild-all-JC7UmRfGjtg@public.gmane.org, LINUX-KERNEL, DEVICETREE,
Dmitry Torokhov, Eduardo Valentin, Guenter Roeck, LINUX-INPUT,
LINUX-PM, LINUX-WATCHDOG, Liam Girdwood, Mark Brown, Mark Rutland,
Rob Herring, Support Opensource, Wim Van Sebroeck, Zhang Rui
In-Reply-To: <CAMuHMdU-kaAZ-Reji2v3jSypoDSiwYEWqD0vyYWwJpr6+rAPOA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Tue, 28 Mar 2017, Geert Uytterhoeven wrote:
> Hi Steve,
>
> On Tue, Mar 28, 2017 at 12:42 PM, Steve Twiss
> <stwiss.opensource-WBD+wuPFNBhBDgjK7y7TUQ@public.gmane.org> wrote:
> > On 28 March 2017 09:37, Geert Uytterhoeven wrote:
> >> Subject: Re: [PATCH V6 4/7] mfd: da9061: MFD core support
> >> On Tue, Mar 28, 2017 at 10:21 AM, Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> >> >> [auto build test WARNING on ljones-mfd/for-mfd-next]
> >> >> [also build test WARNING on v4.11-rc4 next-20170327]
> >> >> base: https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
> >> >> config: x86_64-randconfig-x009-201713 (attached as .config)
> >> >> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
> >> >> reproduce:
> >> >> # save the attached .config to linux build tree
> >> >> make ARCH=x86_64
> >> >>
> >> >> All warnings (new ones prefixed by >>):
> >> >>
> >> >> drivers//mfd/da9062-core.c: In function 'da9062_i2c_probe':
> >> >> >> drivers//mfd/da9062-core.c:845:21: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
> >> >> chip->chip_type = (int)match->data;
> >> >> ^
> >> >
> >> > Please use longs or enums.
> >>
> >> Enums would still give a warning on 64-bit.
> >> The simple fix is change the cast from (int) to (uintptr_t).
> >
> > Hi Lee and Geert,
> >
> > How about this? Fix by redefining the enum chip_type to be an int.
> > Then, just use substitution:
> > #define COMPAT_TYPE_DA9061 1
> > #define COMPAT_TYPE_DA9062 2
> >
> > That would be simple.
> > Are there any reasons this would not be acceptable?
>
> I don't see how that can help.
> The warning is caused by casting the "void *" (which is either 32-bit or
> 64-bit) in of_device_if.data to an integer or enum (which is always 32-bit).
>
> The right fix is to cast it to uintptr_t intead of int, like other drivers do.
That's a hack though, isn't it? chip->chip_type is not of type
uintptr_t, so all you're doing here is making the compiler happy.
I see people using (int)(uintptr_t), which I guess keeps the
compiler happy in the first instance and actually culminates in a
correct cast to the right type.
So how about something like (enum da9062_compatible_types)(long)?
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2 6/8] regulator: arizona-micbias: Add regulator driver for Arizona micbiases
From: Charles Keepax @ 2017-03-29 8:30 UTC (permalink / raw)
To: broonie, lee.jones
Cc: mark.rutland, devicetree, alsa-devel, patches, lgirdwood,
linux-kernel, robh+dt
In-Reply-To: <201703291403.z4sFz6z9%fengguang.wu@intel.com>
On Wed, Mar 29, 2017 at 02:18:23PM +0800, kbuild test robot wrote:
> Hi Charles,
>
> [auto build test WARNING on regulator/for-next]
> [also build test WARNING on v4.11-rc4 next-20170328]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>
> url: https://github.com/0day-ci/linux/commits/Charles-Keepax/regulator-arizona-micsupp-Avoid-potential-memory-leak-reading-init_data/20170329-112224
> base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next
> config: i386-randconfig-x0-03291136 (attached as .config)
> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
> reproduce:
> # save the attached .config to linux build tree
> make ARCH=i386
>
Hmm... this is due to the tree missing the patch that Lee already
applied from version 1. I guess perhaps we should pull that back
into this series or he could make an immutable branch you can pull
in?
Thanks,
Charles
^ permalink raw reply
* Re: [PATCH v8 3/3] ARM: dts: imx6q-icore: Add touchscreen node
From: Shawn Guo @ 2017-03-29 8:22 UTC (permalink / raw)
To: Jagan Teki
Cc: linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Jagan Teki, Dmitry Torokhov,
Domenico Acri, Matteo Lisi, Michael Trimarchi
In-Reply-To: <1490209518-20790-3-git-send-email-jagan-oRp2ZoJdM/RWk0Htik3J/w@public.gmane.org>
On Thu, Mar 23, 2017 at 12:35:18AM +0530, Jagan Teki wrote:
> From: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
>
> max11801 touchscreen on Engicam iCoreM6 Quad module is
> connected via i2c1, so add max11801: touchscreen@48 on i2c1.
>
> Cc: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Cc: Domenico Acri <domenico.acri-4s7YQHO/iPVBDgjK7y7TUQ@public.gmane.org>
> Cc: Matteo Lisi <matteo.lisi-4s7YQHO/iPVBDgjK7y7TUQ@public.gmane.org>
> Cc: Michael Trimarchi <michael-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
> Cc: Shawn Guo <shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Signed-off-by: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
Applied, thanks.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH/RFC v2 1/2] arm64: dts: r8a7795: Add support for R-Car H3 ES2.0
From: Simon Horman @ 2017-03-29 8:13 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Geert Uytterhoeven, Magnus Damm, Yoshihiro Shimoda,
Kuninori Morimoto, Wolfram Sang, Rob Herring, Mark Rutland,
linux-renesas-soc, devicetree, linux-arm-kernel
In-Reply-To: <1612430.SNEha5n02K@avalon>
On Mon, Mar 27, 2017 at 11:48:12AM +0300, Laurent Pinchart wrote:
> Hi Geert,
>
> Thank you for the patch.
>
> On Friday 24 Mar 2017 14:37:44 Geert Uytterhoeven wrote:
> > Update r8a7795.dtsi so it corresponds to R-Car H3 ES2.0 or later:
> > - The following devices no longer exist on ES2.0, and are thus removed:
> > fcpf2, fcpvd3, fcpvi2, fdp1-2, usb3-if1, vspd3, vspi2.
> > - The DU <-> VSPD topology is different on ES2.0, hence remove the
> > "vsps" property from the DU node until the driver can handle this.
>
> I think I'll need a different compatible string between ES1.x and ES2 for the
> DU. It could make sense to move the whole DU node to *-es1.dtsi. We can decide
> about that later when I'll have a DU driver prototype ready.
That makes sense to me.
Geert, will you respin this?
^ permalink raw reply
* Re: [PATCH] ARM: dts: r7s72100: add power-domains to sdhi
From: Simon Horman @ 2017-03-29 8:09 UTC (permalink / raw)
To: Chris Brandt
Cc: Geert Uytterhoeven, Magnus Damm, Rob Herring, Mark Rutland,
devicetree@vger.kernel.org, Linux-Renesas
In-Reply-To: <SG2PR06MB116573C9325106B5ED4580578A3E0@SG2PR06MB1165.apcprd06.prod.outlook.com>
On Fri, Mar 24, 2017 at 11:17:25AM +0000, Chris Brandt wrote:
> On Friday, March 24, 2017, Geert Uytterhoeven wrote:
> > > The fixes tag above indicates this is a fix for v4.10, however, when I
> > > tried to apply it on top of v4.11-rc1 there was a conflict. So I
> > > think a backport will be required if we want it to be considered for
> > > v4.11 and be considered for and in turn v4.10-stable.
> >
> > That's because of commit 3d2abda02ad2d06d
> > ("ARM: dts: r7s72100: update sdhi clock bindings")
>
>
> Between the two, "update sdhi clock bindings" is more important this this patch ("add power-domains").
> Without "update sdhi clock bindings", the SDHI /might/ not work.
>
>
> But, "update sdhi clock bindings", also relies on the driver update 34a1654706c6 ("mmc: sh_mobile_sdhi: add support for 2 clocks").
> That one is in v4.11-rc1, but not in 4.10.5.
>
> I just noticed now that 34a1654706c6 does not have "Fixes" in the commit log, so it is probably not marked to go into v4.10-stable, so in that case backporting the dtsi is pointless.
We could try to coordinate getting 34a1654706c6 and the dtsi changes into
v4.10-stable if you it is sufficiently important. What are your thoughts on
that?
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: Document the STM32 MDMA bindings
From: M'boumba Cedric Madianga @ 2017-03-29 8:07 UTC (permalink / raw)
To: Rob Herring
Cc: Mark Rutland, devicetree@vger.kernel.org, Alexandre Torgue,
Vinod Koul, linux-kernel@vger.kernel.org, Maxime Coquelin,
dmaengine, Dan Williams, linux-arm-kernel@lists.infradead.org
In-Reply-To: <CAL_JsqLMn7W=r+JRX51zOScs9N04PcTtX8EFy2eacwadCxwaRg@mail.gmail.com>
Hi Rob,
> stm32 is not a specific SoC. Compatible strings should be specific to
> an SoC (with fallback strings to whatever they are compatible with) so
> you can handle SoC specific differences or errata.
Ok I see. I will add a more specific SoC description in my compatible.
Thanks.
> I still don't understand. Is the difference in DMA addresses vs. CPU
> addresses? If so, you should dma-ranges to translate these.
Not really.
In fact, the MDMA controller provides a master AXI interface for
memories like DDR/SRAM and peripheral registers access (system access
port).
It also provides a master AHB interface only for Cortex-M7 TCM memory
access (TCM access port).
So the goal of this st,ahb-addr-masks property is to list all TCM
addresses avalaible in the SoC, in order to correctly configure the
MDMA as an AHB master in that particular case.
For all other cases (other memories or peripheral registers access),
the MDMA will act as AXI master.
Hope it helps to understand.
BR,
Cedric
^ permalink raw reply
* Re: [PATCH v3 3/9] arm: fix return value of parse_cpu_capacity
From: Juri Lelli @ 2017-03-29 8:06 UTC (permalink / raw)
To: Vincent Guittot
Cc: linux-kernel, linux-pm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
LAK, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Peter Zijlstra, Rob Herring, Mark Rutland,
Russell King - ARM Linux, Sudeep Holla, Lorenzo Pieralisi,
Catalin Marinas, Will Deacon, Morten Rasmussen, Dietmar Eggemann,
Mark Brown,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org
In-Reply-To: <CAKfTPtCswVBMCaEUzBF4w_GZf-2iLORsS5S0HhGD94ps4+J1Xg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On 29/03/17 09:37, Vincent Guittot wrote:
> On 27 March 2017 at 15:18, Juri Lelli <juri.lelli-5wv7dgnIgG8@public.gmane.org> wrote:
> > parse_cpu_capacity() has to return 0 on failure, but it currently returns
> > 1 instead if raw_capacity kcalloc failed.
> >
> > Fix it by removing the negation of the return value.
> >
> > Cc: Russell King <linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>
> > Reported-by: Morten Rasmussen <morten.rasmussen-5wv7dgnIgG8@public.gmane.org>
> > Fixes: 06073ee26775 ('ARM: 8621/3: parse cpu capacity-dmips-mhz from DT')
> > Signed-off-by: Juri Lelli <juri.lelli-5wv7dgnIgG8@public.gmane.org>
> > ---
> > arch/arm/kernel/topology.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
> > index f8a3ab82e77f..4e4af809606a 100644
> > --- a/arch/arm/kernel/topology.c
> > +++ b/arch/arm/kernel/topology.c
> > @@ -166,7 +166,7 @@ static int __init parse_cpu_capacity(struct device_node *cpu_node, int cpu)
> > if (!raw_capacity) {
> > pr_err("cpu_capacity: failed to allocate memory for raw capacities\n");
> > cap_parsing_failed = true;
> > - return !ret;
> > + return ret;
>
> Why not directly returning 0 ? whatever the value of ret, the parse of
> cpu capacity has failed in this case
>
Sure, can change that.
Thanks,
- Juri
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCHv4] mfd: cpcap: implement irq sense helper
From: Lee Jones @ 2017-03-29 8:04 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Tony Lindgren, Dmitry Torokhov, Rob Herring, Mark Rutland,
linux-input, devicetree, linux-kernel
In-Reply-To: <20170328145415.td4xeqxedem5yjen@earth>
On Tue, 28 Mar 2017, Sebastian Reichel wrote:
> Hi Lee,
>
> On Tue, Mar 28, 2017 at 11:27:16AM +0100, Lee Jones wrote:
> > > +int cpcap_sense_virq(struct regmap *regmap, int virq)
> > > +{
> > > + struct regmap_irq_chip_data *d = irq_get_chip_data(virq);
> > > + int base = regmap_irq_chip_get_base(d);
> >
> > What base is this?
>
> This function takes an Linux irq number. That number is a virtual
> irq number, which has nothing to do with the hardware. For example
> a platform could look like this:
>
> linux irq device base device irq
> ---------------------------------------------
> 0-63 SoC 0 0-63
> 64-127 SoC-GPIO 64 0-63
> 128-191 CPCAP 128 0-63
>
> For the above example the function would map 128-191 to 0-63 as
> used by the device.
In which case may I suggest that you rename the variable, since 'base'
is commonly used in the kernel to mean base of a particular IP's
memory block.
> > Could it be used to avoid some calculations in cpcap_sense_irq()?
>
> No.
>
> > > + return cpcap_sense_irq(regmap, virq - base);
> > > +}
> > > +EXPORT_SYMBOL_GPL(cpcap_sense_virq);
>
> -- Sebastian
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* Re: [PATCH 1/2] ARM: dts: r8a7792: add IMR-L[S]X3 clocks
From: Simon Horman @ 2017-03-29 8:04 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: Mark Rutland, devicetree, Magnus Damm, Russell King,
linux-renesas-soc, Rob Herring, linux-arm-kernel
In-Reply-To: <a802018c-9943-22e5-0f78-28b8ab9689d9@cogentembedded.com>
On Tue, Mar 21, 2017 at 11:14:43PM +0300, Sergei Shtylyov wrote:
> On 03/21/2017 11:08 PM, Sergei Shtylyov wrote:
>
> >Still not cover letter but I think it's better now, so I won't retry...
> >The patches are against Simon Horman's 'renesas.git' repo,
> >'renesas-devel-20170321-v4.11-rc3' tag.
>
> The patches depend on the IMR driver patches adding the IMR-L[S]X3
> support for the "compatible" values.
I have marked these patches as deferred accordingly.
^ permalink raw reply
* Re: [PATCH v3 05/11] Documentation: DT: bindings: input: touschcreen: remove sun4i documentation
From: Lee Jones @ 2017-03-29 7:58 UTC (permalink / raw)
To: Quentin Schulz
Cc: dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8, wens-jdAy2FN1RRM,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, jic23-DgEjT+Ai2ygdnm+yROfE0A,
knaack.h-Mmb7MZpHnFY, lars-Qo5EllUWu/uELgA04lAiVw,
pmeerw-jW+XmwGofnusTnJN9+BGXg,
thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
linux-input-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-iio-u79uwXL29TY76Z2rM5mHXA,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, icenowy-ymACFijhrKM
In-Reply-To: <20170321153611.16228-6-quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
On Tue, 21 Mar 2017, Quentin Schulz wrote:
> This patch removes the sun4i touchscreen controller binding
> documentation since it has been merged with the sun4i GPADC binding
> documentation.
>
> Signed-off-by: Quentin Schulz <quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>
> added in v2
>
> .../bindings/input/touchscreen/sun4i.txt | 38 ----------------------
Just an Input Ack missing here.
> 1 file changed, 38 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/sun4i.txt
>
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt b/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt
> deleted file mode 100644
> index 89abecd..0000000
> --- a/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt
> +++ /dev/null
> @@ -1,38 +0,0 @@
> -sun4i resistive touchscreen controller
> ---------------------------------------
> -
> -Required properties:
> - - compatible: "allwinner,sun4i-a10-ts", "allwinner,sun5i-a13-ts" or
> - "allwinner,sun6i-a31-ts"
> - - reg: mmio address range of the chip
> - - interrupts: interrupt to which the chip is connected
> - - #thermal-sensor-cells: shall be 0
> -
> -Optional properties:
> - - allwinner,ts-attached : boolean indicating that an actual touchscreen
> - is attached to the controller
> - - allwinner,tp-sensitive-adjust : integer (4 bits)
> - adjust sensitivity of pen down detection
> - between 0 (least sensitive) and 15
> - (defaults to 15)
> - - allwinner,filter-type : integer (2 bits)
> - select median and averaging filter
> - samples used for median / averaging filter
> - 0: 4/2
> - 1: 5/3
> - 2: 8/4
> - 3: 16/8
> - (defaults to 1)
> -
> -Example:
> -
> - rtp: rtp@01c25000 {
> - compatible = "allwinner,sun4i-a10-ts";
> - reg = <0x01c25000 0x100>;
> - interrupts = <29>;
> - allwinner,ts-attached;
> - #thermal-sensor-cells = <0>;
> - /* sensitive/noisy touch panel */
> - allwinner,tp-sensitive-adjust = <0>;
> - allwinner,filter-type = <3>;
> - };
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply
* Re: [PATCH v4 01/18] dt-bindings: power: battery: add constant-charge-current property
From: Quentin Schulz @ 2017-03-29 7:54 UTC (permalink / raw)
To: Liam Breck; +Cc: Sebastian Reichel, robh+dt, linux-pm, devicetree
In-Reply-To: <CAKvHMgSFNBmr3fU-biHDo5tzCDV7QaCpFnbChgn4wgSN_1FBig@mail.gmail.com>
Hi,
On 29/03/2017 09:39, Liam Breck wrote:
> On Wed, Mar 29, 2017 at 12:09 AM, Quentin Schulz
> <quentin.schulz@free-electrons.com> wrote:
>> Hi Liam,
>>
>> On 29/03/2017 08:55, Liam Breck wrote:
>>> Hi Quentin,
>>>
>>> On Thu, Mar 16, 2017 at 12:42 AM, Liam Breck <liam@networkimprov.net> wrote:
>>>> On Thu, Mar 16, 2017 at 12:03 AM, Quentin Schulz
>>>> <quentin.schulz@free-electrons.com> wrote:
>>>>> Hi Liam,
>>>>>
>>>>> On 16/03/2017 07:27, Liam Breck wrote:
>>>>>> Hi Rob,
>>>>>>
>>>>>> On Wed, Mar 15, 2017 at 6:10 AM, Quentin Schulz
>>>>>> <quentin.schulz@free-electrons.com> wrote:
>>>>>>> Hi Liam,
>>>>>>>
>>>>>>> On 15/03/2017 13:08, Liam Breck wrote:
>>>>>>>> I dropped most of the CCs, pls re-add anyone essential. Use Cc lines
>>>>>>>> in patch description to direct a patch to interested parties and
>>>>>>>> relevant lists. I don't want to see all 19 patches in this series.
>>>>>>>>
>>>>>>>> On Wed, Mar 15, 2017 at 3:55 AM, Quentin Schulz
>>>>>>>> <quentin.schulz@free-electrons.com> wrote:
>>>>>>>>> This adds the constant-charge-current property to the list of optional
>>>>>>>>> properties of the battery.
>>>>>>>>>
>>>>>>>>> The constant charge current is critical for batteries as they can't
>>>>>>>>> handle all charge currents.
>>>>>>>>>
>>>>>>>>> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
>>>>>>>>> Acked-by: Rob Herring <robh@kernel.org>
>>>>>>>>> ---
>>>>>>>>>
>>>>>>>>> v4:
>>>>>>>>> - switch from constant-charge-current-microamp to constant-charge-microamp,
>>>>>>
>>>>>> Sebastian is on record supporting name alignment between DT:battery
>>>>>> properties and enum power_supply_property.
>>>>>>
>>>>>> Could you OK a change back to constant-charge-current-microamp in this patch?
>>>>>>
>>>>>> Note that the following could appear in DT:battery in future:
>>>>>>
>>>>>> constant-charge-current-microamp
>>>>>> constant-charge-current-max-microamp
>>>>>
>>>>> OK. I am actually setting max constant charge current and constant
>>>>> current charge with the same DT property so I might need to adapt my
>>>>> patches.
>>>>
>>>> I suspect you should set battery:*-current-max with DT, as -current is
>>>> "programmed by charger" so seems to be a stat, not a fixed
>>>> characteristic.
>>>
>>> Did you resolve this issue?
>>>
>>
>> Sorry, completely missed your first mail.
>>
>> Constant charge current is actually what I set in the PMIC. The maximum
>> constant charge current is completely PMIC-agnostic in my driver as it
>> is used to tell the user that (s)he shouldn't really have a constant
>> charge current over the maximum limit as the battery might not be able
>> to handle such high current.
>>
>> What I suggest is to have both properties in DT. I'll set the maximum as
>> I do today and we can give the user the ability to set a "default"
>> constant charge current (below maximum constant charge current) in the
>> DT. Maybe we do not want to recharge your battery with the maximum value
>> by default?
>
> The scope here is just static battery characteristics. For the battery
> node, I think constant-charge-current-max-microamp is the relevant
> term.
If it's only for static battery characteristics, I agree.
> If we added both properties, one would be an alias for the
> other, which doesn't seem useful.
>
Hum. Not really an alias. In my driver, I have a maximum which avoids to
set a constant charge current higher than what the battery is supposed
to be able to handle. The maximum can be increased via sysfs if ever the
user decides to go wild (or if (s)he changes the battery for example).
The maximum is never input in any of PMIC registers, it is not dealing
with the PMIC at all.
If I have only the max constant charge current in the DT, I'll set the
max and constant charge current with the same DT entry. That's perfectly
fine.
However, what I was thinking is to have a "default" value taken from DT
for constant charge current (which will be below maximum ccc) if ever
someone wants to set a maximum but use a lower ccc value. Anyway, I
guess it's more a "fancy" feature than a requirement (unlike max-ccc).
> The pmic can report both independently of the battery characteristic,
> and take a driver-specific DT property for
> constant-charge-current-microamp which it applies if less than the
> battery's -max setting.
Indeed.
> Or you could set that in userspace via
> /sys/class.../constant_charge_current.
The goal is to have both. The DT for default values (given by the
vendor/upstream) and sysfs for custom values (interesting if you don't
want to/can't recompile a DT.
> The charger's -max value would
> be a characteristic of its regulator.
>
I don't really understand what you mean by that.
> Or am I missing something...?
>
>>> Rob & Sebastian want me to merge all items for
>>> bindings/power/supply/battery.txt. If I do that I'll also roll up
>>> their counterparts in power_supply_core.c and submit a patchset for
>>> those two files.
>>>
>>
>> I guess that adding the two properties make sense, don't you think?
>>
>> Also, could you Cc me on your next version of your patches? So I know
>> when to rebase and slightly rework my patches once your patch series is
>> merged.
>
> Surely.
>
>> Thanks,
>> Quentin
>>
>>>> You may program your charger's -current with the battery's
>>>> -current-max, of course.
>>>>
>>>> Note that your charger also has a -current-max characteristic, likely
>>>> different than your battery. You may not need that in DT tho.
>>>>
>>>>>> constant-charge-voltage-microvolt
>>>>>> constant-charge-voltage-max-microvolt
>>>>>>
>>>>>> Thanks!
>>>>>>
>>>>>>>> Must be constant-charge-current-microamp for the reasons discussed in
>>>>>>>> battery.txt - consistency with sysfs names.
>>>>>>>>
>>>>>>>
>>>>>>> Hum. Just nitpicking, but I disagree with the use of 'must'. IIRC there
>>>>>>> is nothing in the code that would require the property to be named after
>>>>>>> a property from the enum power_supply_property.
>>>>>>>
>>>>>>> I would say that you _want_ it to be named like that because it
>>>>>>> underlines the relation between the DT property and the actual impacted
>>>>>>> property in the power supply subsystem. I'm fine with this reason but in
>>>>>>> the end, the maintainer's opinion prevails (if (s)he does not want it,
>>>>>>> (s)he will not take it). So, basically, I actually don't mind either
>>>>>>> option and I see arguments on each side.
>>>>>>>
>>>>>>> So, just waiting for maintainer's opinion to make the final version of
>>>>>>> this patch.
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Quentin
>>>>>>>
>>>>>>>> Also applies to power_supply_core.c patch.
>>>>>>>>
>>>>>>>> Rob: enum power_supply_property also lists constant-charge-voltage,
>>>>>>>> hence the -current
>>>>>>>>
>>>>>>>>
>>>>>>>>> added in v3
>>>>>>>>>
>>>>>>>>> Documentation/devicetree/bindings/power/supply/battery.txt | 2 ++
>>>>>>>>> 1 file changed, 2 insertions(+)
>>>>>>>>>
>>>>>>>>> diff --git a/Documentation/devicetree/bindings/power/supply/battery.txt b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>>>> index 0278617..9594e1e 100644
>>>>>>>>> --- a/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>>>> +++ b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>>>> @@ -7,6 +7,7 @@ Optional Properties:
>>>>>>>>> - voltage-min-design-microvolt: drained battery voltage
>>>>>>>>> - energy-full-design-microwatt-hours: battery design energy
>>>>>>>>> - charge-full-design-microamp-hours: battery design capacity
>>>>>>>>> + - constant-charge-microamp: battery constant charge current
>>>>>>>>>
>>>>>>>>> Because drivers surface properties in sysfs using names derived
>>>>>>>>> from enum power_supply_property, e.g.
>>>>>>>>> @@ -30,6 +31,7 @@ Example:
>>>>>>>>> voltage-min-design-microvolt = <3200000>;
>>>>>>>>> energy-full-design-microwatt-hours = <5290000>;
>>>>>>>>> charge-full-design-microamp-hours = <1430000>;
>>>>>>>>> + constant-charge-microamp = <300000>;
>>>>>>>>> };
>>>>>>>>>
>>>>>>>>> charger: charger@11 {
>>>>>>>>> --
>>>>>>>>> 2.9.3
>>>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> Quentin Schulz, Free Electrons
>>>>>>> Embedded Linux and Kernel engineering
>>>>>>> http://free-electrons.com
>>>>>
>>>>> --
>>>>> Quentin Schulz, Free Electrons
>>>>> Embedded Linux and Kernel engineering
>>>>> http://free-electrons.com
>>
>> --
>> Quentin Schulz, Free Electrons
>> Embedded Linux and Kernel engineering
>> http://free-electrons.com
--
Quentin Schulz, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* Re: [RFC PATCH 2/3] iio: adc: sun4i-gpadc-iio: add support for H3 thermal sensor
From: Lee Jones @ 2017-03-29 7:54 UTC (permalink / raw)
To: Icenowy Zheng
Cc: Quentin Schulz, Zhang Rui, linux-pm-u79uwXL29TY76Z2rM5mHXA,
Rob Herring, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Jonathan Cameron,
Maxime Ripard, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Chen-Yu Tsai
In-Reply-To: <20170329065717.D0AF37C1EFF-Y9/x5g2N/Tt0ykcd9G8QkxTxI0vvWBSX@public.gmane.org>
On Wed, 29 Mar 2017, Icenowy Zheng wrote:
>
> 2017年3月29日 14:54于 Quentin Schulz <quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>写道:
> >
> > Hi,
> >
> > On 28/03/2017 19:30, Icenowy Zheng wrote:
> > > This adds support for the Allwinner H3 thermal sensor.
> > >
> > > Allwinner H3 has a thermal sensor like the one in A33, but have its
> > > registers nearly all re-arranged, sample clock moved to CCU and a pair
> > > of bus clock and reset added. It's also the base of newer SoCs' thermal
> > > sensors.
> > >
> > > An option is added to gpadc_data struct, to indicate whether this device
> > > is a new-generation Allwinner thermal sensor.
> > >
> > > The thermal sensors on A64 and H5 is like the one on H3, but with of
> > > course different formula factors.
> > >
> > > Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
> > > ---
> > > drivers/iio/adc/sun4i-gpadc-iio.c | 130 ++++++++++++++++++++++++++++++++------
> > > include/linux/mfd/sun4i-gpadc.h | 33 +++++++++-
> > > 2 files changed, 141 insertions(+), 22 deletions(-)
How have you managed to reply un-threaded?
Please ensure you mailer attaches your reply to the rest of the
thread, or things will become very confusing, very quickly.
> > > diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
> > > index 74705aa37982..7512b1cae877 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 <linux/clk.h>
> > > #include <linux/completion.h>
> > > #include <linux/interrupt.h>
> > > #include <linux/io.h>
> > > @@ -31,6 +32,7 @@
> > > #include <linux/platform_device.h>
> > > #include <linux/pm_runtime.h>
> > > #include <linux/regmap.h>
> > > +#include <linux/reset.h>
> > > #include <linux/thermal.h>
> > > #include <linux/delay.h>
> > >
> > > @@ -56,6 +58,7 @@ struct gpadc_data {
> > > unsigned int tp_adc_select;
> > > unsigned int (*adc_chan_select)(unsigned int chan);
> > > unsigned int adc_chan_mask;
> > > + bool gen2_ths;
> > > };
> > >
> >
> > Instead of a boolean, give the TEMP_DATA register address.
> >
> > > static const struct gpadc_data sun4i_gpadc_data = {
> > > @@ -88,7 +91,20 @@ static const struct gpadc_data sun6i_gpadc_data = {
> > > static const struct gpadc_data sun8i_a33_gpadc_data = {
> > > .temp_offset = -1662,
> > > .temp_scale = 162,
> > > - .tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN,
> > > + .tp_mode_en = SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN,
> > > +};
> >
> > Separate patch for this?
> >
> > > +
> > > +static const struct gpadc_data sun8i_h3_gpadc_data = {
> > > + /*
> > > + * The original formula on the datasheet seems to be wrong.
> > > + * These factors are calculated based on the formula in the BSP
> > > + * kernel, which is originally Tem = 217 - (T / 8.253), in which Tem
> > > + * is the temperature in Celsius degree and T is the raw value
> > > + * from the sensor.
> > > + */
> > > + .temp_offset = -1791,
> > > + .temp_scale = -121,
> > > + .gen2_ths = true,
> > > };
> > >
> > > struct sun4i_gpadc_iio {
> > > @@ -103,6 +119,9 @@ struct sun4i_gpadc_iio {
> > > atomic_t ignore_temp_data_irq;
> > > const struct gpadc_data *data;
> > > bool no_irq;
> > > + struct clk *ths_bus_clk;
> > > + struct clk *ths_clk;
> > > + struct reset_control *reset;
> > > /* prevents concurrent reads of temperature and ADC */
> > > struct mutex mutex;
> > > };
> > > @@ -274,7 +293,11 @@ 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);
> > > + if (info->data->gen2_ths)
> > > + regmap_read(info->regmap, SUN8I_H3_GPADC_TEMP_DATA,
> > > + val);
> > > + else
> > > + regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val);
> > >
> >
> > Instead of gen2_ths, use the TEMP_DATA register address.
> >
> > > pm_runtime_mark_last_busy(indio_dev->dev.parent);
> > > pm_runtime_put_autosuspend(indio_dev->dev.parent);
> > > @@ -386,10 +409,15 @@ static int sun4i_gpadc_runtime_suspend(struct device *dev)
> > > {
> > > 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 */
> > > - regmap_write(info->regmap, SUN4I_GPADC_TPR, 0);
> > > + if (info->data->gen2_ths) {
> > > + /* Disable temperature sensor */
> > > + regmap_write(info->regmap, SUN8I_H3_GPADC_CTRL2, 0);
> > > + } else {
> > > + /* Disable the ADC on IP */
> > > + regmap_write(info->regmap, SUN4I_GPADC_CTRL1, 0);
> > > + /* Disable temperature sensor on IP */
> > > + regmap_write(info->regmap, SUN4I_GPADC_TPR, 0);
> > > + }
> > >
> >
> > Either use another register address or add a suspend function to struct
> > gpadc_data which will be different for each version of the IP.
> >
> > > return 0;
> > > }
> > > @@ -398,19 +426,36 @@ static int sun4i_gpadc_runtime_resume(struct device *dev)
> > > {
> > > 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) |
> > > - SUN4I_GPADC_CTRL0_FS_DIV(7) |
> > > - SUN4I_GPADC_CTRL0_T_ACQ(63));
> > > - regmap_write(info->regmap, SUN4I_GPADC_CTRL1, info->data->tp_mode_en);
> > > - regmap_write(info->regmap, SUN4I_GPADC_CTRL3,
> > > - SUN4I_GPADC_CTRL3_FILTER_EN |
> > > - SUN4I_GPADC_CTRL3_FILTER_TYPE(1));
> > > - /* period = SUN4I_GPADC_TPR_TEMP_PERIOD * 256 * 16 / clkin; ~0.6s */
> > > - regmap_write(info->regmap, SUN4I_GPADC_TPR,
> > > - SUN4I_GPADC_TPR_TEMP_ENABLE |
> > > - SUN4I_GPADC_TPR_TEMP_PERIOD(800));
> > > + if (info->data->gen2_ths) {
> > > + regmap_write(info->regmap, SUN8I_H3_GPADC_CTRL2,
> > > + SUN8I_H3_GPADC_CTRL2_TEMP_SENSE_EN |
> > > + SUN8I_H3_GPADC_CTRL2_T_ACQ1(31));
> > > + regmap_write(info->regmap, SUN4I_GPADC_CTRL0,
> > > + SUN4I_GPADC_CTRL0_T_ACQ(31));
> > > + regmap_write(info->regmap, SUN8I_H3_GPADC_CTRL3,
> > > + SUN4I_GPADC_CTRL3_FILTER_EN |
> > > + SUN4I_GPADC_CTRL3_FILTER_TYPE(1));
> > > + regmap_write(info->regmap, SUN8I_H3_GPADC_INTC,
> > > + SUN8I_H3_GPADC_INTC_TEMP_PERIOD(800));
> > > + } else {
> > > + /* clkin = 6MHz */
> > > + regmap_write(info->regmap, SUN4I_GPADC_CTRL0,
> > > + SUN4I_GPADC_CTRL0_ADC_CLK_DIVIDER(2) |
> > > + SUN4I_GPADC_CTRL0_FS_DIV(7) |
> > > + SUN4I_GPADC_CTRL0_T_ACQ(63));
> > > + regmap_write(info->regmap, SUN4I_GPADC_CTRL1,
> > > + info->data->tp_mode_en);
> > > + regmap_write(info->regmap, SUN4I_GPADC_CTRL3,
> > > + SUN4I_GPADC_CTRL3_FILTER_EN |
> > > + SUN4I_GPADC_CTRL3_FILTER_TYPE(1));
> > > + /*
> > > + * period = SUN4I_GPADC_TPR_TEMP_PERIOD * 256 * 16 / clkin;
> > > + * ~0.6s
> > > + */
> > > + regmap_write(info->regmap, SUN4I_GPADC_TPR,
> > > + SUN4I_GPADC_TPR_TEMP_ENABLE |
> > > + SUN4I_GPADC_TPR_TEMP_PERIOD(800));
> > > + }
> > >
> >
> > Same here as suspend function?
> >
> > > return 0;
> > > }
> > > @@ -494,6 +539,10 @@ static const struct of_device_id sun4i_gpadc_of_id[] = {
> > > .compatible = "allwinner,sun8i-a33-ths",
> > > .data = &sun8i_a33_gpadc_data,
> > > },
> > > + {
> > > + .compatible = "allwinner,sun8i-h3-ths",
> > > + .data = &sun8i_h3_gpadc_data,
> > > + },
> > > { /* sentinel */ }
> > > };
> > >
> > > @@ -529,6 +578,43 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
> > > return ret;
> > > }
> > >
> > > + if (info->data->gen2_ths) {
> > > + info->reset = devm_reset_control_get(&pdev->dev, NULL);
> > > + if (IS_ERR(info->reset)) {
> > > + ret = PTR_ERR(info->reset);
> > > + return ret;
> > > + }
> > > +
> > > + ret = reset_control_deassert(info->reset);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + info->ths_bus_clk = devm_clk_get(&pdev->dev, "bus");
> > > + if (IS_ERR(info->ths_bus_clk)) {
> > > + ret = PTR_ERR(info->ths_bus_clk);
> > > + return ret;
> > > + }
> > > +
> > > + ret = clk_prepare_enable(info->ths_bus_clk);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + info->ths_clk = devm_clk_get(&pdev->dev, "ths");
> > > + if (IS_ERR(info->ths_clk)) {
> > > + ret = PTR_ERR(info->ths_clk);
> > > + return ret;
> > > + }
> > > +
> > > + /* Running at 6MHz */
> > > + ret = clk_set_rate(info->ths_clk, 6000000);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + ret = clk_prepare_enable(info->ths_clk);
> > > + if (ret)
> > > + return ret;
> > > + }
> > > +
> > > if (!IS_ENABLED(CONFIG_THERMAL_OF))
> > > return 0;
> > >
> > > @@ -691,6 +777,12 @@ static int sun4i_gpadc_remove(struct platform_device *pdev)
> > > if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF))
> > > iio_map_array_unregister(indio_dev);
> > >
> > > + if (info->data->gen2_ths) {
> > > + clk_disable_unprepare(info->ths_clk);
> > > + clk_disable_unprepare(info->ths_bus_clk);
> > > + reset_control_deassert(info->reset);
> > > + }
> > > +
> >
> > I'm not really fond of using this boolean as I don't see it being
> > possibly reused for any other SoCs that has a GPADC or THS.
>
> Because you didn't care new SoCs :-)
>
> All SoCs after H3 (A64, H5, R40) uses the same THS architecture with H3.
>
> >
> > Here, you could make use of a list/array of clk which then can be reused
> > for other SoCs just by changing the list. Add a default rate to the
> > gpadc_data structure and you're go to go.
> >
> > > return 0;
> > > }
> > >
> > > diff --git a/include/linux/mfd/sun4i-gpadc.h b/include/linux/mfd/sun4i-gpadc.h
> > > index 139872c2e0fe..f794a2988a93 100644
> > > --- a/include/linux/mfd/sun4i-gpadc.h
> > > +++ b/include/linux/mfd/sun4i-gpadc.h
> > > @@ -38,9 +38,12 @@
> > > #define SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(x) (GENMASK(3, 0) & BIT(x))
> > > #define SUN6I_GPADC_CTRL1_ADC_CHAN_MASK GENMASK(3, 0)
> > >
> > > -/* TP_CTRL1 bits for sun8i SoCs */
> > > -#define SUN8I_GPADC_CTRL1_CHOP_TEMP_EN BIT(8)
> > > -#define SUN8I_GPADC_CTRL1_GPADC_CALI_EN BIT(7)
> > > +/* TP_CTRL1 bits for sun8i A23/A33 SoCs */
> > > +#define SUN8I_A23_GPADC_CTRL1_CHOP_TEMP_EN BIT(8)
> > > +#define SUN8I_A23_GPADC_CTRL1_GPADC_CALI_EN BIT(7)
> > > +
> >
> > Different patch for these?
> >
> > Thanks,
> > Quentin
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v3 2/3] irqchip: mtk-cirq: Add mediatek mtk-cirq implement
From: Mars Cheng @ 2017-03-29 7:53 UTC (permalink / raw)
To: Marc Zyngier
Cc: Youlin Pei, Rob Herring, Matthias Brugger, Mark Rutland,
devicetree-u79uwXL29TY76Z2rM5mHXA,
hongkun.cao-NuS5LvNUpcJWk0Htik3J/w, Jason Cooper,
srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
erin.lo-NuS5LvNUpcJWk0Htik3J/w,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Russell King,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
yong.wu-NuS5LvNUpcJWk0Htik3J/w, Thomas Gleixner,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <499f9186-82c1-cb5a-91de-754c89bcdd3d-5wv7dgnIgG8@public.gmane.org>
Hi Marc
comments inline
On Fri, 2017-03-24 at 16:22 +0000, Marc Zyngier wrote:
> On 14/02/17 02:56, Youlin Pei wrote:
> > In Mediatek SOCs, the CIRQ is a low power interrupt controller
> > designed to works outside MCUSYS which comprises with Cortex-Ax
> > cores,CCI and GIC.
> >
> > The CIRQ controller is integrated in between MCUSYS( include
> > Cortex-Ax, CCI and GIC ) and interrupt sources as the second
> > level interrupt controller. The external interrupts which outside
> > MCUSYS will feed through CIRQ then bypass to GIC. CIRQ can monitors
> > all edge trigger interupts. When an edge interrupt is triggered,
> > CIRQ can record the status and generate a pulse signal to GIC when
> > flush command executed.
> >
> > When system enters sleep mode, MCUSYS will be turned off to improve
> > power consumption, also GIC is power down. The edge trigger interrupts
> > will be lost in this scenario without CIRQ.
> >
> > This commit provides the CIRQ irqchip implement.
> >
> > Signed-off-by: Youlin Pei <youlin.pei-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> > ---
> > drivers/irqchip/Makefile | 2 +-
> > drivers/irqchip/irq-mtk-cirq.c | 288 ++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 289 insertions(+), 1 deletion(-)
> > create mode 100644 drivers/irqchip/irq-mtk-cirq.c
> >
> > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> > index 0e55d94..db9acd1 100644
> > --- a/drivers/irqchip/Makefile
> > +++ b/drivers/irqchip/Makefile
> > @@ -61,7 +61,7 @@ obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o
> > obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o
> > obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o
> > obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o
> > -obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o
> > +obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o irq-mtk-cirq.o
> > obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o
> > obj-$(CONFIG_RENESAS_H8300H_INTC) += irq-renesas-h8300h.o
> > obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o
> > diff --git a/drivers/irqchip/irq-mtk-cirq.c b/drivers/irqchip/irq-mtk-cirq.c
> > new file mode 100644
> > index 0000000..b5cf506
> > --- /dev/null
> > +++ b/drivers/irqchip/irq-mtk-cirq.c
> > @@ -0,0 +1,288 @@
> > +/*
> > + * Copyright (c) 2016 MediaTek Inc.
> > + * Author: Youlin.Pei <youlin.pei-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> > + *
> > + * 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.
> > + *
> > + * 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 <linux/interrupt.h>
> > +#include <linux/io.h>
> > +#include <linux/irq.h>
> > +#include <linux/irqchip.h>
> > +#include <linux/irqdomain.h>
> > +#include <linux/of.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/of_address.h>
> > +#include <linux/slab.h>
> > +#include <linux/syscore_ops.h>
> > +
> > +#define CIRQ_ACK 0x40
> > +#define CIRQ_MASK_SET 0xc0
> > +#define CIRQ_MASK_CLR 0x100
> > +#define CIRQ_SENS_SET 0x180
> > +#define CIRQ_SENS_CLR 0x1c0
> > +#define CIRQ_POL_SET 0x240
> > +#define CIRQ_POL_CLR 0x280
> > +#define CIRQ_CONTROL 0x300
> > +
> > +#define CIRQ_EN 0x1
> > +#define CIRQ_EDGE 0x2
> > +#define CIRQ_FLUSH 0x4
> > +
> > +struct mtk_cirq_chip_data {
> > + void __iomem *base;
> > + unsigned int ext_irq_start;
> > + unsigned int ext_irq_end;
> > + struct irq_domain *domain;
> > +};
> > +
> > +static struct mtk_cirq_chip_data *cirq_data;
>
> Question in relation to the sysirq patches that have been queued for
> 4.12: Are we going to see something similar with this driver, where
> you're going to have to support multiple non-contiguous register sets?
> I'd rather have this kind of thing from day one, instead of adding that
> at a later time...
>
> Specially given that the platform that is using this driver does also
> have a sysirq controller.
sysirq is kind of special design which mediatek's HW guys put the bases
in a range with other misc usages. so sysirq might happen to have
several bases.
cirq is like other normal controller which has its own base and range.
We have all cirq design with single base.
Also asked our HW guys to allocate sysirq with single base as possible
in the future even they put it in misc address range.
Thanks.
>
> > +
> > +static void mtk_cirq_write_mask(struct irq_data *data, unsigned int offset)
> > +{
> > + struct mtk_cirq_chip_data *chip_data = data->chip_data;
> > + unsigned int cirq_num = data->hwirq;
> > + u32 mask = 1 << (cirq_num % 32);
> > +
> > + writel_relaxed(mask, chip_data->base + offset + (cirq_num / 32) * 4);
> > +}
> > +
> > +static void mtk_cirq_mask(struct irq_data *data)
> > +{
> > + mtk_cirq_write_mask(data, CIRQ_MASK_SET);
> > + irq_chip_mask_parent(data);
> > +}
> > +
> > +static void mtk_cirq_unmask(struct irq_data *data)
> > +{
> > + mtk_cirq_write_mask(data, CIRQ_MASK_CLR);
> > + irq_chip_unmask_parent(data);
> > +}
> > +
> > +static int mtk_cirq_set_type(struct irq_data *data, unsigned int type)
> > +{
> > + int ret;
> > +
> > + switch (type & IRQ_TYPE_SENSE_MASK) {
> > + case IRQ_TYPE_EDGE_FALLING:
> > + mtk_cirq_write_mask(data, CIRQ_POL_CLR);
> > + mtk_cirq_write_mask(data, CIRQ_SENS_CLR);
> > + break;
> > + case IRQ_TYPE_EDGE_RISING:
> > + mtk_cirq_write_mask(data, CIRQ_POL_SET);
> > + mtk_cirq_write_mask(data, CIRQ_SENS_CLR);
> > + break;
> > + case IRQ_TYPE_LEVEL_LOW:
> > + mtk_cirq_write_mask(data, CIRQ_POL_CLR);
> > + mtk_cirq_write_mask(data, CIRQ_SENS_SET);
> > + break;
> > + case IRQ_TYPE_LEVEL_HIGH:
> > + mtk_cirq_write_mask(data, CIRQ_POL_SET);
> > + mtk_cirq_write_mask(data, CIRQ_SENS_SET);
> > + break;
> > + default:
> > + break;
> > + }
> > +
> > + data = data->parent_data;
> > + ret = data->chip->irq_set_type(data, type);
> > + return ret;
> > +}
> > +
> > +static struct irq_chip mtk_cirq_chip = {
> > + .name = "MT_CIRQ",
> > + .irq_mask = mtk_cirq_mask,
> > + .irq_unmask = mtk_cirq_unmask,
> > + .irq_eoi = irq_chip_eoi_parent,
> > + .irq_set_type = mtk_cirq_set_type,
> > + .irq_retrigger = irq_chip_retrigger_hierarchy,
> > +#ifdef CONFIG_SMP
> > + .irq_set_affinity = irq_chip_set_affinity_parent,
> > +#endif
> > +};
> > +
> > +static int mtk_cirq_domain_translate(struct irq_domain *d,
> > + struct irq_fwspec *fwspec,
> > + unsigned long *hwirq,
> > + unsigned int *type)
> > +{
> > + if (is_of_node(fwspec->fwnode)) {
> > + if (fwspec->param_count != 3)
> > + return -EINVAL;
> > +
> > + /* No PPI should point to this domain */
> > + if (fwspec->param[0] != 0)
> > + return -EINVAL;
> > +
> > + /* cirq support irq number check */
> > + if (fwspec->param[1] < cirq_data->ext_irq_start ||
> > + fwspec->param[1] > cirq_data->ext_irq_end)
> > + return -EINVAL;
> > +
> > + *hwirq = fwspec->param[1] - cirq_data->ext_irq_start;
> > + *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
> > + return 0;
> > + }
> > +
> > + return -EINVAL;
> > +}
> > +
> > +static int mtk_cirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
> > + unsigned int nr_irqs, void *arg)
> > +{
> > + int ret;
> > + irq_hw_number_t hwirq;
> > + unsigned int type;
> > + struct irq_fwspec *fwspec = arg;
> > + struct irq_fwspec parent_fwspec = *fwspec;
> > +
> > + ret = mtk_cirq_domain_translate(domain, fwspec, &hwirq, &type);
> > + if (ret)
> > + return ret;
> > +
> > + if (WARN_ON(nr_irqs != 1))
> > + return -EINVAL;
> > +
> > + irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
> > + &mtk_cirq_chip,
> > + domain->host_data);
> > +
> > + parent_fwspec.fwnode = domain->parent->fwnode;
> > + return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
> > + &parent_fwspec);
> > +}
> > +
> > +static const struct irq_domain_ops cirq_domain_ops = {
> > + .translate = mtk_cirq_domain_translate,
> > + .alloc = mtk_cirq_domain_alloc,
> > + .free = irq_domain_free_irqs_common,
> > +};
> > +
> > +#ifdef CONFIG_PM_SLEEP
> > +static int mtk_cirq_suspend(void)
> > +{
> > + u32 value, mask;
> > + unsigned int irq, hwirq_num;
> > + bool pending, masked;
> > + int i, pendret, maskret;
> > +
> > + hwirq_num = cirq_data->ext_irq_end - cirq_data->ext_irq_start + 1;
> > + for (i = 0; i < hwirq_num; i++) {
> > + irq = irq_find_mapping(cirq_data->domain, i);
> > + if (irq) {
> > + pendret = irq_get_irqchip_state(irq,
> > + IRQCHIP_STATE_PENDING,
> > + &pending);
> > +
> > + maskret = irq_get_irqchip_state(irq,
> > + IRQCHIP_STATE_MASKED,
> > + &masked);
> > +
> > + if (pendret == 0 && maskret == 0 &&
> > + (pending && !masked))
> > + continue;
> > + }
> > +
> > + mask = 1 << (i % 32);
> > + writel_relaxed(mask, cirq_data->base + CIRQ_ACK + (i / 32) * 4);
> > + }
>
> It would be worth documenting exactly what this is for. I had to go back
> to our previous discussion in November to remember it.
>
> > +
> > + /* set edge_only mode, record edge-triggerd interrupts */
> > + /* enable cirq */
> > + value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
> > + value |= (CIRQ_EDGE | CIRQ_EN);
> > + writel_relaxed(value, cirq_data->base + CIRQ_CONTROL);
> > +
> > + return 0;
> > +}
> > +
> > +static void mtk_cirq_resume(void)
> > +{
> > + u32 value;
> > +
> > + /* flush recored interrupts, will send signals to parent controller */
> > + value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
> > + writel_relaxed(value | CIRQ_FLUSH, cirq_data->base + CIRQ_CONTROL);
> > +
> > + /* disable cirq */
> > + value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
> > + value &= ~(CIRQ_EDGE | CIRQ_EN);
> > + writel_relaxed(value, cirq_data->base + CIRQ_CONTROL);
> > +}
> > +
> > +static struct syscore_ops mtk_cirq_syscore_ops = {
> > + .suspend = mtk_cirq_suspend,
> > + .resume = mtk_cirq_resume,
> > +};
> > +
> > +static void mtk_cirq_syscore_init(void)
> > +{
> > + register_syscore_ops(&mtk_cirq_syscore_ops);
> > +}
> > +#else
> > +static inline void mtk_cirq_syscore_init(void) {}
> > +#endif
> > +
> > +static int __init mtk_cirq_of_init(struct device_node *node,
> > + struct device_node *parent)
> > +{
> > + struct irq_domain *domain, *domain_parent;
> > + unsigned int irq_num;
> > + int ret;
> > +
> > + domain_parent = irq_find_host(parent);
> > + if (!domain_parent) {
> > + pr_err("mtk_cirq: interrupt-parent not found\n");
> > + return -EINVAL;
> > + }
> > +
> > + cirq_data = kzalloc(sizeof(*cirq_data), GFP_KERNEL);
> > + if (!cirq_data)
> > + return -ENOMEM;
> > +
> > + cirq_data->base = of_iomap(node, 0);
> > + if (!cirq_data->base) {
> > + pr_err("mtk_cirq: unable to map cirq register\n");
> > + ret = -ENXIO;
> > + goto out_free;
> > + }
> > +
> > + ret = of_property_read_u32_index(node, "mediatek,ext-irq-range", 0,
> > + &cirq_data->ext_irq_start);
> > + if (ret)
> > + goto out_unmap;
> > +
> > + ret = of_property_read_u32_index(node, "mediatek,ext-irq-range", 1,
> > + &cirq_data->ext_irq_end);
> > + if (ret)
> > + goto out_unmap;
> > +
> > + irq_num = cirq_data->ext_irq_end - cirq_data->ext_irq_start + 1;
> > + domain = irq_domain_add_hierarchy(domain_parent, 0,
> > + irq_num, node,
> > + &cirq_domain_ops, cirq_data);
> > + if (!domain) {
> > + ret = -ENOMEM;
> > + goto out_unmap;
> > + }
> > + cirq_data->domain = domain;
> > +
> > + mtk_cirq_syscore_init();
> > +
> > + return 0;
> > +
> > +out_unmap:
> > + iounmap(cirq_data->base);
> > +out_free:
> > + kfree(cirq_data);
> > + return ret;
> > +}
> > +
> > +IRQCHIP_DECLARE(mtk_cirq, "mediatek,mtk-cirq", mtk_cirq_of_init);
> >
>
> It otherwise looks much better than the previous iteration.
>
> Thanks,
>
> M.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v4 01/18] dt-bindings: power: battery: add constant-charge-current property
From: Liam Breck @ 2017-03-29 7:39 UTC (permalink / raw)
To: Quentin Schulz; +Cc: Sebastian Reichel, robh+dt, linux-pm, devicetree
In-Reply-To: <659fb6a3-d49d-5429-8770-88917e4fd0b3@free-electrons.com>
On Wed, Mar 29, 2017 at 12:09 AM, Quentin Schulz
<quentin.schulz@free-electrons.com> wrote:
> Hi Liam,
>
> On 29/03/2017 08:55, Liam Breck wrote:
>> Hi Quentin,
>>
>> On Thu, Mar 16, 2017 at 12:42 AM, Liam Breck <liam@networkimprov.net> wrote:
>>> On Thu, Mar 16, 2017 at 12:03 AM, Quentin Schulz
>>> <quentin.schulz@free-electrons.com> wrote:
>>>> Hi Liam,
>>>>
>>>> On 16/03/2017 07:27, Liam Breck wrote:
>>>>> Hi Rob,
>>>>>
>>>>> On Wed, Mar 15, 2017 at 6:10 AM, Quentin Schulz
>>>>> <quentin.schulz@free-electrons.com> wrote:
>>>>>> Hi Liam,
>>>>>>
>>>>>> On 15/03/2017 13:08, Liam Breck wrote:
>>>>>>> I dropped most of the CCs, pls re-add anyone essential. Use Cc lines
>>>>>>> in patch description to direct a patch to interested parties and
>>>>>>> relevant lists. I don't want to see all 19 patches in this series.
>>>>>>>
>>>>>>> On Wed, Mar 15, 2017 at 3:55 AM, Quentin Schulz
>>>>>>> <quentin.schulz@free-electrons.com> wrote:
>>>>>>>> This adds the constant-charge-current property to the list of optional
>>>>>>>> properties of the battery.
>>>>>>>>
>>>>>>>> The constant charge current is critical for batteries as they can't
>>>>>>>> handle all charge currents.
>>>>>>>>
>>>>>>>> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
>>>>>>>> Acked-by: Rob Herring <robh@kernel.org>
>>>>>>>> ---
>>>>>>>>
>>>>>>>> v4:
>>>>>>>> - switch from constant-charge-current-microamp to constant-charge-microamp,
>>>>>
>>>>> Sebastian is on record supporting name alignment between DT:battery
>>>>> properties and enum power_supply_property.
>>>>>
>>>>> Could you OK a change back to constant-charge-current-microamp in this patch?
>>>>>
>>>>> Note that the following could appear in DT:battery in future:
>>>>>
>>>>> constant-charge-current-microamp
>>>>> constant-charge-current-max-microamp
>>>>
>>>> OK. I am actually setting max constant charge current and constant
>>>> current charge with the same DT property so I might need to adapt my
>>>> patches.
>>>
>>> I suspect you should set battery:*-current-max with DT, as -current is
>>> "programmed by charger" so seems to be a stat, not a fixed
>>> characteristic.
>>
>> Did you resolve this issue?
>>
>
> Sorry, completely missed your first mail.
>
> Constant charge current is actually what I set in the PMIC. The maximum
> constant charge current is completely PMIC-agnostic in my driver as it
> is used to tell the user that (s)he shouldn't really have a constant
> charge current over the maximum limit as the battery might not be able
> to handle such high current.
>
> What I suggest is to have both properties in DT. I'll set the maximum as
> I do today and we can give the user the ability to set a "default"
> constant charge current (below maximum constant charge current) in the
> DT. Maybe we do not want to recharge your battery with the maximum value
> by default?
The scope here is just static battery characteristics. For the battery
node, I think constant-charge-current-max-microamp is the relevant
term. If we added both properties, one would be an alias for the
other, which doesn't seem useful.
The pmic can report both independently of the battery characteristic,
and take a driver-specific DT property for
constant-charge-current-microamp which it applies if less than the
battery's -max setting. Or you could set that in userspace via
/sys/class.../constant_charge_current. The charger's -max value would
be a characteristic of its regulator.
Or am I missing something...?
>> Rob & Sebastian want me to merge all items for
>> bindings/power/supply/battery.txt. If I do that I'll also roll up
>> their counterparts in power_supply_core.c and submit a patchset for
>> those two files.
>>
>
> I guess that adding the two properties make sense, don't you think?
>
> Also, could you Cc me on your next version of your patches? So I know
> when to rebase and slightly rework my patches once your patch series is
> merged.
Surely.
> Thanks,
> Quentin
>
>>> You may program your charger's -current with the battery's
>>> -current-max, of course.
>>>
>>> Note that your charger also has a -current-max characteristic, likely
>>> different than your battery. You may not need that in DT tho.
>>>
>>>>> constant-charge-voltage-microvolt
>>>>> constant-charge-voltage-max-microvolt
>>>>>
>>>>> Thanks!
>>>>>
>>>>>>> Must be constant-charge-current-microamp for the reasons discussed in
>>>>>>> battery.txt - consistency with sysfs names.
>>>>>>>
>>>>>>
>>>>>> Hum. Just nitpicking, but I disagree with the use of 'must'. IIRC there
>>>>>> is nothing in the code that would require the property to be named after
>>>>>> a property from the enum power_supply_property.
>>>>>>
>>>>>> I would say that you _want_ it to be named like that because it
>>>>>> underlines the relation between the DT property and the actual impacted
>>>>>> property in the power supply subsystem. I'm fine with this reason but in
>>>>>> the end, the maintainer's opinion prevails (if (s)he does not want it,
>>>>>> (s)he will not take it). So, basically, I actually don't mind either
>>>>>> option and I see arguments on each side.
>>>>>>
>>>>>> So, just waiting for maintainer's opinion to make the final version of
>>>>>> this patch.
>>>>>>
>>>>>> Thanks,
>>>>>> Quentin
>>>>>>
>>>>>>> Also applies to power_supply_core.c patch.
>>>>>>>
>>>>>>> Rob: enum power_supply_property also lists constant-charge-voltage,
>>>>>>> hence the -current
>>>>>>>
>>>>>>>
>>>>>>>> added in v3
>>>>>>>>
>>>>>>>> Documentation/devicetree/bindings/power/supply/battery.txt | 2 ++
>>>>>>>> 1 file changed, 2 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/Documentation/devicetree/bindings/power/supply/battery.txt b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>>> index 0278617..9594e1e 100644
>>>>>>>> --- a/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>>> +++ b/Documentation/devicetree/bindings/power/supply/battery.txt
>>>>>>>> @@ -7,6 +7,7 @@ Optional Properties:
>>>>>>>> - voltage-min-design-microvolt: drained battery voltage
>>>>>>>> - energy-full-design-microwatt-hours: battery design energy
>>>>>>>> - charge-full-design-microamp-hours: battery design capacity
>>>>>>>> + - constant-charge-microamp: battery constant charge current
>>>>>>>>
>>>>>>>> Because drivers surface properties in sysfs using names derived
>>>>>>>> from enum power_supply_property, e.g.
>>>>>>>> @@ -30,6 +31,7 @@ Example:
>>>>>>>> voltage-min-design-microvolt = <3200000>;
>>>>>>>> energy-full-design-microwatt-hours = <5290000>;
>>>>>>>> charge-full-design-microamp-hours = <1430000>;
>>>>>>>> + constant-charge-microamp = <300000>;
>>>>>>>> };
>>>>>>>>
>>>>>>>> charger: charger@11 {
>>>>>>>> --
>>>>>>>> 2.9.3
>>>>>>>>
>>>>>>
>>>>>> --
>>>>>> Quentin Schulz, Free Electrons
>>>>>> Embedded Linux and Kernel engineering
>>>>>> http://free-electrons.com
>>>>
>>>> --
>>>> Quentin Schulz, Free Electrons
>>>> Embedded Linux and Kernel engineering
>>>> http://free-electrons.com
>
> --
> Quentin Schulz, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
^ permalink raw reply
* Re: [PATCH v3 4/9] arm: remove wrong CONFIG_PROC_SYSCTL ifdef
From: Vincent Guittot @ 2017-03-29 7:39 UTC (permalink / raw)
To: Juri Lelli
Cc: linux-kernel, linux-pm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
LAK, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Peter Zijlstra, Rob Herring, Mark Rutland,
Russell King - ARM Linux, Sudeep Holla, Lorenzo Pieralisi,
Catalin Marinas, Will Deacon, Morten Rasmussen, Dietmar Eggemann,
Mark Brown,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org
In-Reply-To: <20170327131825.32134-5-juri.lelli-5wv7dgnIgG8@public.gmane.org>
On 27 March 2017 at 15:18, Juri Lelli <juri.lelli-5wv7dgnIgG8@public.gmane.org> wrote:
> The sysfs cpu_capacity entry for each CPU has nothing to do with
> PROC_FS, nor it's in /proc/sys path.
>
> Remove such ifdef.
>
> Cc: Russell King <linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>
> Reported-and-suggested-by: Sudeep Holla <sudeep.holla-5wv7dgnIgG8@public.gmane.org>
> Fixes: 7e5930aaef5d ('ARM: 8622/3: add sysfs cpu_capacity attribute')
> Signed-off-by: Juri Lelli <juri.lelli-5wv7dgnIgG8@public.gmane.org>
Acked-by: Vincent Guittot <vincent.guittot-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> arch/arm/kernel/topology.c | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
> index 4e4af809606a..162c82aeed96 100644
> --- a/arch/arm/kernel/topology.c
> +++ b/arch/arm/kernel/topology.c
> @@ -57,7 +57,6 @@ static void set_capacity_scale(unsigned int cpu, unsigned long capacity)
> per_cpu(cpu_scale, cpu) = capacity;
> }
>
> -#ifdef CONFIG_PROC_SYSCTL
> static ssize_t cpu_capacity_show(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> @@ -114,7 +113,6 @@ static int register_cpu_capacity_sysctl(void)
> return 0;
> }
> subsys_initcall(register_cpu_capacity_sysctl);
> -#endif
>
> #ifdef CONFIG_OF
> struct cpu_efficiency {
> --
> 2.10.0
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox