* [PATCH v2] v4l: async: make v4l2 coexist with devicetree nodes in a dt overlay
From: Javi Merino @ 2016-12-05 10:09 UTC (permalink / raw)
To: Javier Martinez Canillas, Sakari Ailus
Cc: linux-media, linux-kernel, devicetree, Javi Merino,
Mauro Carvalho Chehab
In asds configured with V4L2_ASYNC_MATCH_OF, the v4l2 subdev can be
part of a devicetree overlay, for example:
&media_bridge {
...
my_port: port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
ep: endpoint@0 {
remote-endpoint = <&camera0>;
};
};
};
/ {
fragment@0 {
target = <&i2c0>;
__overlay__ {
my_cam {
compatible = "foo,bar";
port {
camera0: endpoint {
remote-endpoint = <&my_port>;
...
};
};
};
};
};
};
Each time the overlay is applied, its of_node pointer will be
different. We are not interested in matching the pointer, what we
want to match is that the path is the one we are expecting. Change to
use of_node_cmp() so that we continue matching after the overlay has
been removed and reapplied.
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: Javier Martinez Canillas <javier@osg.samsung.com>
Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Javi Merino <javi.merino@kernel.org>
---
drivers/media/v4l2-core/v4l2-async.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 5bada20..d33a17c 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -42,7 +42,8 @@ static bool match_devname(struct v4l2_subdev *sd,
static bool match_of(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
{
- return sd->of_node == asd->match.of.node;
+ return !of_node_cmp(of_node_full_name(sd->of_node),
+ of_node_full_name(asd->match.of.node));
}
static bool match_custom(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
--
2.1.4
^ permalink raw reply related
* Re: [PATCHv4 11/15] clk: ti: clockdomain: add clock provider support to clockdomains
From: Tero Kristo @ 2016-12-05 10:08 UTC (permalink / raw)
To: Tony Lindgren, Michael Turquette
Cc: devicetree, Stephen Boyd, Rob Herring, linux-omap, linux-clk,
linux-arm-kernel
In-Reply-To: <20161203001852.GI4705@atomide.com>
On 03/12/16 02:18, Tony Lindgren wrote:
> * Michael Turquette <mturquette@baylibre.com> [161202 15:52]:
>> Quoting Tony Lindgren (2016-12-02 15:12:40)
>>> * Michael Turquette <mturquette@baylibre.com> [161202 14:34]:
>>>> Quoting Tony Lindgren (2016-10-28 16:54:48)
>>>>> * Stephen Boyd <sboyd@codeaurora.org> [161028 16:37]:
>>>>>> On 10/28, Tony Lindgren wrote:
>>>>>>> * Tero Kristo <t-kristo@ti.com> [161028 00:43]:
>>>>>>>> On 28/10/16 03:50, Stephen Boyd wrote:
>>>>>>>>> I suppose a PRCM is
>>>>>>>>> like an MFD that has clocks and resets under it? On other
>>>>>>>>> platforms we've combined that all into one node and just had
>>>>>>>>> #clock-cells and #reset-cells in that node. Is there any reason
>>>>>>>>> we can't do that here?
>>>>>>>>
>>>>>>>> For OMAPs, there are typically multiple instances of the PRCM around; OMAP4
>>>>>>>> for example has:
>>>>>>>>
>>>>>>>> cm1 @ 0x4a004000 (clocks + clockdomains)
>>>>>>>> cm2 @ 0x4a008000 (clocks + clockdomains)
>>>>>>>> prm @ 0x4a306000 (few clocks + resets + power state handling)
>>>>>>>> scrm @ 0x4a30a000 (few external clocks + plenty of misc stuff)
>>>>>>>>
>>>>>>>> These instances are also under different power/voltage domains which means
>>>>>>>> their PM behavior is different.
>>>>>>>>
>>>>>>>> The idea behind having a clockdomain as a provider was mostly to have the
>>>>>>>> topology visible : prcm-instance -> clockdomain -> clocks
>>>>>>>
>>>>>>> Yeah that's needed to get the interconnect hierarchy right for
>>>>>>> genpd :)
>>>>>>>
>>>>>>>> ... but basically I think it would be possible to drop the clockdomain
>>>>>>>> representation and just mark the prcm-instance as a clock provider. Tony,
>>>>>>>> any thoughts on that?
>>>>>>>
>>>>>>> No let's not drop the clockdomains as those will be needed when we
>>>>>>> move things into proper hierarchy within the interconnect instances.
>>>>>>> This will then help with getting things right with genpd.
>>>>>>>
>>>>>>> In the long run we just want to specify clockdomain and the offset of
>>>>>>> the clock instance within the clockdomain in the dts files.
>>>>>>>
>>>>>>
>>>>>> Sorry, I have very little idea how OMAP hardware works. Do you
>>>>>> mean that you will have different nodes for each clockdomain so
>>>>>> that genpd can map 1:1 to the node in dts? But in hardware
>>>>>> there's a prcm that allows us to control many clock domains
>>>>>> through register read/writes? How is the interconnect involved?
>>>>>
>>>>> There are multiple clockdomains, at least one for each interconnect
>>>>> instance. Once a clockdomain is idle, the related interconnect can
>>>>> idle too. So yeah genpd pretty much maps 1:1 with the clockdomains.
>>>>>
>>>>> There's more info in for example omap4 TRM section "3.4.1 Device
>>>>> Power-Management Layout" that shows the voltage/power/clock domains.
>>>>> The interconnect instances are mostly named there too looking at
>>>>> the L4/L3 naming.
>>>>
>>>> I'm confused on two points:
>>>>
>>>> 1) why are the clkdm's acting as clock providers? I've always hated the
>>>> name "clock domain" since those bits are for managing module state, not
>>>> clock state. The PRM, CM1 and CM2 provide the clocks, not the
>>>> clockdomains.
>>>
>>> The clock domains have multiple clock inputs that are routed to multiple
>>> child clocks. So it is a clock :)
>>>
>>> See for example omap4430 TRM "3.6.4 CD_WKUP Clock Domain" on page
>>> 393 in my revision here.
>>>
>>> On that page "Figure 3-48" shows CD_WKUP with the four input clocks.
>>> And then "Table 3-84. CD_WKUP Control and Status Parameters" shows
>>> the CD_WKUP clock domain specific registers. These registers show
>>> the status, I think they are all read-only registers. Then CD_WKUP
>>> has multiple child clocks with configurable registers.
>>>
>>> From hardware register point of view, each clock domain has:
>>>
>>> - Read-only clockdomain status registers in the beginning of
>>> the address space
>>>
>>> - Multiple similar clock instances register instances each
>>> mapping to a specific interconnect target module
>>>
>>> These are documented in "3.11.16.1 WKUP_CM Register Summary".
>>
>> Oh, this is because you are treating the MODULEMODE bits like gate
>> clocks. I never really figured out if this was the best way to model
>> those bits since they do more than control a line toggling at a rate.
>> For instance this bit will affect the master/slave IDLE protocol between
>> the module and the PRCM.
>
> Yes seems like there is some negotiation going on there with the
> target module. But from practical point of view the CLKCTRL
> register is the gate for a module functional clock.
There's some confusion on this, clockdomain is effectively a collection
of clocks, and can be used to force control that collection if needed.
Chapter "3.1.1.1.3 Clock Domain" in some OMAP4 TRM shows the
relationship neatly.
>
>>> From hardware point of view, we ideally want to map interconnect
>>> target modules to the clock instance offset from the clock domain
>>> for that interconnect segment. For example gptimer1 clocks would
>>> be just:
>>>
>>> clocks = <&cd_wkup 0x40>;
>>>
>>>> 2) why aren't the clock domains modeled as genpds with their associated
>>>> devices attached to them? Note that it is possible to "nest" genpd
>>>> objects. This would also allow for the "Clockdomain Dependency"
>>>> relationships to be properly modeled (see section 3.1.1.1.7 Clock Domain
>>>> Dependency in the OMAP4 TRM).
>>>
>>> Clock domains only route clocks to child clocks. Power domains
>>> are different registers. The power domains map roughly to
>>> interconnect instances, there we have registers to disable the
>>> whole interconnect when idle.
>>
>> I'm not talking about power islands at all, but the genpd object in
>> Linux. For instance, if we treat each clock domain like a clock
>> provider, how could the functional dependency between clkdm_A and
>> clkdm_B be asserted?
>
> To me it seems that some output of a clockdomain is just a input
> of another clockdomain? So it's just the usual parent child
> relationship once we treat a clockdomain just as a clock. Tero
> probably has some input here.
A clockdomain should be modelled as a genpd, that I agree. However, it
doesn't prevent it from being a clock provider also, or does it?
>> There is certainly no API for that in the clock framework, but for genpd
>> your runtime_pm_get() callback for clkdm_A could call runtime_pm_get
>> against clkdm_B, which would satisfy the requirement. See section
>> 3.1.1.1.7 Clock Domain Dependency in the OMAP4 TRM, version AB.
For static dependencies the apis genpd_add/remove_subdomain could
probably be used.
> To me it seems the API is just clk_get() :) Do you have some
> specific example we can use to check? My guess is that the
> TRM "Clock Domain Dependency" is just the usual parent child
> relationship between clocks that are the clockdomains..
>
> If there is something more magical there certainly that should
> be considered though.
The hwmods could be transformed to individual genpds also I guess. On DT
level though, we would still need a clock pointer to the main clock and
a genpd pointer in addition to that.
Tony, any thoughts on that? Would this break up the plans for the
interconnect completely?
-Tero
^ permalink raw reply
* Re: [PATCH 2/8] dt-bindings: document the STM32 RTC bindings
From: Alexandre Belloni @ 2016-12-05 10:06 UTC (permalink / raw)
To: Amelie Delaunay
Cc: a.zummo-BfzFCNDTiLLj+vYz1yj4TQ, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w,
alexandre.torgue-qxv4g6HH51o, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
rtc-linux-/JYPxA39Uh5TLH3MbocFFw,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
gabriel.fernandez-qxv4g6HH51o
In-Reply-To: <1480687801-19525-4-git-send-email-amelie.delaunay-qxv4g6HH51o@public.gmane.org>
Hi,
On 02/12/2016 at 15:09:55 +0100, Amelie Delaunay wrote :
> This patch adds documentation of device tree bindings for the STM32 RTC.
>
> Signed-off-by: Amelie Delaunay <amelie.delaunay-qxv4g6HH51o@public.gmane.org>
> ---
> .../devicetree/bindings/rtc/st,stm32-rtc.txt | 31 ++++++++++++++++++++++
> 1 file changed, 31 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
>
> diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
> new file mode 100644
> index 0000000..4578838
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
> @@ -0,0 +1,31 @@
> +STM32 Real Time Clock
> +
> +Required properties:
> +- compatible: "st,stm32-rtc".
> +- reg: address range of rtc register set.
> +- clocks: reference to the clock entry ck_rtc.
> +- clock-names: name of the clock used. Should be "ck_rtc".
Is this name really useful?
> +- interrupt-parent: phandle for the interrupt controller.
> +- interrupts: rtc alarm interrupt.
> +- interrupt-names: rtc alarm interrupt name, should be "alarm".
Same comment, is this name really useful?
--
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply
* Re: [PATCH 3/8] rtc: add STM32 RTC driver
From: Amelie DELAUNAY @ 2016-12-05 9:45 UTC (permalink / raw)
To: Mathieu Poirier
Cc: a.zummo-BfzFCNDTiLLj+vYz1yj4TQ@public.gmane.org,
alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
mark.rutland-5wv7dgnIgG8@public.gmane.org,
mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
Alexandre TORGUE, linux-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org,
rtc-linux-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Gabriel FERNANDEZ
In-Reply-To: <20161202180527.GB3284-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On 12/02/2016 07:05 PM, Mathieu Poirier wrote:
> On Fri, Dec 02, 2016 at 03:09:56PM +0100, Amelie Delaunay wrote:
>> This patch adds support for the STM32 RTC.
>>
>> Signed-off-by: Amelie Delaunay <amelie.delaunay-qxv4g6HH51o@public.gmane.org>
>> ---
>> drivers/rtc/Kconfig | 10 +
>> drivers/rtc/Makefile | 1 +
>> drivers/rtc/rtc-stm32.c | 777 ++++++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 788 insertions(+)
>> create mode 100644 drivers/rtc/rtc-stm32.c
>>
>> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
>> index e859d14..dd8b218 100644
>> --- a/drivers/rtc/Kconfig
>> +++ b/drivers/rtc/Kconfig
>> @@ -1706,6 +1706,16 @@ config RTC_DRV_PIC32
>> This driver can also be built as a module. If so, the module
>> will be called rtc-pic32
>>
>> +config RTC_DRV_STM32
>> + tristate "STM32 On-Chip RTC"
>> + depends on ARCH_STM32
>> + help
>> + If you say yes here you get support for the STM32 On-Chip
>> + Real Time Clock.
>> +
>> + This driver can also be built as a module, if so, the module
>> + will be called "rtc-stm32".
>> +
>> comment "HID Sensor RTC drivers"
>>
>> config RTC_DRV_HID_SENSOR_TIME
>> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
>> index 1ac694a..87bd9cc 100644
>> --- a/drivers/rtc/Makefile
>> +++ b/drivers/rtc/Makefile
>> @@ -144,6 +144,7 @@ obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o
>> obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o
>> obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
>> obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
>> +obj-$(CONFIG_RTC_DRV_STM32) += rtc-stm32.o
>> obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o
>> obj-$(CONFIG_RTC_DRV_ST_LPC) += rtc-st-lpc.o
>> obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o
>> diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
>> new file mode 100644
>> index 0000000..9e710ff
>> --- /dev/null
>> +++ b/drivers/rtc/rtc-stm32.c
>> @@ -0,0 +1,777 @@
>> +/*
>> + * Copyright (C) Amelie Delaunay 2015
>> + * Author: Amelie Delaunay <adelaunay.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> + * License terms: GNU General Public License (GPL), version 2
>> + */
>> +
>> +#include <linux/bcd.h>
>> +#include <linux/clk.h>
>> +#include <linux/init.h>
>> +#include <linux/io.h>
>> +#include <linux/iopoll.h>
>> +#include <linux/ioport.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/regmap.h>
>> +#include <linux/rtc.h>
>> +#include <linux/spinlock.h>
>> +
>> +#define DRIVER_NAME "stm32_rtc"
>> +
>> +/* STM32 RTC registers */
>> +#define STM32_RTC_TR 0x00
>> +#define STM32_RTC_DR 0x04
>> +#define STM32_RTC_CR 0x08
>> +#define STM32_RTC_ISR 0x0C
>> +#define STM32_RTC_PRER 0x10
>> +#define STM32_RTC_ALRMAR 0x1C
>> +#define STM32_RTC_WPR 0x24
>> +
>> +/* STM32_RTC_TR bit fields */
>> +#define STM32_RTC_TR_SEC_SHIFT 0
>> +#define STM32_RTC_TR_SEC GENMASK(6, 0)
>> +#define STM32_RTC_TR_MIN_SHIFT 8
>> +#define STM32_RTC_TR_MIN GENMASK(14, 8)
>> +#define STM32_RTC_TR_HOUR_SHIFT 16
>> +#define STM32_RTC_TR_HOUR GENMASK(21, 16)
>> +
>> +/* STM32_RTC_DR bit fields */
>> +#define STM32_RTC_DR_DATE_SHIFT 0
>> +#define STM32_RTC_DR_DATE GENMASK(5, 0)
>> +#define STM32_RTC_DR_MONTH_SHIFT 8
>> +#define STM32_RTC_DR_MONTH GENMASK(11, 8)
>> +#define STM32_RTC_DR_WDAY_SHIFT 13
>> +#define STM32_RTC_DR_WDAY GENMASK(15, 13)
>> +#define STM32_RTC_DR_YEAR_SHIFT 16
>> +#define STM32_RTC_DR_YEAR GENMASK(23, 16)
>> +
>> +/* STM32_RTC_CR bit fields */
>> +#define STM32_RTC_CR_FMT BIT(6)
>> +#define STM32_RTC_CR_ALRAE BIT(8)
>> +#define STM32_RTC_CR_ALRAIE BIT(12)
>> +
>> +/* STM32_RTC_ISR bit fields */
>> +#define STM32_RTC_ISR_ALRAWF BIT(0)
>> +#define STM32_RTC_ISR_INITS BIT(4)
>> +#define STM32_RTC_ISR_RSF BIT(5)
>> +#define STM32_RTC_ISR_INITF BIT(6)
>> +#define STM32_RTC_ISR_INIT BIT(7)
>> +#define STM32_RTC_ISR_ALRAF BIT(8)
>> +
>> +/* STM32_RTC_PRER bit fields */
>> +#define STM32_RTC_PRER_PRED_S_SHIFT 0
>> +#define STM32_RTC_PRER_PRED_S GENMASK(14, 0)
>> +#define STM32_RTC_PRER_PRED_A_SHIFT 16
>> +#define STM32_RTC_PRER_PRED_A GENMASK(22, 16)
>> +
>> +/* STM32_RTC_ALRMAR and STM32_RTC_ALRMBR bit fields */
>> +#define STM32_RTC_ALRMXR_SEC_SHIFT 0
>> +#define STM32_RTC_ALRMXR_SEC GENMASK(6, 0)
>> +#define STM32_RTC_ALRMXR_SEC_MASK BIT(7)
>> +#define STM32_RTC_ALRMXR_MIN_SHIFT 8
>> +#define STM32_RTC_ALRMXR_MIN GENMASK(14, 8)
>> +#define STM32_RTC_ALRMXR_MIN_MASK BIT(15)
>> +#define STM32_RTC_ALRMXR_HOUR_SHIFT 16
>> +#define STM32_RTC_ALRMXR_HOUR GENMASK(21, 16)
>> +#define STM32_RTC_ALRMXR_PM BIT(22)
>> +#define STM32_RTC_ALRMXR_HOUR_MASK BIT(23)
>> +#define STM32_RTC_ALRMXR_DATE_SHIFT 24
>> +#define STM32_RTC_ALRMXR_DATE GENMASK(29, 24)
>> +#define STM32_RTC_ALRMXR_WDSEL BIT(30)
>> +#define STM32_RTC_ALRMXR_WDAY_SHIFT 24
>> +#define STM32_RTC_ALRMXR_WDAY GENMASK(27, 24)
>> +#define STM32_RTC_ALRMXR_DATE_MASK BIT(31)
>> +
>> +/* STM32_RTC_WPR key constants */
>> +#define RTC_WPR_1ST_KEY 0xCA
>> +#define RTC_WPR_2ND_KEY 0x53
>> +#define RTC_WPR_WRONG_KEY 0xFF
>> +
>> +/*
>> + * RTC registers are protected agains parasitic write access.
>> + * PWR_CR_DBP bit must be set to enable write access to RTC registers.
>> + */
>> +/* STM32_PWR_CR */
>> +#define PWR_CR 0x00
>> +/* STM32_PWR_CR bit field */
>> +#define PWR_CR_DBP BIT(8)
>> +
>> +static struct regmap *dbp;
>> +
>> +struct stm32_rtc {
>> + struct rtc_device *rtc_dev;
>> + void __iomem *base;
>> + struct clk *pclk;
>> + struct clk *ck_rtc;
>> + unsigned int clksrc;
>> + spinlock_t lock; /* Protects registers accesses */
>> + int irq_alarm;
>> + struct regmap *pwrcr;
>> +};
>
> One more thing... What did you want to do with pclk, clksrc and pwrcr? They
> aren't used in the driver. If this is for future enhancement I suggest you
> introduce those when you submit the patches.
You're right.
>
>> +
>> +static inline unsigned int stm32_rtc_readl(struct stm32_rtc *rtc,
>> + unsigned int offset)
>> +{
>> + return readl_relaxed(rtc->base + offset);
>> +}
>> +
>> +static inline void stm32_rtc_writel(struct stm32_rtc *rtc,
>> + unsigned int offset, unsigned int value)
>> +{
>> + writel_relaxed(value, rtc->base + offset);
>> +}
>> +
>> +static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)
>> +{
>> +// if (dbp)
>> +// regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
>> +
>> + stm32_rtc_writel(rtc, STM32_RTC_WPR, RTC_WPR_1ST_KEY);
>> + stm32_rtc_writel(rtc, STM32_RTC_WPR, RTC_WPR_2ND_KEY);
>> +}
>> +
>> +static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc)
>> +{
>> + stm32_rtc_writel(rtc, STM32_RTC_WPR, RTC_WPR_WRONG_KEY);
>> +
>> +// if (dbp)
>> +// regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
>> +}
>> +
>> +static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
>> +{
>> + unsigned int isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
>> +
>> + if (!(isr & STM32_RTC_ISR_INITF)) {
>> + isr |= STM32_RTC_ISR_INIT;
>> + stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
>> +
>> + return readl_relaxed_poll_timeout_atomic(
>> + rtc->base + STM32_RTC_ISR,
>> + isr, (isr & STM32_RTC_ISR_INITF),
>> + 10, 100000);
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static void stm32_rtc_exit_init_mode(struct stm32_rtc *rtc)
>> +{
>> + unsigned int isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
>> +
>> + isr &= ~STM32_RTC_ISR_INIT;
>> + stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
>> +}
>> +
>> +static int stm32_rtc_wait_sync(struct stm32_rtc *rtc)
>> +{
>> + unsigned int isr;
>> +
>> + isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
>> +
>> + isr &= ~STM32_RTC_ISR_RSF;
>> + stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
>> +
>> + /* Wait the registers to be synchronised */
>> + return readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
>> + isr,
>> + (isr & STM32_RTC_ISR_RSF),
>> + 10, 100000);
>> +}
>> +
>> +static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id)
>> +{
>> + struct stm32_rtc *rtc = (struct stm32_rtc *)dev_id;
>> + unsigned long irqflags, events = 0;
>> + unsigned int isr, cr;
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
>> + cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
>> +
>> + if ((isr & STM32_RTC_ISR_ALRAF) &&
>> + (cr & STM32_RTC_CR_ALRAIE)) {
>> + /* Alarm A flag - Alarm interrupt */
>> + events |= RTC_IRQF | RTC_AF;
>> + isr &= ~STM32_RTC_ISR_ALRAF;
>> + }
>> +
>> + /* Clear event irqflags, otherwise new events won't be received */
>> + stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + if (events) {
>> + dev_info(&rtc->rtc_dev->dev, "Alarm occurred\n");
>> +
>> + /* Pass event to the kernel */
>> + rtc_update_irq(rtc->rtc_dev, 1, events);
>> + return IRQ_HANDLED;
>> + } else {
>> + return IRQ_NONE;
>> + }
>> +}
>> +
>> +/* Convert rtc_time structure from bin to bcd format */
>> +static void tm2bcd(struct rtc_time *tm)
>> +{
>> + tm->tm_sec = bin2bcd(tm->tm_sec);
>> + tm->tm_min = bin2bcd(tm->tm_min);
>> + tm->tm_hour = bin2bcd(tm->tm_hour);
>> +
>> + tm->tm_mday = bin2bcd(tm->tm_mday);
>> + tm->tm_mon = bin2bcd(tm->tm_mon + 1);
>> + tm->tm_year = bin2bcd(tm->tm_year - 100);
>> + /*
>> + * Number of days since Sunday
>> + * - on kernel side, 0=Sunday...6=Saturday
>> + * - on rtc side, 0=invalid,1=Monday...7=Sunday
>> + */
>> + tm->tm_wday = (!tm->tm_wday) ? 7 : tm->tm_wday;
>> +}
>> +
>> +/* Convert rtc_time structure from bcd to bin format */
>> +static void bcd2tm(struct rtc_time *tm)
>> +{
>> + tm->tm_sec = bcd2bin(tm->tm_sec);
>> + tm->tm_min = bcd2bin(tm->tm_min);
>> + tm->tm_hour = bcd2bin(tm->tm_hour);
>> +
>> + tm->tm_mday = bcd2bin(tm->tm_mday);
>> + tm->tm_mon = bcd2bin(tm->tm_mon) - 1;
>> + tm->tm_year = bcd2bin(tm->tm_year) + 100;
>> + /*
>> + * Number of days since Sunday
>> + * - on kernel side, 0=Sunday...6=Saturday
>> + * - on rtc side, 0=invalid,1=Monday...7=Sunday
>> + */
>> + tm->tm_wday %= 7;
>> +}
>> +
>> +static int stm32_rtc_read_time(struct device *dev, struct rtc_time *tm)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> + unsigned int tr, dr;
>> + unsigned long irqflags;
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + /* Time and Date in BCD format */
>> + tr = stm32_rtc_readl(rtc, STM32_RTC_TR);
>> + dr = stm32_rtc_readl(rtc, STM32_RTC_DR);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + tm->tm_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT;
>> + tm->tm_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT;
>> + tm->tm_hour = (tr & STM32_RTC_TR_HOUR) >> STM32_RTC_TR_HOUR_SHIFT;
>> +
>> + tm->tm_mday = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT;
>> + tm->tm_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT;
>> + tm->tm_year = (dr & STM32_RTC_DR_YEAR) >> STM32_RTC_DR_YEAR_SHIFT;
>> + tm->tm_wday = (dr & STM32_RTC_DR_WDAY) >> STM32_RTC_DR_WDAY_SHIFT;
>> +
>> + /* We don't report tm_yday and tm_isdst */
>> +
>> + bcd2tm(tm);
>> +
>> + if (rtc_valid_tm(tm) < 0) {
>> + dev_err(dev, "%s: rtc_time is not valid.\n", __func__);
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int stm32_rtc_set_time(struct device *dev, struct rtc_time *tm)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> + unsigned int tr, dr;
>> + unsigned long irqflags;
>> + int ret = 0;
>> +
>> + if (rtc_valid_tm(tm) < 0) {
>> + dev_err(dev, "%s: rtc_time is not valid.\n", __func__);
>> + return -EINVAL;
>> + }
>> +
>> + tm2bcd(tm);
>> +
>> + /* Time in BCD format */
>> + tr = ((tm->tm_sec << STM32_RTC_TR_SEC_SHIFT) & STM32_RTC_TR_SEC) |
>> + ((tm->tm_min << STM32_RTC_TR_MIN_SHIFT) & STM32_RTC_TR_MIN) |
>> + ((tm->tm_hour << STM32_RTC_TR_HOUR_SHIFT) & STM32_RTC_TR_HOUR);
>> +
>> + /* Date in BCD format */
>> + dr = ((tm->tm_mday << STM32_RTC_DR_DATE_SHIFT) & STM32_RTC_DR_DATE) |
>> + ((tm->tm_mon << STM32_RTC_DR_MONTH_SHIFT) & STM32_RTC_DR_MONTH) |
>> + ((tm->tm_year << STM32_RTC_DR_YEAR_SHIFT) & STM32_RTC_DR_YEAR) |
>> + ((tm->tm_wday << STM32_RTC_DR_WDAY_SHIFT) & STM32_RTC_DR_WDAY);
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + stm32_rtc_wpr_unlock(rtc);
>> +
>> + ret = stm32_rtc_enter_init_mode(rtc);
>> + if (ret) {
>> + dev_err(dev, "Can't enter in init mode. Set time aborted.\n");
>> + goto end;
>> + }
>> +
>> + stm32_rtc_writel(rtc, STM32_RTC_TR, tr);
>> + stm32_rtc_writel(rtc, STM32_RTC_DR, dr);
>> +
>> + stm32_rtc_exit_init_mode(rtc);
>> +
>> + ret = stm32_rtc_wait_sync(rtc);
>> +end:
>> + stm32_rtc_wpr_lock(rtc);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + return ret;
>> +}
>> +
>> +static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> + struct rtc_time *tm = &alrm->time;
>> + unsigned int alrmar, cr, isr;
>> + unsigned long irqflags;
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + alrmar = stm32_rtc_readl(rtc, STM32_RTC_ALRMAR);
>> + cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
>> + isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + if (alrmar & STM32_RTC_ALRMXR_DATE_MASK) {
>> + /*
>> + * Date/day don't care in Alarm comparison so alarm triggers
>> + * every day
>> + */
>> + tm->tm_mday = -1;
>> + tm->tm_wday = -1;
>> + } else {
>> + if (alrmar & STM32_RTC_ALRMXR_WDSEL) {
>> + /* Alarm is set to a day of week */
>> + tm->tm_mday = -1;
>> + tm->tm_wday = (alrmar & STM32_RTC_ALRMXR_WDAY) >>
>> + STM32_RTC_ALRMXR_WDAY_SHIFT;
>> + tm->tm_wday %= 7;
>> + } else {
>> + /* Alarm is set to a day of month */
>> + tm->tm_wday = -1;
>> + tm->tm_mday = (alrmar & STM32_RTC_ALRMXR_DATE) >>
>> + STM32_RTC_ALRMXR_DATE_SHIFT;
>> + }
>> + }
>> +
>> + if (alrmar & STM32_RTC_ALRMXR_HOUR_MASK) {
>> + /* Hours don't care in Alarm comparison */
>> + tm->tm_hour = -1;
>> + } else {
>> + tm->tm_hour = (alrmar & STM32_RTC_ALRMXR_HOUR) >>
>> + STM32_RTC_ALRMXR_HOUR_SHIFT;
>> + if (alrmar & STM32_RTC_ALRMXR_PM)
>> + tm->tm_hour += 12;
>> + }
>> +
>> + if (alrmar & STM32_RTC_ALRMXR_MIN_MASK) {
>> + /* Minutes don't care in Alarm comparison */
>> + tm->tm_min = -1;
>> + } else {
>> + tm->tm_min = (alrmar & STM32_RTC_ALRMXR_MIN) >>
>> + STM32_RTC_ALRMXR_MIN_SHIFT;
>> + }
>> +
>> + if (alrmar & STM32_RTC_ALRMXR_SEC_MASK) {
>> + /* Seconds don't care in Alarm comparison */
>> + tm->tm_sec = -1;
>> + } else {
>> + tm->tm_sec = (alrmar & STM32_RTC_ALRMXR_SEC) >>
>> + STM32_RTC_ALRMXR_SEC_SHIFT;
>> + }
>> +
>> + bcd2tm(tm);
>> +
>> + alrm->enabled = (cr & STM32_RTC_CR_ALRAE) ? 1 : 0;
>> + alrm->pending = (isr & STM32_RTC_ISR_ALRAF) ? 1 : 0;
>> +
>> + return 0;
>> +}
>> +
>> +static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> + unsigned long irqflags;
>> + unsigned int isr, cr;
>> +
>> + cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + stm32_rtc_wpr_unlock(rtc);
>> +
>> + /* We expose Alarm A to the kernel */
>> + if (enabled)
>> + cr |= (STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
>> + else
>> + cr &= ~(STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
>> + stm32_rtc_writel(rtc, STM32_RTC_CR, cr);
>> +
>> + /* Clear event irqflags, otherwise new events won't be received */
>> + isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
>> + isr &= ~STM32_RTC_ISR_ALRAF;
>> + stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
>> +
>> + stm32_rtc_wpr_lock(rtc);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + return 0;
>> +}
>> +
>> +static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> + struct rtc_time *tm = &alrm->time;
>> + unsigned long irqflags;
>> + unsigned int cr, isr, alrmar;
>> + int ret = 0;
>> +
>> + if (rtc_valid_tm(tm)) {
>> + dev_err(dev, "Alarm time not valid.\n");
>> + return -EINVAL;
>> + }
>> +
>> + tm2bcd(tm);
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + stm32_rtc_wpr_unlock(rtc);
>> +
>> + /* Disable Alarm */
>> + cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
>> + cr &= ~STM32_RTC_CR_ALRAE;
>> + stm32_rtc_writel(rtc, STM32_RTC_CR, cr);
>> +
>> + /* Poll Alarm write flag to be sure that Alarm update is allowed */
>> + ret = readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
>> + isr,
>> + (isr & STM32_RTC_ISR_ALRAWF),
>> + 10, 100);
>> +
>> + if (ret) {
>> + dev_err(dev, "Alarm update not allowed\n");
>> + goto end;
>> + }
>> +
>> + alrmar = 0;
>> +
>> + if (tm->tm_mday < 0 && tm->tm_wday < 0) {
>> + /*
>> + * Date/day don't care in Alarm comparison so alarm triggers
>> + * every day
>> + */
>> + alrmar |= STM32_RTC_ALRMXR_DATE_MASK;
>> + } else {
>> + if (tm->tm_mday > 0) {
>> + /* Date is selected (ignoring wday) */
>> + alrmar |= (tm->tm_mday << STM32_RTC_ALRMXR_DATE_SHIFT) &
>> + STM32_RTC_ALRMXR_DATE;
>> + } else {
>> + /* Day of week is selected */
>> + int wday = (tm->tm_wday == 0) ? 7 : tm->tm_wday;
>> +
>> + alrmar |= STM32_RTC_ALRMXR_WDSEL;
>> + alrmar |= (wday << STM32_RTC_ALRMXR_WDAY_SHIFT) &
>> + STM32_RTC_ALRMXR_WDAY;
>> + }
>> + }
>> +
>> + if (tm->tm_hour < 0) {
>> + /* Hours don't care in Alarm comparison */
>> + alrmar |= STM32_RTC_ALRMXR_HOUR_MASK;
>> + } else {
>> + /* 24-hour format */
>> + alrmar &= ~STM32_RTC_ALRMXR_PM;
>> + alrmar |= (tm->tm_hour << STM32_RTC_ALRMXR_HOUR_SHIFT) &
>> + STM32_RTC_ALRMXR_HOUR;
>> + }
>> +
>> + if (tm->tm_min < 0) {
>> + /* Minutes don't care in Alarm comparison */
>> + alrmar |= STM32_RTC_ALRMXR_MIN_MASK;
>> + } else {
>> + alrmar |= (tm->tm_min << STM32_RTC_ALRMXR_MIN_SHIFT) &
>> + STM32_RTC_ALRMXR_MIN;
>> + }
>> +
>> + if (tm->tm_sec < 0) {
>> + /* Seconds don't care in Alarm comparison */
>> + alrmar |= STM32_RTC_ALRMXR_SEC_MASK;
>> + } else {
>> + alrmar |= (tm->tm_sec << STM32_RTC_ALRMXR_SEC_SHIFT) &
>> + STM32_RTC_ALRMXR_SEC;
>> + }
>> +
>> + /* Write to Alarm register */
>> + stm32_rtc_writel(rtc, STM32_RTC_ALRMAR, alrmar);
>> +
>> + if (alrm->enabled)
>> + stm32_rtc_alarm_irq_enable(dev, 1);
>> + else
>> + stm32_rtc_alarm_irq_enable(dev, 0);
>> +
>> +end:
>> + stm32_rtc_wpr_lock(rtc);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + return ret;
>> +}
>> +
>> +static const struct rtc_class_ops stm32_rtc_ops = {
>> + .read_time = stm32_rtc_read_time,
>> + .set_time = stm32_rtc_set_time,
>> + .read_alarm = stm32_rtc_read_alarm,
>> + .set_alarm = stm32_rtc_set_alarm,
>> + .alarm_irq_enable = stm32_rtc_alarm_irq_enable,
>> +};
>> +
>> +#ifdef CONFIG_OF
>> +static const struct of_device_id stm32_rtc_of_match[] = {
>> + { .compatible = "st,stm32-rtc" },
>> + {}
>> +};
>> +MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
>> +#endif
>> +
>> +static int stm32_rtc_init(struct platform_device *pdev,
>> + struct stm32_rtc *rtc)
>> +{
>> + unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr;
>> + unsigned int rate;
>> + unsigned long irqflags;
>> + int ret = 0;
>> +
>> + rate = clk_get_rate(rtc->ck_rtc);
>> +
>> + /* Find prediv_a and prediv_s to obtain the 1Hz calendar clock */
>> + pred_a_max = STM32_RTC_PRER_PRED_A >> STM32_RTC_PRER_PRED_A_SHIFT;
>> + pred_s_max = STM32_RTC_PRER_PRED_S >> STM32_RTC_PRER_PRED_S_SHIFT;
>> +
>> + for (pred_a = pred_a_max; pred_a >= 0; pred_a--) {
>> + pred_s = (rate / (pred_a + 1)) - 1;
>> +
>> + if (((pred_s + 1) * (pred_a + 1)) == rate)
>> + break;
>> + }
>> +
>> + /*
>> + * Can't find a 1Hz, so give priority to RTC power consumption
>> + * by choosing the higher possible value for prediv_a
>> + */
>> + if ((pred_s > pred_s_max) || (pred_a > pred_a_max)) {
>> + pred_a = pred_a_max;
>> + pred_s = (rate / (pred_a + 1)) - 1;
>> +
>> + dev_warn(&pdev->dev, "ck_rtc is %s\n",
>> + (rate - ((pred_a + 1) * (pred_s + 1)) < 0) ?
>> + "fast" : "slow");
>> + }
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + stm32_rtc_wpr_unlock(rtc);
>> +
>> + ret = stm32_rtc_enter_init_mode(rtc);
>> + if (ret) {
>> + dev_err(&pdev->dev,
>> + "Can't enter in init mode. Prescaler config failed.\n");
>> + goto end;
>> + }
>> +
>> + prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) & STM32_RTC_PRER_PRED_S;
>> + stm32_rtc_writel(rtc, STM32_RTC_PRER, prer);
>> + prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) & STM32_RTC_PRER_PRED_A;
>> + stm32_rtc_writel(rtc, STM32_RTC_PRER, prer);
>> +
>> + /* Force 24h time format */
>> + cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
>> + cr &= ~STM32_RTC_CR_FMT;
>> + stm32_rtc_writel(rtc, STM32_RTC_CR, cr);
>> +
>> + stm32_rtc_exit_init_mode(rtc);
>> +
>> + ret = stm32_rtc_wait_sync(rtc);
>> +
>> + if (stm32_rtc_readl(rtc, STM32_RTC_ISR) & STM32_RTC_ISR_INITS)
>> + dev_warn(&pdev->dev, "Date/Time must be initialized\n");
>> +end:
>> + stm32_rtc_wpr_lock(rtc);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + return ret;
>> +}
>> +
>> +static int stm32_rtc_probe(struct platform_device *pdev)
>> +{
>> + struct stm32_rtc *rtc;
>> + struct resource *res;
>> + int ret;
>> +
>> + rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
>> + if (!rtc)
>> + return -ENOMEM;
>> +
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + rtc->base = devm_ioremap_resource(&pdev->dev, res);
>> + if (IS_ERR(rtc->base))
>> + return PTR_ERR(rtc->base);
>> +
>> + dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "st,syscfg");
>> + if (IS_ERR(dbp)) {
>> + dev_err(&pdev->dev, "no st,syscfg\n");
>> + return PTR_ERR(dbp);
>> + }
>> +
>> + spin_lock_init(&rtc->lock);
>> +
>> + rtc->ck_rtc = devm_clk_get(&pdev->dev, "ck_rtc");
>> + if (IS_ERR(rtc->ck_rtc)) {
>> + dev_err(&pdev->dev, "no ck_rtc clock");
>> + return PTR_ERR(rtc->ck_rtc);
>> + }
>> +
>> + ret = clk_prepare_enable(rtc->ck_rtc);
>> + if (ret)
>> + return ret;
>> +
>> + if (dbp)
>> + regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
>> +
>> + ret = stm32_rtc_init(pdev, rtc);
>> + if (ret)
>> + goto err;
>> +
>> + rtc->irq_alarm = platform_get_irq_byname(pdev, "alarm");
>> + if (rtc->irq_alarm <= 0) {
>> + dev_err(&pdev->dev, "no alarm irq\n");
>> + ret = -ENOENT;
>> + goto err;
>> + }
>> +
>> + platform_set_drvdata(pdev, rtc);
>> +
>> + device_init_wakeup(&pdev->dev, true);
>> +
>> + rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
>> + &stm32_rtc_ops, THIS_MODULE);
>> + if (IS_ERR(rtc->rtc_dev)) {
>> + ret = PTR_ERR(rtc->rtc_dev);
>> + dev_err(&pdev->dev, "rtc device registration failed, err=%d\n",
>> + ret);
>> + goto err;
>> + }
>> +
>> + /* Handle RTC alarm interrupts */
>> + ret = devm_request_irq(&pdev->dev, rtc->irq_alarm,
>> + stm32_rtc_alarm_irq, IRQF_TRIGGER_RISING,
>> + dev_name(&rtc->rtc_dev->dev), rtc);
>> + if (ret) {
>> + dev_err(&pdev->dev, "IRQ%d (alarm interrupt) already claimed\n",
>> + rtc->irq_alarm);
>> + goto err;
>> + }
>> +
>> + return 0;
>> +err:
>> + clk_disable_unprepare(rtc->ck_rtc);
>> +
>> + if (dbp)
>> + regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
>> +
>> + device_init_wakeup(&pdev->dev, false);
>> +
>> + return ret;
>> +}
>> +
>> +static int __exit stm32_rtc_remove(struct platform_device *pdev)
>> +{
>> + struct stm32_rtc *rtc = platform_get_drvdata(pdev);
>> + unsigned int cr;
>> +
>> + /* Disable interrupts */
>> + stm32_rtc_wpr_unlock(rtc);
>> + cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
>> + cr &= ~STM32_RTC_CR_ALRAIE;
>> + stm32_rtc_writel(rtc, STM32_RTC_CR, cr);
>> + stm32_rtc_wpr_lock(rtc);
>> +
>> + clk_disable_unprepare(rtc->ck_rtc);
>> +
>> + /* Enable backup domain write protection */
>> + if (dbp)
>> + regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
>> +
>> + device_init_wakeup(&pdev->dev, false);
>> +
>> + return 0;
>> +}
>> +
>> +#ifdef CONFIG_PM_SLEEP
>> +static int stm32_rtc_suspend(struct device *dev)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> +
>> + if (device_may_wakeup(dev))
>> + return enable_irq_wake(rtc->irq_alarm);
>> +
>> + return 0;
>> +}
>> +
>> +static int stm32_rtc_resume(struct device *dev)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> + int ret = 0;
>> +
>> + ret = stm32_rtc_wait_sync(rtc);
>> + if (ret < 0)
>> + return ret;
>> +
>> + if (device_may_wakeup(dev))
>> + return disable_irq_wake(rtc->irq_alarm);
>> +
>> + return ret;
>> +}
>> +#endif
>> +
>> +static SIMPLE_DEV_PM_OPS(stm32_rtc_pm_ops,
>> + stm32_rtc_suspend, stm32_rtc_resume);
>> +
>> +static struct platform_driver stm32_rtc_driver = {
>> + .probe = stm32_rtc_probe,
>> + .remove = stm32_rtc_remove,
>> + .driver = {
>> + .name = DRIVER_NAME,
>> + .pm = &stm32_rtc_pm_ops,
>> + .of_match_table = stm32_rtc_of_match,
>> + },
>> +};
>> +
>> +module_platform_driver(stm32_rtc_driver);
>> +
>> +MODULE_ALIAS("platform:" DRIVER_NAME);
>> +MODULE_AUTHOR("Amelie Delaunay <amelie.delaunay-qxv4g6HH51o@public.gmane.org>");
>> +MODULE_DESCRIPTION("STMicroelectronics STM32 Real Time Clock driver");
>> +MODULE_LICENSE("GPL v2");
>> --
>> 1.9.1
>>
Best regards,
Amelie
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply
* Re: [PATCH 3/8] rtc: add STM32 RTC driver
From: Amelie DELAUNAY @ 2016-12-05 9:43 UTC (permalink / raw)
To: Mathieu Poirier
Cc: a.zummo-BfzFCNDTiLLj+vYz1yj4TQ@public.gmane.org,
alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
mark.rutland-5wv7dgnIgG8@public.gmane.org,
mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
Alexandre TORGUE, linux-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org,
rtc-linux-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Gabriel FERNANDEZ
In-Reply-To: <20161202175646.GA3284-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Hi Mathieu,
Thanks for reviewing
On 12/02/2016 06:56 PM, Mathieu Poirier wrote:
> On Fri, Dec 02, 2016 at 03:09:56PM +0100, Amelie Delaunay wrote:
>> This patch adds support for the STM32 RTC.
>
> Hello Amelie,
>
>>
>> Signed-off-by: Amelie Delaunay <amelie.delaunay-qxv4g6HH51o@public.gmane.org>
>> ---
>> drivers/rtc/Kconfig | 10 +
>> drivers/rtc/Makefile | 1 +
>> drivers/rtc/rtc-stm32.c | 777
++++++++++++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 788 insertions(+)
>> create mode 100644 drivers/rtc/rtc-stm32.c
>>
>> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
>> index e859d14..dd8b218 100644
>> --- a/drivers/rtc/Kconfig
>> +++ b/drivers/rtc/Kconfig
>> @@ -1706,6 +1706,16 @@ config RTC_DRV_PIC32
>> This driver can also be built as a module. If so, the module
>> will be called rtc-pic32
>>
>> +config RTC_DRV_STM32
>> + tristate "STM32 On-Chip RTC"
>> + depends on ARCH_STM32
>> + help
>> + If you say yes here you get support for the STM32 On-Chip
>> + Real Time Clock.
>> +
>> + This driver can also be built as a module, if so, the module
>> + will be called "rtc-stm32".
>> +
>> comment "HID Sensor RTC drivers"
>>
>> config RTC_DRV_HID_SENSOR_TIME
>> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
>> index 1ac694a..87bd9cc 100644
>> --- a/drivers/rtc/Makefile
>> +++ b/drivers/rtc/Makefile
>> @@ -144,6 +144,7 @@ obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o
>> obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o
>> obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
>> obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
>> +obj-$(CONFIG_RTC_DRV_STM32) += rtc-stm32.o
>> obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o
>> obj-$(CONFIG_RTC_DRV_ST_LPC) += rtc-st-lpc.o
>> obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o
>> diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
>> new file mode 100644
>> index 0000000..9e710ff
>> --- /dev/null
>> +++ b/drivers/rtc/rtc-stm32.c
>> @@ -0,0 +1,777 @@
>> +/*
>> + * Copyright (C) Amelie Delaunay 2015
>> + * Author: Amelie Delaunay <adelaunay.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> + * License terms: GNU General Public License (GPL), version 2
>> + */
>> +
>> +#include <linux/bcd.h>
>> +#include <linux/clk.h>
>> +#include <linux/init.h>
>> +#include <linux/io.h>
>> +#include <linux/iopoll.h>
>> +#include <linux/ioport.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/regmap.h>
>> +#include <linux/rtc.h>
>> +#include <linux/spinlock.h>
>> +
>> +#define DRIVER_NAME "stm32_rtc"
>> +
>> +/* STM32 RTC registers */
>> +#define STM32_RTC_TR 0x00
>> +#define STM32_RTC_DR 0x04
>> +#define STM32_RTC_CR 0x08
>> +#define STM32_RTC_ISR 0x0C
>> +#define STM32_RTC_PRER 0x10
>> +#define STM32_RTC_ALRMAR 0x1C
>> +#define STM32_RTC_WPR 0x24
>> +
>> +/* STM32_RTC_TR bit fields */
>> +#define STM32_RTC_TR_SEC_SHIFT 0
>> +#define STM32_RTC_TR_SEC GENMASK(6, 0)
>> +#define STM32_RTC_TR_MIN_SHIFT 8
>> +#define STM32_RTC_TR_MIN GENMASK(14, 8)
>> +#define STM32_RTC_TR_HOUR_SHIFT 16
>> +#define STM32_RTC_TR_HOUR GENMASK(21, 16)
>> +
>> +/* STM32_RTC_DR bit fields */
>> +#define STM32_RTC_DR_DATE_SHIFT 0
>> +#define STM32_RTC_DR_DATE GENMASK(5, 0)
>> +#define STM32_RTC_DR_MONTH_SHIFT 8
>> +#define STM32_RTC_DR_MONTH GENMASK(11, 8)
>> +#define STM32_RTC_DR_WDAY_SHIFT 13
>> +#define STM32_RTC_DR_WDAY GENMASK(15, 13)
>> +#define STM32_RTC_DR_YEAR_SHIFT 16
>> +#define STM32_RTC_DR_YEAR GENMASK(23, 16)
>> +
>> +/* STM32_RTC_CR bit fields */
>> +#define STM32_RTC_CR_FMT BIT(6)
>> +#define STM32_RTC_CR_ALRAE BIT(8)
>> +#define STM32_RTC_CR_ALRAIE BIT(12)
>> +
>> +/* STM32_RTC_ISR bit fields */
>> +#define STM32_RTC_ISR_ALRAWF BIT(0)
>> +#define STM32_RTC_ISR_INITS BIT(4)
>> +#define STM32_RTC_ISR_RSF BIT(5)
>> +#define STM32_RTC_ISR_INITF BIT(6)
>> +#define STM32_RTC_ISR_INIT BIT(7)
>> +#define STM32_RTC_ISR_ALRAF BIT(8)
>> +
>> +/* STM32_RTC_PRER bit fields */
>> +#define STM32_RTC_PRER_PRED_S_SHIFT 0
>> +#define STM32_RTC_PRER_PRED_S GENMASK(14, 0)
>> +#define STM32_RTC_PRER_PRED_A_SHIFT 16
>> +#define STM32_RTC_PRER_PRED_A GENMASK(22, 16)
>> +
>> +/* STM32_RTC_ALRMAR and STM32_RTC_ALRMBR bit fields */
>> +#define STM32_RTC_ALRMXR_SEC_SHIFT 0
>> +#define STM32_RTC_ALRMXR_SEC GENMASK(6, 0)
>> +#define STM32_RTC_ALRMXR_SEC_MASK BIT(7)
>> +#define STM32_RTC_ALRMXR_MIN_SHIFT 8
>> +#define STM32_RTC_ALRMXR_MIN GENMASK(14, 8)
>> +#define STM32_RTC_ALRMXR_MIN_MASK BIT(15)
>> +#define STM32_RTC_ALRMXR_HOUR_SHIFT 16
>> +#define STM32_RTC_ALRMXR_HOUR GENMASK(21, 16)
>> +#define STM32_RTC_ALRMXR_PM BIT(22)
>> +#define STM32_RTC_ALRMXR_HOUR_MASK BIT(23)
>> +#define STM32_RTC_ALRMXR_DATE_SHIFT 24
>> +#define STM32_RTC_ALRMXR_DATE GENMASK(29, 24)
>> +#define STM32_RTC_ALRMXR_WDSEL BIT(30)
>> +#define STM32_RTC_ALRMXR_WDAY_SHIFT 24
>> +#define STM32_RTC_ALRMXR_WDAY GENMASK(27, 24)
>> +#define STM32_RTC_ALRMXR_DATE_MASK BIT(31)
>> +
>> +/* STM32_RTC_WPR key constants */
>> +#define RTC_WPR_1ST_KEY 0xCA
>> +#define RTC_WPR_2ND_KEY 0x53
>> +#define RTC_WPR_WRONG_KEY 0xFF
>> +
>> +/*
>> + * RTC registers are protected agains parasitic write access.
>> + * PWR_CR_DBP bit must be set to enable write access to RTC registers.
>> + */
>> +/* STM32_PWR_CR */
>> +#define PWR_CR 0x00
>> +/* STM32_PWR_CR bit field */
>> +#define PWR_CR_DBP BIT(8)
>> +
>> +static struct regmap *dbp;
>> +
>> +struct stm32_rtc {
>> + struct rtc_device *rtc_dev;
>> + void __iomem *base;
>> + struct clk *pclk;
>> + struct clk *ck_rtc;
>> + unsigned int clksrc;
>> + spinlock_t lock; /* Protects registers accesses */
>> + int irq_alarm;
>> + struct regmap *pwrcr;
>> +};
>> +
>> +static inline unsigned int stm32_rtc_readl(struct stm32_rtc *rtc,
>> + unsigned int offset)
>> +{
>> + return readl_relaxed(rtc->base + offset);
>> +}
>> +
>> +static inline void stm32_rtc_writel(struct stm32_rtc *rtc,
>> + unsigned int offset, unsigned int value)
>> +{
>> + writel_relaxed(value, rtc->base + offset);
>> +}
>
> I'm not sure wrapping the readl/writel_relaxed function does anything
special
> other than simply redirecting the reader to another section of the code.
During development phase, it is useful to add debug traces but you're
right, this can be remove.
>
>> +
>> +static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)
>> +{
>> +// if (dbp)
>> +// regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
>
> Did checkpatch let you get away with this? What did you intend to do
here?
Hum, as surprising as it may seem, checkpatch didn't complained about
these comments! But anyway, this has to be removed, it was a tentative
to enable/disable backup domain write protection any time we have to
write in a protected RTC register, but it is not functionnal. I have
commented this just to keep it in mind and forget to remove it before
sending.
>
>> +
>> + stm32_rtc_writel(rtc, STM32_RTC_WPR, RTC_WPR_1ST_KEY);
>> + stm32_rtc_writel(rtc, STM32_RTC_WPR, RTC_WPR_2ND_KEY);
>> +}
>> +
>> +static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc)
>> +{
>> + stm32_rtc_writel(rtc, STM32_RTC_WPR, RTC_WPR_WRONG_KEY);
>> +
>> +// if (dbp)
>> +// regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
>> +}
>> +
>> +static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
>> +{
>> + unsigned int isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
>> +
>> + if (!(isr & STM32_RTC_ISR_INITF)) {
>> + isr |= STM32_RTC_ISR_INIT;
>> + stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
>> +
>> + return readl_relaxed_poll_timeout_atomic(
>> + rtc->base + STM32_RTC_ISR,
>> + isr, (isr & STM32_RTC_ISR_INITF),
>> + 10, 100000);
>
> When using hard coded numerics please add comments that explains the
reason
> behind the selected values.
Sure. It takes around 2 RTCCLK clock cycles to enter in initialization
phase mode. So it depends on the frequency of the ck_rtc parent clock.
Either I keep parent clock frequency and compute the exact timeout, or I
use the "best and worst cases": slowest RTCCLK frequency is 32kHz, so it
can take up to 62us, highest RTCCLK frequency should be 1MHz, so it can
take only 2us. Polling every 10us with a timeout of 100ms seemed
reasonable and be a good compromise.
>
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static void stm32_rtc_exit_init_mode(struct stm32_rtc *rtc)
>> +{
>> + unsigned int isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
>> +
>> + isr &= ~STM32_RTC_ISR_INIT;
>> + stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
>> +}
>> +
>> +static int stm32_rtc_wait_sync(struct stm32_rtc *rtc)
>> +{
>> + unsigned int isr;
>> +
>> + isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
>> +
>> + isr &= ~STM32_RTC_ISR_RSF;
>> + stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
>> +
>> + /* Wait the registers to be synchronised */
>> + return readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
>> + isr,
>> + (isr & STM32_RTC_ISR_RSF),
>> + 10, 100000);
>
> Shouldn't the break condition be !((isr & STM32_RTC_ISR_RSF) ? If
not this
> probably deserve a better comment.
RSF bit is set by hardware each time the calendar registers are
synchronized (it takes up to 2 RTCCLK). So the break condition is
correct: we poll until RSF flag is set or timeout is reached.
>
>> +}
>> +
>> +static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id)
>> +{
>> + struct stm32_rtc *rtc = (struct stm32_rtc *)dev_id;
>> + unsigned long irqflags, events = 0;
>> + unsigned int isr, cr;
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
>> + cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
>> +
>> + if ((isr & STM32_RTC_ISR_ALRAF) &&
>> + (cr & STM32_RTC_CR_ALRAIE)) {
>> + /* Alarm A flag - Alarm interrupt */
>> + events |= RTC_IRQF | RTC_AF;
>> + isr &= ~STM32_RTC_ISR_ALRAF;
>> + }
>> +
>> + /* Clear event irqflags, otherwise new events won't be received */
>> + stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + if (events) {
>> + dev_info(&rtc->rtc_dev->dev, "Alarm occurred\n");
>> +
>> + /* Pass event to the kernel */
>> + rtc_update_irq(rtc->rtc_dev, 1, events);
>> + return IRQ_HANDLED;
>> + } else {
>> + return IRQ_NONE;
>> + }
>> +}
>> +
>> +/* Convert rtc_time structure from bin to bcd format */
>> +static void tm2bcd(struct rtc_time *tm)
>> +{
>> + tm->tm_sec = bin2bcd(tm->tm_sec);
>> + tm->tm_min = bin2bcd(tm->tm_min);
>> + tm->tm_hour = bin2bcd(tm->tm_hour);
>> +
>> + tm->tm_mday = bin2bcd(tm->tm_mday);
>> + tm->tm_mon = bin2bcd(tm->tm_mon + 1);
>> + tm->tm_year = bin2bcd(tm->tm_year - 100);
>> + /*
>> + * Number of days since Sunday
>> + * - on kernel side, 0=Sunday...6=Saturday
>> + * - on rtc side, 0=invalid,1=Monday...7=Sunday
>> + */
>> + tm->tm_wday = (!tm->tm_wday) ? 7 : tm->tm_wday;
>> +}
>> +
>> +/* Convert rtc_time structure from bcd to bin format */
>> +static void bcd2tm(struct rtc_time *tm)
>> +{
>> + tm->tm_sec = bcd2bin(tm->tm_sec);
>> + tm->tm_min = bcd2bin(tm->tm_min);
>> + tm->tm_hour = bcd2bin(tm->tm_hour);
>> +
>> + tm->tm_mday = bcd2bin(tm->tm_mday);
>> + tm->tm_mon = bcd2bin(tm->tm_mon) - 1;
>> + tm->tm_year = bcd2bin(tm->tm_year) + 100;
>> + /*
>> + * Number of days since Sunday
>> + * - on kernel side, 0=Sunday...6=Saturday
>> + * - on rtc side, 0=invalid,1=Monday...7=Sunday
>> + */
>> + tm->tm_wday %= 7;
>> +}
>> +
>> +static int stm32_rtc_read_time(struct device *dev, struct rtc_time *tm)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> + unsigned int tr, dr;
>> + unsigned long irqflags;
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + /* Time and Date in BCD format */
>> + tr = stm32_rtc_readl(rtc, STM32_RTC_TR);
>> + dr = stm32_rtc_readl(rtc, STM32_RTC_DR);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + tm->tm_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT;
>> + tm->tm_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT;
>> + tm->tm_hour = (tr & STM32_RTC_TR_HOUR) >> STM32_RTC_TR_HOUR_SHIFT;
>> +
>> + tm->tm_mday = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT;
>> + tm->tm_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT;
>> + tm->tm_year = (dr & STM32_RTC_DR_YEAR) >> STM32_RTC_DR_YEAR_SHIFT;
>> + tm->tm_wday = (dr & STM32_RTC_DR_WDAY) >> STM32_RTC_DR_WDAY_SHIFT;
>> +
>> + /* We don't report tm_yday and tm_isdst */
>> +
>> + bcd2tm(tm);
>> +
>> + if (rtc_valid_tm(tm) < 0) {
>> + dev_err(dev, "%s: rtc_time is not valid.\n", __func__);
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int stm32_rtc_set_time(struct device *dev, struct rtc_time *tm)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> + unsigned int tr, dr;
>> + unsigned long irqflags;
>> + int ret = 0;
>> +
>> + if (rtc_valid_tm(tm) < 0) {
>> + dev_err(dev, "%s: rtc_time is not valid.\n", __func__);
>> + return -EINVAL;
>> + }
>> +
>> + tm2bcd(tm);
>> +
>> + /* Time in BCD format */
>> + tr = ((tm->tm_sec << STM32_RTC_TR_SEC_SHIFT) & STM32_RTC_TR_SEC) |
>> + ((tm->tm_min << STM32_RTC_TR_MIN_SHIFT) & STM32_RTC_TR_MIN) |
>> + ((tm->tm_hour << STM32_RTC_TR_HOUR_SHIFT) &
STM32_RTC_TR_HOUR);
>> +
>> + /* Date in BCD format */
>> + dr = ((tm->tm_mday << STM32_RTC_DR_DATE_SHIFT) &
STM32_RTC_DR_DATE) |
>> + ((tm->tm_mon << STM32_RTC_DR_MONTH_SHIFT) &
STM32_RTC_DR_MONTH) |
>> + ((tm->tm_year << STM32_RTC_DR_YEAR_SHIFT) &
STM32_RTC_DR_YEAR) |
>> + ((tm->tm_wday << STM32_RTC_DR_WDAY_SHIFT) &
STM32_RTC_DR_WDAY);
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + stm32_rtc_wpr_unlock(rtc);
>> +
>> + ret = stm32_rtc_enter_init_mode(rtc);
>> + if (ret) {
>> + dev_err(dev, "Can't enter in init mode. Set time aborted.\n");
>> + goto end;
>> + }
>> +
>> + stm32_rtc_writel(rtc, STM32_RTC_TR, tr);
>> + stm32_rtc_writel(rtc, STM32_RTC_DR, dr);
>> +
>> + stm32_rtc_exit_init_mode(rtc);
>> +
>> + ret = stm32_rtc_wait_sync(rtc);
>> +end:
>> + stm32_rtc_wpr_lock(rtc);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + return ret;
>> +}
>> +
>> +static int stm32_rtc_read_alarm(struct device *dev, struct
rtc_wkalrm *alrm)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> + struct rtc_time *tm = &alrm->time;
>> + unsigned int alrmar, cr, isr;
>> + unsigned long irqflags;
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + alrmar = stm32_rtc_readl(rtc, STM32_RTC_ALRMAR);
>> + cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
>> + isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + if (alrmar & STM32_RTC_ALRMXR_DATE_MASK) {
>> + /*
>> + * Date/day don't care in Alarm comparison so alarm triggers
>> + * every day
>> + */
>> + tm->tm_mday = -1;
>> + tm->tm_wday = -1;
>> + } else {
>> + if (alrmar & STM32_RTC_ALRMXR_WDSEL) {
>> + /* Alarm is set to a day of week */
>> + tm->tm_mday = -1;
>> + tm->tm_wday = (alrmar & STM32_RTC_ALRMXR_WDAY) >>
>> + STM32_RTC_ALRMXR_WDAY_SHIFT;
>> + tm->tm_wday %= 7;
>> + } else {
>> + /* Alarm is set to a day of month */
>> + tm->tm_wday = -1;
>> + tm->tm_mday = (alrmar & STM32_RTC_ALRMXR_DATE) >>
>> + STM32_RTC_ALRMXR_DATE_SHIFT;
>> + }
>> + }
>> +
>> + if (alrmar & STM32_RTC_ALRMXR_HOUR_MASK) {
>> + /* Hours don't care in Alarm comparison */
>> + tm->tm_hour = -1;
>> + } else {
>> + tm->tm_hour = (alrmar & STM32_RTC_ALRMXR_HOUR) >>
>> + STM32_RTC_ALRMXR_HOUR_SHIFT;
>> + if (alrmar & STM32_RTC_ALRMXR_PM)
>> + tm->tm_hour += 12;
>> + }
>> +
>> + if (alrmar & STM32_RTC_ALRMXR_MIN_MASK) {
>> + /* Minutes don't care in Alarm comparison */
>> + tm->tm_min = -1;
>> + } else {
>> + tm->tm_min = (alrmar & STM32_RTC_ALRMXR_MIN) >>
>> + STM32_RTC_ALRMXR_MIN_SHIFT;
>> + }
>> +
>> + if (alrmar & STM32_RTC_ALRMXR_SEC_MASK) {
>> + /* Seconds don't care in Alarm comparison */
>> + tm->tm_sec = -1;
>> + } else {
>> + tm->tm_sec = (alrmar & STM32_RTC_ALRMXR_SEC) >>
>> + STM32_RTC_ALRMXR_SEC_SHIFT;
>> + }
>> +
>> + bcd2tm(tm);
>> +
>> + alrm->enabled = (cr & STM32_RTC_CR_ALRAE) ? 1 : 0;
>> + alrm->pending = (isr & STM32_RTC_ISR_ALRAF) ? 1 : 0;
>> +
>> + return 0;
>> +}
>> +
>> +static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned
int enabled)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> + unsigned long irqflags;
>> + unsigned int isr, cr;
>> +
>> + cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
>
> Is the STM32_RTC_CR garanteed to be valid, i.e updated atomically?
If not this
> should probably be below the spinlock.
You're right.
>
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + stm32_rtc_wpr_unlock(rtc);
>> +
>> + /* We expose Alarm A to the kernel */
>> + if (enabled)
>> + cr |= (STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
>> + else
>> + cr &= ~(STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
>> + stm32_rtc_writel(rtc, STM32_RTC_CR, cr);
>> +
>> + /* Clear event irqflags, otherwise new events won't be received */
>> + isr = stm32_rtc_readl(rtc, STM32_RTC_ISR);
>> + isr &= ~STM32_RTC_ISR_ALRAF;
>> + stm32_rtc_writel(rtc, STM32_RTC_ISR, isr);
>> +
>> + stm32_rtc_wpr_lock(rtc);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + return 0;
>> +}
>> +
>> +static int stm32_rtc_set_alarm(struct device *dev, struct
rtc_wkalrm *alrm)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> + struct rtc_time *tm = &alrm->time;
>> + unsigned long irqflags;
>> + unsigned int cr, isr, alrmar;
>> + int ret = 0;
>> +
>> + if (rtc_valid_tm(tm)) {
>> + dev_err(dev, "Alarm time not valid.\n");
>> + return -EINVAL;
>> + }
>> +
>> + tm2bcd(tm);
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + stm32_rtc_wpr_unlock(rtc);
>> +
>> + /* Disable Alarm */
>> + cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
>> + cr &= ~STM32_RTC_CR_ALRAE;
>> + stm32_rtc_writel(rtc, STM32_RTC_CR, cr);
>> +
>> + /* Poll Alarm write flag to be sure that Alarm update is allowed */
>> + ret = readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
>> + isr,
>> + (isr & STM32_RTC_ISR_ALRAWF),
>> + 10, 100);
>> +
>> + if (ret) {
>> + dev_err(dev, "Alarm update not allowed\n");
>> + goto end;
>> + }
>> +
>> + alrmar = 0;
>> +
>> + if (tm->tm_mday < 0 && tm->tm_wday < 0) {
>> + /*
>> + * Date/day don't care in Alarm comparison so alarm triggers
>> + * every day
>> + */
>> + alrmar |= STM32_RTC_ALRMXR_DATE_MASK;
>> + } else {
>> + if (tm->tm_mday > 0) {
>> + /* Date is selected (ignoring wday) */
>> + alrmar |= (tm->tm_mday << STM32_RTC_ALRMXR_DATE_SHIFT) &
>> + STM32_RTC_ALRMXR_DATE;
>> + } else {
>> + /* Day of week is selected */
>> + int wday = (tm->tm_wday == 0) ? 7 : tm->tm_wday;
>> +
>> + alrmar |= STM32_RTC_ALRMXR_WDSEL;
>> + alrmar |= (wday << STM32_RTC_ALRMXR_WDAY_SHIFT) &
>> + STM32_RTC_ALRMXR_WDAY;
>> + }
>> + }
>> +
>> + if (tm->tm_hour < 0) {
>> + /* Hours don't care in Alarm comparison */
>> + alrmar |= STM32_RTC_ALRMXR_HOUR_MASK;
>> + } else {
>> + /* 24-hour format */
>> + alrmar &= ~STM32_RTC_ALRMXR_PM;
>> + alrmar |= (tm->tm_hour << STM32_RTC_ALRMXR_HOUR_SHIFT) &
>> + STM32_RTC_ALRMXR_HOUR;
>> + }
>> +
>> + if (tm->tm_min < 0) {
>> + /* Minutes don't care in Alarm comparison */
>> + alrmar |= STM32_RTC_ALRMXR_MIN_MASK;
>> + } else {
>> + alrmar |= (tm->tm_min << STM32_RTC_ALRMXR_MIN_SHIFT) &
>> + STM32_RTC_ALRMXR_MIN;
>> + }
>> +
>> + if (tm->tm_sec < 0) {
>> + /* Seconds don't care in Alarm comparison */
>> + alrmar |= STM32_RTC_ALRMXR_SEC_MASK;
>> + } else {
>> + alrmar |= (tm->tm_sec << STM32_RTC_ALRMXR_SEC_SHIFT) &
>> + STM32_RTC_ALRMXR_SEC;
>> + }
>> +
>> + /* Write to Alarm register */
>> + stm32_rtc_writel(rtc, STM32_RTC_ALRMAR, alrmar);
>> +
>> + if (alrm->enabled)
>> + stm32_rtc_alarm_irq_enable(dev, 1);
>> + else
>> + stm32_rtc_alarm_irq_enable(dev, 0);
>> +
>> +end:
>> + stm32_rtc_wpr_lock(rtc);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + return ret;
>> +}
>> +
>> +static const struct rtc_class_ops stm32_rtc_ops = {
>> + .read_time = stm32_rtc_read_time,
>> + .set_time = stm32_rtc_set_time,
>> + .read_alarm = stm32_rtc_read_alarm,
>> + .set_alarm = stm32_rtc_set_alarm,
>> + .alarm_irq_enable = stm32_rtc_alarm_irq_enable,
>> +};
>> +
>> +#ifdef CONFIG_OF
>> +static const struct of_device_id stm32_rtc_of_match[] = {
>> + { .compatible = "st,stm32-rtc" },
>> + {}
>> +};
>> +MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
>> +#endif
>> +
>> +static int stm32_rtc_init(struct platform_device *pdev,
>> + struct stm32_rtc *rtc)
>> +{
>> + unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr;
>> + unsigned int rate;
>> + unsigned long irqflags;
>> + int ret = 0;
>> +
>> + rate = clk_get_rate(rtc->ck_rtc);
>> +
>> + /* Find prediv_a and prediv_s to obtain the 1Hz calendar clock */
>> + pred_a_max = STM32_RTC_PRER_PRED_A >> STM32_RTC_PRER_PRED_A_SHIFT;
>> + pred_s_max = STM32_RTC_PRER_PRED_S >> STM32_RTC_PRER_PRED_S_SHIFT;
>> +
>> + for (pred_a = pred_a_max; pred_a >= 0; pred_a--) {
>> + pred_s = (rate / (pred_a + 1)) - 1;
>> +
>> + if (((pred_s + 1) * (pred_a + 1)) == rate)
>> + break;
>> + }
>> +
>> + /*
>> + * Can't find a 1Hz, so give priority to RTC power consumption
>> + * by choosing the higher possible value for prediv_a
>> + */
>> + if ((pred_s > pred_s_max) || (pred_a > pred_a_max)) {
>> + pred_a = pred_a_max;
>> + pred_s = (rate / (pred_a + 1)) - 1;
>> +
>> + dev_warn(&pdev->dev, "ck_rtc is %s\n",
>> + (rate - ((pred_a + 1) * (pred_s + 1)) < 0) ?
>> + "fast" : "slow");
>> + }
>> +
>> + spin_lock_irqsave(&rtc->lock, irqflags);
>> +
>> + stm32_rtc_wpr_unlock(rtc);
>> +
>> + ret = stm32_rtc_enter_init_mode(rtc);
>> + if (ret) {
>> + dev_err(&pdev->dev,
>> + "Can't enter in init mode. Prescaler config failed.\n");
>> + goto end;
>> + }
>> +
>> + prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) &
STM32_RTC_PRER_PRED_S;
>> + stm32_rtc_writel(rtc, STM32_RTC_PRER, prer);
>> + prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) &
STM32_RTC_PRER_PRED_A;
>> + stm32_rtc_writel(rtc, STM32_RTC_PRER, prer);
>> +
>> + /* Force 24h time format */
>> + cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
>> + cr &= ~STM32_RTC_CR_FMT;
>> + stm32_rtc_writel(rtc, STM32_RTC_CR, cr);
>> +
>> + stm32_rtc_exit_init_mode(rtc);
>> +
>> + ret = stm32_rtc_wait_sync(rtc);
>> +
>> + if (stm32_rtc_readl(rtc, STM32_RTC_ISR) & STM32_RTC_ISR_INITS)
>> + dev_warn(&pdev->dev, "Date/Time must be initialized\n");
>> +end:
>> + stm32_rtc_wpr_lock(rtc);
>> +
>> + spin_unlock_irqrestore(&rtc->lock, irqflags);
>> +
>> + return ret;
>> +}
>> +
>> +static int stm32_rtc_probe(struct platform_device *pdev)
>> +{
>> + struct stm32_rtc *rtc;
>> + struct resource *res;
>> + int ret;
>> +
>> + rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
>> + if (!rtc)
>> + return -ENOMEM;
>> +
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>
> The value of 'res' should be checked before using it.
res is checked in devm_ioremap_resource just below :
if (!res || resource_type(res) != IORESOURCE_MEM) {
dev_err(dev, "invalid resource\n");
return IOMEM_ERR_PTR(-EINVAL);
}
That's why it is not checked here.
>
>> + rtc->base = devm_ioremap_resource(&pdev->dev, res);
>> + if (IS_ERR(rtc->base))
>> + return PTR_ERR(rtc->base);
>> +
>> + dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"st,syscfg");
>> + if (IS_ERR(dbp)) {
>> + dev_err(&pdev->dev, "no st,syscfg\n");
>> + return PTR_ERR(dbp);
>> + }
>> +
>> + spin_lock_init(&rtc->lock);
>> +
>> + rtc->ck_rtc = devm_clk_get(&pdev->dev, "ck_rtc");
>> + if (IS_ERR(rtc->ck_rtc)) {
>> + dev_err(&pdev->dev, "no ck_rtc clock");
>> + return PTR_ERR(rtc->ck_rtc);
>> + }
>> +
>> + ret = clk_prepare_enable(rtc->ck_rtc);
>> + if (ret)
>> + return ret;
>> +
>> + if (dbp)
>> + regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
>
> The code above exits if there is a problem with the dbp, there is no
point in
> checking again.
You're right.
>
>> +
>> + ret = stm32_rtc_init(pdev, rtc);
>> + if (ret)
>> + goto err;
>> +
>> + rtc->irq_alarm = platform_get_irq_byname(pdev, "alarm");
>> + if (rtc->irq_alarm <= 0) {
>> + dev_err(&pdev->dev, "no alarm irq\n");
>> + ret = -ENOENT;
>> + goto err;
>> + }
>> +
>> + platform_set_drvdata(pdev, rtc);
>> +
>> + device_init_wakeup(&pdev->dev, true);
>
> What happens if device_init_wakeup() returns an error?
It means that RTC won't be able to wake up the board with RTC alarm. I
can add a warning for the user in this case ?
>
>> +
>> + rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
>> + &stm32_rtc_ops, THIS_MODULE);
>> + if (IS_ERR(rtc->rtc_dev)) {
>> + ret = PTR_ERR(rtc->rtc_dev);
>> + dev_err(&pdev->dev, "rtc device registration failed, err=%d\n",
>> + ret);
>> + goto err;
>> + }
>> +
>> + /* Handle RTC alarm interrupts */
>> + ret = devm_request_irq(&pdev->dev, rtc->irq_alarm,
>> + stm32_rtc_alarm_irq, IRQF_TRIGGER_RISING,
>> + dev_name(&rtc->rtc_dev->dev), rtc);
>> + if (ret) {
>> + dev_err(&pdev->dev, "IRQ%d (alarm interrupt) already
claimed\n",
>> + rtc->irq_alarm);
>> + goto err;
>> + }
>> +
>> + return 0;
>> +err:
>> + clk_disable_unprepare(rtc->ck_rtc);
>> +
>> + if (dbp)
>> + regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
>
> Same comment as above.
OK.
>
>> +
>> + device_init_wakeup(&pdev->dev, false);
>> +
>> + return ret;
>> +}
>> +
>> +static int __exit stm32_rtc_remove(struct platform_device *pdev)
>> +{
>> + struct stm32_rtc *rtc = platform_get_drvdata(pdev);
>> + unsigned int cr;
>> +
>> + /* Disable interrupts */
>> + stm32_rtc_wpr_unlock(rtc);
>> + cr = stm32_rtc_readl(rtc, STM32_RTC_CR);
>> + cr &= ~STM32_RTC_CR_ALRAIE;
>> + stm32_rtc_writel(rtc, STM32_RTC_CR, cr);
>> + stm32_rtc_wpr_lock(rtc);
>> +
>> + clk_disable_unprepare(rtc->ck_rtc);
>> +
>> + /* Enable backup domain write protection */
>> + if (dbp)
>> + regmap_update_bits(dbp, PWR_CR, PWR_CR_DBP, ~PWR_CR_DBP);
>> +
>> + device_init_wakeup(&pdev->dev, false);
>> +
>> + return 0;
>> +}
>> +
>> +#ifdef CONFIG_PM_SLEEP
>> +static int stm32_rtc_suspend(struct device *dev)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> +
>> + if (device_may_wakeup(dev))
>> + return enable_irq_wake(rtc->irq_alarm);
>> +
>> + return 0;
>> +}
>> +
>> +static int stm32_rtc_resume(struct device *dev)
>> +{
>> + struct stm32_rtc *rtc = dev_get_drvdata(dev);
>> + int ret = 0;
>> +
>> + ret = stm32_rtc_wait_sync(rtc);
>> + if (ret < 0)
>> + return ret;
>> +
>> + if (device_may_wakeup(dev))
>> + return disable_irq_wake(rtc->irq_alarm);
>> +
>> + return ret;
>> +}
>> +#endif
>> +
>> +static SIMPLE_DEV_PM_OPS(stm32_rtc_pm_ops,
>> + stm32_rtc_suspend, stm32_rtc_resume);
>> +
>> +static struct platform_driver stm32_rtc_driver = {
>> + .probe = stm32_rtc_probe,
>> + .remove = stm32_rtc_remove,
>> + .driver = {
>> + .name = DRIVER_NAME,
>> + .pm = &stm32_rtc_pm_ops,
>> + .of_match_table = stm32_rtc_of_match,
>> + },
>> +};
>> +
>> +module_platform_driver(stm32_rtc_driver);
>> +
>> +MODULE_ALIAS("platform:" DRIVER_NAME);
>> +MODULE_AUTHOR("Amelie Delaunay <amelie.delaunay-qxv4g6HH51o@public.gmane.org>");
>> +MODULE_DESCRIPTION("STMicroelectronics STM32 Real Time Clock driver");
>> +MODULE_LICENSE("GPL v2");
>> --
>> 1.9.1
>>
Best regards,
Amelie
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply
* Re: [PATCH v2 2/3] ARM: dts: sunxi: add support for Orange Pi Zero board
From: Maxime Ripard @ 2016-12-05 9:40 UTC (permalink / raw)
To: Icenowy Zheng
Cc: Mark Rutland, devicetree@vger.kernel.org, Vishnu Patekar,
Arnd Bergmann, linux-doc@vger.kernel.org, André Przywara,
Jonathan Corbet, linux-kernel, Russell King, Hans de Goede,
Chen-Yu Tsai, linux-arm-kernel@lists.infradead.org
In-Reply-To: <20161205120021.0GBGtAl4@smtp3m.mail.yandex.net>
[-- Attachment #1.1: Type: text/plain, Size: 2277 bytes --]
On Mon, Dec 05, 2016 at 04:59:44PM +0800, Icenowy Zheng wrote:
>
> 2016年12月5日 16:52于 Maxime Ripard <maxime.ripard@free-electrons.com>写道:
> >
> > On Fri, Dec 02, 2016 at 10:22:30PM +0800, Icenowy Zheng wrote:
> > >
> > >
> > > 01.12.2016, 17:36, "Maxime Ripard" <maxime.ripard@free-electrons.com>:
> > > > On Mon, Nov 28, 2016 at 12:29:07AM +0000, André Przywara wrote:
> > > >> > Something more interesting happened.
> > > >> >
> > > >> > Xunlong made a add-on board for Orange Pi Zero, which exposes the
> > > >> > two USB Controllers exported at expansion bus as USB Type-A
> > > >> > connectors.
> > > >> >
> > > >> > Also it exposes a analog A/V jack and a microphone.
> > > >> >
> > > >> > Should I enable {e,o}hci{2.3} in the device tree?
> > > >>
> > > >> Actually we should do this regardless of this extension board. The USB
> > > >> pins are not multiplexed and are exposed on user accessible pins (just
> > > >> not soldered, but that's a detail), so I think they qualify for DT
> > > >> enablement. And even if a user can't use them, it doesn't hurt to have
> > > >> them (since they are not multiplexed).
> > > >
> > > > My main concern about this is that we'll leave regulators enabled by
> > > > default, for a minority of users. And that minority will prevent to do
> > > > a proper power management when the times come since we'll have to keep
> > > > that behaviour forever.
> > >
> > > I think these users can add a 'fdt set /xxx/xxx status "disabled" ' .
> >
> > You can't ask that from the majority of users. These users will take
> > debian or fedora, install it, and expect everything to work
> > properly. I would make the opposite argument actually. If someone is
> > knowledgeable enough to solder the USB pins a connector, then (s)he'll
> > be able to make that u-boot call.
>
> Now (s)he do not need soldering.
>
> (S)he needs only paying $1.99 more to Xunlong to get the expansion
> board, and insert it on the OPi Zero.
Which is going to require an overlay anyway, so we could have the USB
bits in there too.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] ARM: dts: sunxi: Add num-cs for A20 spi nodes
From: Emmanuel Vadot @ 2016-12-05 9:39 UTC (permalink / raw)
To: Maxime Ripard
Cc: mark.rutland, devicetree, linux, linux-kernel, wens, robh+dt,
linux-arm-kernel
In-Reply-To: <20161205092821.m2fmqxnzalcignly@lukather>
On Mon, 5 Dec 2016 10:28:21 +0100
Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
> On Thu, Dec 01, 2016 at 11:24:14AM +0100, Emmanuel Vadot wrote:
> > > > > > If num-cs isn't present nothing prevent to start a transfer
> > > > > > with a non-valid CS pin, resulting in an error. num-cs are
> > > > > > default property especially made for this and a SPI driver
> > > > > > should try to get the property at probe/attach time.
> > > > >
> > > > > Yes, but as far as I know, our driver doesn't. I'm all in for
> > > > > having support for that in our driver, but without it, that
> > > > > patch is kind of useless.
> > > >
> > > > Yes the Linux driver doesn't use it but my upcoming one for FreeBSD
> > > > uses it. So it is not useless for downstream user of DTS.
> > >
> > > Ah, I didn't know this was for FreeBSD. So you started to use our DTs,
> > > or do you have some modifications to it? How does that work?
> >
> > Yes we use the DTS from linux from quite some times now. We're
> > currently synced with 4.7-ish. We either use them directly or
> > modify them according to our needs and driver support.
>
> Do you have a link to those modifications?
>
> Thanks,
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
Sure,
https://svnweb.freebsd.org/base/head/sys/boot/fdt/dts/arm/
--
Emmanuel Vadot <manu@bidouilliste.com> <manu@freebsd.org>
^ permalink raw reply
* Re: [PATCH] ARM: dts: sunxi: Add num-cs for A20 spi nodes
From: Maxime Ripard @ 2016-12-05 9:28 UTC (permalink / raw)
To: Emmanuel Vadot
Cc: mark.rutland, devicetree, linux, linux-kernel, wens, robh+dt,
linux-arm-kernel
In-Reply-To: <20161201112414.62f9b351186115f62c8998a9@bidouilliste.com>
[-- Attachment #1: Type: text/plain, Size: 1187 bytes --]
On Thu, Dec 01, 2016 at 11:24:14AM +0100, Emmanuel Vadot wrote:
> > > > > If num-cs isn't present nothing prevent to start a transfer
> > > > > with a non-valid CS pin, resulting in an error. num-cs are
> > > > > default property especially made for this and a SPI driver
> > > > > should try to get the property at probe/attach time.
> > > >
> > > > Yes, but as far as I know, our driver doesn't. I'm all in for
> > > > having support for that in our driver, but without it, that
> > > > patch is kind of useless.
> > >
> > > Yes the Linux driver doesn't use it but my upcoming one for FreeBSD
> > > uses it. So it is not useless for downstream user of DTS.
> >
> > Ah, I didn't know this was for FreeBSD. So you started to use our DTs,
> > or do you have some modifications to it? How does that work?
>
> Yes we use the DTS from linux from quite some times now. We're
> currently synced with 4.7-ish. We either use them directly or
> modify them according to our needs and driver support.
Do you have a link to those modifications?
Thanks,
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH v3 -next 1/2] ARM: sunxi: add support for H2+ SoC
From: Maxime Ripard @ 2016-12-05 9:19 UTC (permalink / raw)
To: Icenowy Zheng
Cc: Chen-Yu Tsai, Rob Herring, Russell King, Andre Przywara,
Hans de Goede, Arnd Bergmann, Vishnu Patekar,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20161202150513.34691-1-icenowy-ymACFijhrKM@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 490 bytes --]
On Fri, Dec 02, 2016 at 11:05:12PM +0800, Icenowy Zheng wrote:
> Allwinner H2+ is a quad-core Cortex-A7 SoC.
>
> It is very like H3, that they share the same SoC ID (0x1680), and H3
> memory maps as well as drivers works well on the SoC.
>
> Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
Fixed the alphabetical order in the bindings doc, and applied.
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH v6 2/2] mtd: nand: Add support for Arasan Nand Flash Controller
From: kbuild test robot @ 2016-12-05 9:16 UTC (permalink / raw)
To: Punnaiah Choudary Kalluri
Cc: mark.rutland, boris.brezillon, devicetree, richard, linux-kernel,
Punnaiah Choudary Kalluri, marek.vasut, robh+dt, linux-mtd,
kbuild-all, kalluripunnaiahchoudary, kpc528, michals,
cyrille.pitchen, computersforpeace, dwmw2
In-Reply-To: <1480911066-26157-2-git-send-email-punnaia@xilinx.com>
[-- Attachment #1: Type: text/plain, Size: 3489 bytes --]
Hi Punnaiah,
[auto build test ERROR on mtd/master]
[also build test ERROR on v4.9-rc8 next-20161205]
[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/Punnaiah-Choudary-Kalluri/mtd-arasan-Add-device-tree-binding-documentation/20161205-162929
base: git://git.infradead.org/linux-mtd.git master
config: x86_64-allmodconfig (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 errors (new ones prefixed by >>):
drivers/mtd/nand/arasan_nand.c: In function 'anfc_read_buf':
>> drivers/mtd/nand/arasan_nand.c:348:3: error: implicit declaration of function 'readsl' [-Werror=implicit-function-declaration]
readsl(nfc->base + DATA_PORT_OFST, bufptr, pktsize/4);
^~~~~~
drivers/mtd/nand/arasan_nand.c: In function 'anfc_write_buf':
>> drivers/mtd/nand/arasan_nand.c:402:3: error: implicit declaration of function 'writesl' [-Werror=implicit-function-declaration]
writesl(nfc->base + DATA_PORT_OFST, bufptr, pktsize/4);
^~~~~~~
cc1: some warnings being treated as errors
vim +/readsl +348 drivers/mtd/nand/arasan_nand.c
342 anfc_wait_for_event(nfc);
343 buf_rd_cnt++;
344
345 if (buf_rd_cnt == pktcount)
346 anfc_enable_intrs(nfc, XFER_COMPLETE);
347
> 348 readsl(nfc->base + DATA_PORT_OFST, bufptr, pktsize/4);
349 bufptr += (pktsize / 4);
350
351 if (buf_rd_cnt < pktcount)
352 anfc_enable_intrs(nfc, (READ_READY | eccintr));
353 }
354
355 anfc_wait_for_event(nfc);
356 }
357
358 static void anfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
359 {
360 u32 pktcount, pktsize;
361 unsigned int buf_wr_cnt = 0;
362 u32 *bufptr = (u32 *)buf;
363 struct nand_chip *chip = mtd_to_nand(mtd);
364 struct anfc_nand_chip *achip = to_anfc_nand(chip);
365 struct anfc *nfc = to_anfc(chip->controller);
366 dma_addr_t paddr;
367
368 if (nfc->iswriteoob) {
369 pktsize = len;
370 pktcount = 1;
371 } else {
372 pktsize = achip->pktsize;
373 pktcount = mtd->writesize / pktsize;
374 }
375
376 anfc_setpktszcnt(nfc, pktsize, pktcount);
377
378 if (nfc->dma) {
379 paddr = dma_map_single(nfc->dev, (void *)buf, len,
380 DMA_TO_DEVICE);
381 if (dma_mapping_error(nfc->dev, paddr)) {
382 dev_err(nfc->dev, "Write buffer mapping error");
383 return;
384 }
385 lo_hi_writeq(paddr, nfc->base + DMA_ADDR0_OFST);
386 anfc_enable_intrs(nfc, XFER_COMPLETE);
387 writel(PROG_PGPROG, nfc->base + PROG_OFST);
388 anfc_wait_for_event(nfc);
389 dma_unmap_single(nfc->dev, paddr, len, DMA_TO_DEVICE);
390 return;
391 }
392
393 anfc_enable_intrs(nfc, WRITE_READY);
394 writel(PROG_PGPROG, nfc->base + PROG_OFST);
395
396 while (buf_wr_cnt < pktcount) {
397 anfc_wait_for_event(nfc);
398 buf_wr_cnt++;
399 if (buf_wr_cnt == pktcount)
400 anfc_enable_intrs(nfc, XFER_COMPLETE);
401
> 402 writesl(nfc->base + DATA_PORT_OFST, bufptr, pktsize/4);
403 bufptr += (pktsize / 4);
404
405 if (buf_wr_cnt < pktcount)
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 56586 bytes --]
[-- Attachment #3: Type: text/plain, Size: 144 bytes --]
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply
* Re: [PATCH 2/2] HID: i2c-hid: support regulator power on/off
From: Benjamin Tissoires @ 2016-12-05 9:14 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Brian Norris, Jiri Kosina, Caesar Wang,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Rob Herring,
linux-input-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mark Rutland, Doug Anderson
In-Reply-To: <20161202230013.GA18268@dtor-ws>
On Dec 02 2016 or thereabouts, Dmitry Torokhov wrote:
> On Fri, Dec 02, 2016 at 02:19:00PM -0800, Brian Norris wrote:
> > On some boards, we need to enable a regulator before using the HID, and
> > it's also nice to save power in suspend by disabling it. Support an
> > optional "vdd-supply" and a companion initialization delay.
> >
> > Signed-off-by: Brian Norris <briannorris-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> > Signed-off-by: Caesar Wang <wxt-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> > Cc: Jiri Kosina <jikos-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> > Cc: linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > ---
> > v2:
> > * support compatible property for wacom, with specific "vdd-supply"
> > * name
> > * support the 100ms delay needed for this digitizer
> > * target regulator support only at specific device
> >
> > v3:
> > * drop Wacom specifics and allow this to be used generically
> > * add "init-delay-ms" property support
> >
> > v4:
> > * use devm_regulator_get() (with a 'dummy' regulator for most cases)
> > instead of _optional() version, to make code less conditional (Dmitry)
> > * fix but where 'init_delay_ms' wasn't getting assigned properly
> > * disable regulator in probe() failure path
> > ---
> > drivers/hid/i2c-hid/i2c-hid.c | 44 +++++++++++++++++++++++++++++++++++++++++--
> > include/linux/i2c/i2c-hid.h | 6 ++++++
> > 2 files changed, 48 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
> > index b3ec4f2de875..5c6e037613d7 100644
> > --- a/drivers/hid/i2c-hid/i2c-hid.c
> > +++ b/drivers/hid/i2c-hid/i2c-hid.c
> > @@ -38,6 +38,7 @@
> > #include <linux/acpi.h>
> > #include <linux/of.h>
> > #include <linux/gpio/consumer.h>
> > +#include <linux/regulator/consumer.h>
> >
> > #include <linux/i2c/i2c-hid.h>
> >
> > @@ -937,6 +938,10 @@ static int i2c_hid_of_probe(struct i2c_client *client,
> > }
> > pdata->hid_descriptor_address = val;
> >
> > + ret = of_property_read_u32(dev->of_node, "init-delay-ms", &val);
> > + if (!ret)
> > + pdata->init_delay_ms = val;
> > +
> > return 0;
> > }
> >
> > @@ -983,6 +988,15 @@ static int i2c_hid_probe(struct i2c_client *client,
> > ihid->pdata = *platform_data;
> > }
> >
> > + ihid->pdata.supply = devm_regulator_get(&client->dev, "vdd");
>
> Oh, haveni't noticed that the rest of the driver does not use devm.
> Well, I'll leave it up to hid-i2c folks to decide if they are OK with
> mixing up the managed and non-managed resources, it seems safe to me in
> this case.
Yeah, it looks good to me as well. However, I think that will be the
trigger to request a devm conversion of the i2c-hid driver. Something
I'll add to my list of things to consider for v4.11 then :)
Acked-by: Benjamin Tissoires <benjamin.tissoires-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Cheers,
Benjamin
>
> Reviewed-by: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>
> Thanks.
>
> --
> Dmitry
--
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
* [PATCH v2 6/6] net: smmac: allow configuring lower pbl values
From: Niklas Cassel @ 2016-12-05 9:12 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Jonathan Corbet, Giuseppe Cavallaro,
Alexandre Torgue, David S. Miller, Phil Reid, Niklas Cassel,
Eric Engestrom, Pavel Machek, Joachim Eastwood, Gabriel Fernandez,
Vincent Palatin
Cc: netdev, devicetree, linux-kernel, linux-doc
In-Reply-To: <1480929155-20462-1-git-send-email-niklass@axis.com>
From: Niklas Cassel <niklas.cassel@axis.com>
The driver currently always sets the PBLx8/PBLx4 bit, which means that
the pbl values configured via the pbl/txpbl/rxpbl DT properties are
always multiplied by 8/4 in the hardware.
In order to allow the DT to configure lower pbl values, while at the
same time not changing behavior of any existing device trees using the
pbl/txpbl/rxpbl settings, add a property to disable the multiplication
of the pbl by 8/4 in the hardware.
Suggested-by: Rabin Vincent <rabinv@axis.com>
Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>
---
Documentation/devicetree/bindings/net/stmmac.txt | 2 ++
Documentation/networking/stmmac.txt | 5 ++++-
drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 3 ++-
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 3 ++-
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 2 ++
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 1 +
include/linux/stmmac.h | 1 +
7 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
index a3dc1453dffb..1fb3c309c558 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -39,6 +39,8 @@ Optional properties:
If set, DMA tx will use this value rather than snps,pbl.
- snps,rxpbl Rx Programmable Burst Length. Only for GMAC and newer.
If set, DMA rx will use this value rather than snps,pbl.
+- snps,no-pbl-x8 Don't multiply the pbl/txpbl/rxpbl values by 8.
+ For core rev < 3.50, don't multiply the values by 4.
- snps,aal Address-Aligned Beats
- snps,fixed-burst Program the DMA to use the fixed burst mode
- snps,mixed-burst Program the DMA to use the mixed burst mode
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 6add57374f70..2bb07078f535 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -152,8 +152,9 @@ Where:
o dma_cfg: internal DMA parameters
o pbl: the Programmable Burst Length is maximum number of beats to
be transferred in one DMA transaction.
- GMAC also enables the 4xPBL by default.
+ GMAC also enables the 4xPBL by default. (8xPBL for GMAC 3.50 and newer)
o txpbl/rxpbl: GMAC and newer supports independent DMA pbl for tx/rx.
+ o pblx8: Enable 8xPBL (4xPBL for core rev < 3.50). Enabled by default.
o fixed_burst/mixed_burst/aal
o clk_csr: fixed CSR Clock range selection.
o has_gmac: uses the GMAC core.
@@ -208,6 +209,7 @@ struct stmmac_dma_cfg {
int pbl;
int txpbl;
int rxpbl;
+ bool pblx8;
int fixed_burst;
int mixed_burst;
bool aal;
@@ -219,6 +221,7 @@ Where:
If set, DMA tx will use this value rather than pbl.
o rxpbl: Receive Programmable Burst Length. Only for GMAC and newer.
If set, DMA rx will use this value rather than pbl.
+ o pblx8: Enable 8xPBL (4xPBL for core rev < 3.50). Enabled by default.
o fixed_burst: program the DMA to use the fixed burst mode
o mixed_burst: program the DMA to use the mixed burst mode
o aal: Address-Aligned Beats
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 1dd34fb4c1a9..1d313af647b4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -96,7 +96,8 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
* Note: before stmmac core 3.50 this mode bit was 4xPBL, and
* post 3.5 mode bit acts as 8*PBL.
*/
- value |= DMA_BUS_MODE_MAXPBL;
+ if (dma_cfg->pblx8)
+ value |= DMA_BUS_MODE_MAXPBL;
value |= DMA_BUS_MODE_USP;
value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 0bf47825bfeb..0f7110d19a4a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -82,7 +82,8 @@ static void dwmac4_dma_init_channel(void __iomem *ioaddr,
* on each channel
*/
value = readl(ioaddr + DMA_CHAN_CONTROL(channel));
- value = value | DMA_BUS_MODE_PBL;
+ if (dma_cfg->pblx8)
+ value = value | DMA_BUS_MODE_PBL;
writel(value, ioaddr + DMA_CHAN_CONTROL(channel));
value = readl(ioaddr + DMA_CHAN_TX_CONTROL(channel));
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
index 56c8a2342c14..a2831773431a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -81,6 +81,7 @@ static void stmmac_default_data(struct plat_stmmacenet_data *plat)
plat->mdio_bus_data->phy_mask = 0;
plat->dma_cfg->pbl = 32;
+ plat->dma_cfg->pblx8 = true;
/* TODO: AXI */
/* Set default value for multicast hash bins */
@@ -115,6 +116,7 @@ static int quark_default_data(struct plat_stmmacenet_data *plat,
plat->mdio_bus_data->phy_mask = 0;
plat->dma_cfg->pbl = 16;
+ plat->dma_cfg->pblx8 = true;
plat->dma_cfg->fixed_burst = 1;
/* AXI (TODO) */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 55cac48897f6..5f1d0ade643f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -312,6 +312,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
of_property_read_u32(np, "snps,txpbl", &dma_cfg->txpbl);
of_property_read_u32(np, "snps,rxpbl", &dma_cfg->rxpbl);
+ dma_cfg->pblx8 = !of_property_read_bool(np, "snps,no-pbl-x8");
dma_cfg->aal = of_property_read_bool(np, "snps,aal");
dma_cfg->fixed_burst = of_property_read_bool(np, "snps,fixed-burst");
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index e6d7a5940819..266dab9ad782 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -90,6 +90,7 @@ struct stmmac_dma_cfg {
int pbl;
int txpbl;
int rxpbl;
+ bool pblx8;
int fixed_burst;
int mixed_burst;
bool aal;
--
2.1.4
^ permalink raw reply related
* [PATCH v2 5/6] net: stmmac: add support for independent DMA pbl for tx/rx
From: Niklas Cassel @ 2016-12-05 9:12 UTC (permalink / raw)
To: Rob Herring, Mark Rutland, Jonathan Corbet, Giuseppe Cavallaro,
Alexandre Torgue, David S. Miller, Niklas Cassel, Phil Reid,
Eric Engestrom, Pavel Machek, Joachim Eastwood, Gabriel Fernandez,
Vincent Palatin
Cc: netdev, devicetree, linux-kernel, linux-doc
From: Niklas Cassel <niklas.cassel@axis.com>
GMAC and newer supports independent programmable burst lengths for
DMA tx/rx. Add new optional devicetree properties representing this.
To be backwards compatible, snps,pbl will still be valid, but
snps,txpbl/snps,rxpbl will override the value in snps,pbl if set.
If the IP is synthesized to use the AXI interface, there is a register
and a matching DT property inside the optional stmmac-axi-config DT node
for controlling burst lengths, named snps,blen.
However, using this register, it is not possible to control tx and rx
independently. Also, this register is not available if the IP was
synthesized with, e.g., the AHB interface.
Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>
---
Documentation/devicetree/bindings/net/stmmac.txt | 6 +++++-
Documentation/networking/stmmac.txt | 19 +++++++++++++------
drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 12 ++++++------
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 12 +++++++-----
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 ++
include/linux/stmmac.h | 2 ++
6 files changed, 35 insertions(+), 18 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
index 41b49e6075f5..a3dc1453dffb 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -34,7 +34,11 @@ Optional properties:
platforms.
- tx-fifo-depth: See ethernet.txt file in the same directory
- rx-fifo-depth: See ethernet.txt file in the same directory
-- snps,pbl Programmable Burst Length
+- snps,pbl Programmable Burst Length (tx and rx)
+- snps,txpbl Tx Programmable Burst Length. Only for GMAC and newer.
+ If set, DMA tx will use this value rather than snps,pbl.
+- snps,rxpbl Rx Programmable Burst Length. Only for GMAC and newer.
+ If set, DMA rx will use this value rather than snps,pbl.
- snps,aal Address-Aligned Beats
- snps,fixed-burst Program the DMA to use the fixed burst mode
- snps,mixed-burst Program the DMA to use the mixed burst mode
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 014f4f756cb7..6add57374f70 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -153,7 +153,8 @@ Where:
o pbl: the Programmable Burst Length is maximum number of beats to
be transferred in one DMA transaction.
GMAC also enables the 4xPBL by default.
- o fixed_burst/mixed_burst/burst_len
+ o txpbl/rxpbl: GMAC and newer supports independent DMA pbl for tx/rx.
+ o fixed_burst/mixed_burst/aal
o clk_csr: fixed CSR Clock range selection.
o has_gmac: uses the GMAC core.
o enh_desc: if sets the MAC will use the enhanced descriptor structure.
@@ -205,16 +206,22 @@ tuned according to the HW capabilities.
struct stmmac_dma_cfg {
int pbl;
+ int txpbl;
+ int rxpbl;
int fixed_burst;
- int burst_len_supported;
+ int mixed_burst;
+ bool aal;
};
Where:
- o pbl: Programmable Burst Length
+ o pbl: Programmable Burst Length (tx and rx)
+ o txpbl: Transmit Programmable Burst Length. Only for GMAC and newer.
+ If set, DMA tx will use this value rather than pbl.
+ o rxpbl: Receive Programmable Burst Length. Only for GMAC and newer.
+ If set, DMA rx will use this value rather than pbl.
o fixed_burst: program the DMA to use the fixed burst mode
- o burst_len: this is the value we put in the register
- supported values are provided as macros in
- linux/stmmac.h header file.
+ o mixed_burst: program the DMA to use the mixed burst mode
+ o aal: Address-Aligned Beats
---
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index 01d0d0f315e5..1dd34fb4c1a9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -87,20 +87,20 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
u32 dma_tx, u32 dma_rx, int atds)
{
u32 value = readl(ioaddr + DMA_BUS_MODE);
+ int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
+ int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
/*
* Set the DMA PBL (Programmable Burst Length) mode.
*
* Note: before stmmac core 3.50 this mode bit was 4xPBL, and
* post 3.5 mode bit acts as 8*PBL.
- *
- * This configuration doesn't take care about the Separate PBL
- * so only the bits: 13-8 are programmed with the PBL passed from the
- * platform.
*/
value |= DMA_BUS_MODE_MAXPBL;
- value &= ~DMA_BUS_MODE_PBL_MASK;
- value |= (dma_cfg->pbl << DMA_BUS_MODE_PBL_SHIFT);
+ value |= DMA_BUS_MODE_USP;
+ value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK);
+ value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT);
+ value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
/* Set the Fixed burst mode */
if (dma_cfg->fixed_burst)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 0946546d6dcd..0bf47825bfeb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -69,11 +69,14 @@ static void dwmac4_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
writel(value, ioaddr + DMA_SYS_BUS_MODE);
}
-static void dwmac4_dma_init_channel(void __iomem *ioaddr, int pbl,
+static void dwmac4_dma_init_channel(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg,
u32 dma_tx_phy, u32 dma_rx_phy,
u32 channel)
{
u32 value;
+ int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
+ int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
/* set PBL for each channels. Currently we affect same configuration
* on each channel
@@ -83,11 +86,11 @@ static void dwmac4_dma_init_channel(void __iomem *ioaddr, int pbl,
writel(value, ioaddr + DMA_CHAN_CONTROL(channel));
value = readl(ioaddr + DMA_CHAN_TX_CONTROL(channel));
- value = value | (pbl << DMA_BUS_MODE_PBL_SHIFT);
+ value = value | (txpbl << DMA_BUS_MODE_PBL_SHIFT);
writel(value, ioaddr + DMA_CHAN_TX_CONTROL(channel));
value = readl(ioaddr + DMA_CHAN_RX_CONTROL(channel));
- value = value | (pbl << DMA_BUS_MODE_RPBL_SHIFT);
+ value = value | (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
writel(value, ioaddr + DMA_CHAN_RX_CONTROL(channel));
/* Mask interrupts by writing to CSR7 */
@@ -118,8 +121,7 @@ static void dwmac4_dma_init(void __iomem *ioaddr,
writel(value, ioaddr + DMA_SYS_BUS_MODE);
for (i = 0; i < DMA_CHANNEL_NB_MAX; i++)
- dwmac4_dma_init_channel(ioaddr, dma_cfg->pbl,
- dma_tx, dma_rx, i);
+ dwmac4_dma_init_channel(ioaddr, dma_cfg, dma_tx, dma_rx, i);
}
static void _dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 channel)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 59e1740479fc..55cac48897f6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -310,6 +310,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
plat->dma_cfg = dma_cfg;
of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+ of_property_read_u32(np, "snps,txpbl", &dma_cfg->txpbl);
+ of_property_read_u32(np, "snps,rxpbl", &dma_cfg->rxpbl);
dma_cfg->aal = of_property_read_bool(np, "snps,aal");
dma_cfg->fixed_burst = of_property_read_bool(np, "snps,fixed-burst");
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 3537fb33cc90..e6d7a5940819 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -88,6 +88,8 @@ struct stmmac_mdio_bus_data {
struct stmmac_dma_cfg {
int pbl;
+ int txpbl;
+ int rxpbl;
int fixed_burst;
int mixed_burst;
bool aal;
--
2.1.4
^ permalink raw reply related
* Re: [PATCH v3 -next 2/2] ARM: dts: sunxi: add support for Orange Pi Zero board
From: Maxime Ripard @ 2016-12-05 9:12 UTC (permalink / raw)
To: Icenowy Zheng
Cc: Jernej Skrabec, linux-sunxi, arnd-r2nGTMty4D4,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
vishnupatekar0510-Re5JQEeQqe8AvxtiuMwx3w,
andre.przywara-5wv7dgnIgG8,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, hdegoede-H+wXaHxf7aLQT0dZR+AlfA,
wens-jdAy2FN1RRM, robh+dt-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20161203162455.OlDm27ch-jDEamKawf7I0PDqKvflMoHmW9unr2Ajn@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 1099 bytes --]
Hi Icenowy,
On Sat, Dec 03, 2016 at 09:24:19PM +0800, Icenowy Zheng wrote:
> <p dir="ltr"><br>
> 2016年12月3日 下午5:43于 Jernej Skrabec <jernej.skrabec-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>写道:<br>
> ><br>
> > Hi,<br>
> ><br>
> > Dne petek, 02. december 2016 17.42.04 UTC+1 je oseba Chen-Yu Tsai napisala:<br>
> >><br>
> >> Hi, <br>
> >><br>
> >> On Fri, Dec 2, 2016 at 11:05 PM, Icenowy Zheng <ice...-ymACFijhrKM@public.gmane.org> wrote: <br>
> >> > Orange Pi Zero is a board that came with the new Allwinner H2+ SoC and a <br>
> >> > SDIO Wi-Fi chip by Allwinner (XR819). <br>
> >> > <br>
> >> > Add a device tree file for it. <br>
> >> > <br>
> >> > Signed-off-by: Icenowy Zheng <ice...-ymACFijhrKM@public.gmane.org> <br>
Please make sure to disable the HTML replies, this is what your mail
looks like on a !HTML MUA :)
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH v2 0/6] net: stmmac: make DMA programmable burst length more configurable
From: Niklas Cassel @ 2016-12-05 9:10 UTC (permalink / raw)
To: netdev; +Cc: Niklas Cassel, devicetree, linux-kernel, linux-doc
From: Niklas Cassel <niklas.cassel@axis.com>
Make DMA programmable burst length more configurable in the stmmac driver.
This is done by adding support for independent pbl for tx/rx through DT.
More fine grained tuning of pbl is possible thanks to a DT property saying
that we should NOT multiply pbl values by x8/x4 in hardware.
All new DT properties are optional, and created in a way that it will not
affect any existing DT configurations.
Changes since V1:
Created cover-letter.
Rebased patch set against next-20161205, since conflicting patches to
stmmac_platform.c has been merged since V1.
Niklas Cassel (6):
net: stmmac: return error if no DMA configuration is found
net: stmmac: simplify the common DMA init API
net: stmmac: stmmac_platform: fix parsing of DT binding
net: stmmac: dwmac1000: fix define DMA_BUS_MODE_RPBL_MASK
net: stmmac: add support for independent DMA pbl for tx/rx
net: smmac: allow configuring lower pbl values
Documentation/devicetree/bindings/net/stmmac.txt | 8 +++++-
Documentation/networking/stmmac.txt | 24 ++++++++++++-----
drivers/net/ethernet/stmicro/stmmac/common.h | 4 +--
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 2 +-
.../net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 26 ++++++++++---------
drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c | 7 ++---
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 25 ++++++++++--------
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 17 ++++++------
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 2 ++
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 30 ++++++++++++----------
include/linux/stmmac.h | 3 +++
11 files changed, 89 insertions(+), 59 deletions(-)
--
2.1.4
^ permalink raw reply
* Re: [PATCH 1/2] devicetree: i2c-hid: Add regulator support
From: Benjamin Tissoires @ 2016-12-05 9:08 UTC (permalink / raw)
To: Brian Norris
Cc: Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA, Dmitry Torokhov,
Jiri Kosina, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Doug Anderson,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Rob Herring,
linux-input-u79uwXL29TY76Z2rM5mHXA, Caesar Wang
In-Reply-To: <1480717140-14558-1-git-send-email-briannorris-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
On Dec 02 2016 or thereabouts, Brian Norris wrote:
> From: Caesar Wang <wxt-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
>
> Document a "vdd-supply" and an initialization delay. Can be used for
> powering on/off a HID.
>
> Signed-off-by: Caesar Wang <wxt-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Cc: Jiri Kosina <jikos-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Cc: linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Signed-off-by: Brian Norris <briannorris-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> ---
> v2:
> * add compatible property for wacom, per Rob's request
> * name the regulator property specifically (VDD)
>
> v3:
> * remove wacom property, per Benjamin's request
> * add delay property
>
> v4: no change
> ---
> Documentation/devicetree/bindings/input/hid-over-i2c.txt | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/input/hid-over-i2c.txt b/Documentation/devicetree/bindings/input/hid-over-i2c.txt
> index 488edcb264c4..1ea290167652 100644
> --- a/Documentation/devicetree/bindings/input/hid-over-i2c.txt
> +++ b/Documentation/devicetree/bindings/input/hid-over-i2c.txt
> @@ -17,6 +17,11 @@ Required properties:
> - interrupt-parent: the phandle for the interrupt controller
> - interrupts: interrupt line
>
> +Optional properties:
> +- vdd-supply: phandle of the regulator that provides the supply voltage.
> +- init-delay-ms: time required by the device after power-on before it is ready
> + for communication.
Nitpick: maybe we should say that the power-on applies to the vdd-supply
parameter, not the SET_POWER HID command. I am just worried people will
misuse this parameter.
Otherwise, Acked-by: Benjamin Tissoires <benjamin.tissoires-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> +
> Example:
>
> i2c-hid-dev@2c {
> --
> 2.8.0.rc3.226.g39d4020
>
^ permalink raw reply
* Re: [PATCH v2 2/3] ARM: dts: sunxi: add support for Orange Pi Zero board
From: Maxime Ripard @ 2016-12-05 9:05 UTC (permalink / raw)
To: Andre Przywara
Cc: Mark Rutland, devicetree@vger.kernel.org, Vishnu Patekar,
Arnd Bergmann, Jonathan Corbet, linux-doc@vger.kernel.org,
Russell King, linux-kernel@vger.kernel.org, Hans de Goede,
Chen-Yu Tsai, Icenowy Zheng, linux-arm-kernel@lists.infradead.org
In-Reply-To: <324c8820-aeea-3fad-0e02-1bdb8f675677@arm.com>
[-- Attachment #1.1: Type: text/plain, Size: 3972 bytes --]
On Fri, Dec 02, 2016 at 04:10:46PM +0000, Andre Przywara wrote:
> Hi,
>
> On 02/12/16 14:32, Icenowy Zheng wrote:
> >
> >
> > 02.12.2016, 22:30, "Hans de Goede" <hdegoede@redhat.com>:
> >> Hi,
> >>
> >> On 02-12-16 15:22, Icenowy Zheng wrote:
> >>> 01.12.2016, 17:36, "Maxime Ripard" <maxime.ripard@free-electrons.com>:
> >>>> On Mon, Nov 28, 2016 at 12:29:07AM +0000, André Przywara wrote:
> >>>>> > Something more interesting happened.
> >>>>> >
> >>>>> > Xunlong made a add-on board for Orange Pi Zero, which exposes the
> >>>>> > two USB Controllers exported at expansion bus as USB Type-A
> >>>>> > connectors.
> >>>>> >
> >>>>> > Also it exposes a analog A/V jack and a microphone.
> >>>>> >
> >>>>> > Should I enable {e,o}hci{2.3} in the device tree?
> >>>>>
> >>>>> Actually we should do this regardless of this extension board. The USB
> >>>>> pins are not multiplexed and are exposed on user accessible pins (just
> >>>>> not soldered, but that's a detail), so I think they qualify for DT
> >>>>> enablement. And even if a user can't use them, it doesn't hurt to have
> >>>>> them (since they are not multiplexed).
> >>>>
> >>>> My main concern about this is that we'll leave regulators enabled by
> >>>> default, for a minority of users. And that minority will prevent to do
> >>>> a proper power management when the times come since we'll have to keep
> >>>> that behaviour forever.
> >>>
> >>> I think these users can add a 'fdt set /xxx/xxx status "disabled" ' .
> >>
> >> I don't think that will be necessary I'm pretty sure these extra usb
> >> ports do not have a regulator for the Vbus, they just hook directly
> >> to the 5V rail, can someone with a schematic check ?
> >
> > We seems to have still no schematics for the add-on board.
>
> From looking at the picture of that expansion board on the Aliexpress
> page and chasing the tracks, there is clearly no voltage regulator on
> there, it's just passive components. The 5V pin from the headers is
> routed forth and back between the two layers via some vias directly to
> the 5V pins of the USB sockets.
>
> > But something is sure is that there's no any regulator-related pins
> > on the add-on pinout. There's only USB DM and DP pins.
> >
> > So the Vbus must be directly connected to +5V.
>
> So yes, it is.
>
> But I think the question is moot anyways, since we don't provide DT
> support for that add-on board at that point anyways.
> One could imagine another board, though, which has regulators switched
> by GPIOs, but that would be their problem and they would have regulators
> specified in their specific DT snippet, then.
>
> So to summarize:
> - For that specific Orange Pi Zero board which we discuss the DT for
> there is no regulator support for the additional USB ports. Thus nothing
> we could turn off to save power.
> - A user could just take these USB brackets with pin headers that are so
> common in PCs to connect additional USB ports to the back of the box.
> One just needs to re-sort the pins, which is a matter of a minute.
> - As long as we don't provide any easy way of handling DT changes, we
> should enable the USB ports for the sake of the users of either those
> brackets or the expansion board. Any more sophisticated USB expansion
> board with regulators would need to amend the DT anyway.
I disagree with this. We already have different ways of changing the
DT at runtime, and even if we didn't I'd still disagree. Once you add
that, there's simply no going back. Saying "let's enable it and we'll
figure it out later" doesn't work, and is essentially a "enable it".
So what you're suggesting is to have those regulators enabled forever,
which might be the case on that board anyway, but definitely shouldn't
be policy.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 2/2] arm: dts: sun8i: reuse the uart1 node of iNet D978 rev2 board
From: Icenowy Zheng @ 2016-12-05 9:03 UTC (permalink / raw)
To: Maxime Ripard
Cc: Hans de Goede, linux-kernel,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
devicetree-u79uwXL29TY76Z2rM5mHXA, Chen-Yu Tsai
2016年12月5日 16:50于 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>写道:
>
> On Fri, Dec 02, 2016 at 11:19:13PM +0800, Icenowy Zheng wrote:
> > As a uart1 node is added into sun8i-reference-design-tablet.dtsi, simply
> > use it in iNet D978 rev2 device tree.
> >
> > Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
>
> I'd like to see more consolidation before that change is needed. If we
> find more boards using that, it will make sense, but for a single
> board it's not worth it.
At least 2~3 Q8 A33 tablets in #linux-sunxi are found to have rtl8703as, which contains UART bluetooth. (including mine)
In fact, what I want to do is to get the node ready-to-be-okay in Q8 dts, so it can be enabled by either u-boot command or (theortically) Hans de Goede's q8-hardwaremgr, just like what is done at touchscreen node.
>
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
--
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 v3 7/7] ARM: dts: stm32: add stm32 general purpose timer driver in DT
From: Lee Jones @ 2016-12-05 8:54 UTC (permalink / raw)
To: Jonathan Cameron
Cc: mark.rutland, devicetree, linaro-kernel, lars, alexandre.torgue,
linux-pwm, linux-iio, pmeerw, arnaud.pouliquen, linux-kernel,
robh+dt, thierry.reding, Benjamin Gaignard, knaack.h,
gerald.baeza, fabrice.gasnier, linus.walleij, linux-arm-kernel,
Benjamin Gaignard
In-Reply-To: <14837e15-07bb-39e5-b5b6-39a7dfb9130f@kernel.org>
On Sat, 03 Dec 2016, Jonathan Cameron wrote:
> On 02/12/16 13:22, Lee Jones wrote:
> > On Fri, 02 Dec 2016, Benjamin Gaignard wrote:
> >
> >> Add general purpose timers and it sub-nodes into DT for stm32f4.
> >> Define and enable pwm1 and pwm3 for stm32f469 discovery board
> >>
> >> version 3:
> >> - use "st,stm32-timer-trigger" in DT
> >>
> >> version 2:
> >> - use parameters to describe hardware capabilities
> >> - do not use references for pwm and iio timer subnodes
> >>
> >> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> >> ---
> >> arch/arm/boot/dts/stm32f429.dtsi | 333 +++++++++++++++++++++++++++++++++-
> >> arch/arm/boot/dts/stm32f469-disco.dts | 28 +++
> >> 2 files changed, 360 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
> >> index bca491d..8c50d03 100644
> >> --- a/arch/arm/boot/dts/stm32f429.dtsi
> >> +++ b/arch/arm/boot/dts/stm32f429.dtsi
> >> @@ -48,7 +48,7 @@
> >> #include "skeleton.dtsi"
> >> #include "armv7-m.dtsi"
> >> #include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
> >> -
> >> +#include <dt-bindings/iio/timer/st,stm32-timer-triggers.h>
> >> / {
> >> clocks {
> >> clk_hse: clk-hse {
> >> @@ -355,6 +355,21 @@
> >> slew-rate = <2>;
> >> };
> >> };
> >> +
> >> + pwm1_pins: pwm@1 {
> >> + pins {
> >> + pinmux = <STM32F429_PA8_FUNC_TIM1_CH1>,
> >> + <STM32F429_PB13_FUNC_TIM1_CH1N>,
> >> + <STM32F429_PB12_FUNC_TIM1_BKIN>;
> >> + };
> >> + };
> >> +
> >> + pwm3_pins: pwm@3 {
> >> + pins {
> >> + pinmux = <STM32F429_PB4_FUNC_TIM3_CH1>,
> >> + <STM32F429_PB5_FUNC_TIM3_CH2>;
> >> + };
> >> + };
> >> };
> >>
> >> rcc: rcc@40023810 {
> >> @@ -426,6 +441,322 @@
> >> interrupts = <80>;
> >> clocks = <&rcc 0 38>;
> >> };
> >> +
> >> + gptimer1: gptimer1@40010000 {
> >
> > timer@xxxxxxx
> >
> > Node names should be generic and not numbered.
> >
> > I suggest that this isn't actually a timer either. Is contains a
> > timer (and a PWM), but in it's completeness it is not a timer per
> > say.
> That's just mean ;) At least suggest an alternative?
>
> stm32-gptimerish-magic?
Perfect! ;)
I already did:
https://lkml.org/lkml/2016/11/23/131
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40010000 0x400>;
> >> + clocks = <&rcc 0 160>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm1@0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <4>;
> >> + st,breakinput;
> >> + st,complementary;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer1@0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <27>;
> >> + st,input-triggers-names = TIM5_TRGO,
> >> + TIM2_TRGO,
> >> + TIM4_TRGO,
> >> + TIM3_TRGO;
> >
> > I'm still dubious with matching by strings.
> >
> > I'll take a look at the C code to see what the alternatives could be.
> >
> >> + st,output-triggers-names = TIM1_TRGO,
> >> + TIM1_CH1,
> >> + TIM1_CH2,
> >> + TIM1_CH3,
> >> + TIM1_CH4;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer2: gptimer2@40000000 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40000000 0x400>;
> >> + clocks = <&rcc 0 128>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm2@0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <4>;
> >> + st,32bits-counter;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer2@0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <28>;
> >> + st,input-triggers-names = TIM1_TRGO,
> >> + TIM8_TRGO,
> >> + TIM3_TRGO,
> >> + TIM4_TRGO;
> >> + st,output-triggers-names = TIM2_TRGO,
> >> + TIM2_CH1,
> >> + TIM2_CH2,
> >> + TIM2_CH3,
> >> + TIM2_CH4;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer3: gptimer3@40000400 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40000400 0x400>;
> >> + clocks = <&rcc 0 129>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm3@0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <4>;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer3@0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <29>;
> >> + st,input-triggers-names = TIM1_TRGO,
> >> + TIM8_TRGO,
> >> + TIM5_TRGO,
> >> + TIM4_TRGO;
> >> + st,output-triggers-names = TIM3_TRGO,
> >> + TIM3_CH1,
> >> + TIM3_CH2,
> >> + TIM3_CH3,
> >> + TIM3_CH4;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer4: gptimer4@40000800 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40000800 0x400>;
> >> + clocks = <&rcc 0 130>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm4@0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <4>;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer4@0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <30>;
> >> + st,input-triggers-names = TIM1_TRGO,
> >> + TIM2_TRGO,
> >> + TIM3_TRGO,
> >> + TIM8_TRGO;
> >> + st,output-triggers-names = TIM4_TRGO,
> >> + TIM4_CH1,
> >> + TIM4_CH2,
> >> + TIM4_CH3,
> >> + TIM4_CH4;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer5: gptimer5@40000C00 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40000C00 0x400>;
> >> + clocks = <&rcc 0 131>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm5@0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <4>;
> >> + st,32bits-counter;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer5@0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <50>;
> >> + st,input-triggers-names = TIM2_TRGO,
> >> + TIM3_TRGO,
> >> + TIM4_TRGO,
> >> + TIM8_TRGO;
> >> + st,output-triggers-names = TIM5_TRGO,
> >> + TIM5_CH1,
> >> + TIM5_CH2,
> >> + TIM5_CH3,
> >> + TIM5_CH4;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer6: gptimer6@40001000 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40001000 0x400>;
> >> + clocks = <&rcc 0 132>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + timer6@0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <54>;
> >> + st,output-triggers-names = TIM6_TRGO;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer7: gptimer7@40001400 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40001400 0x400>;
> >> + clocks = <&rcc 0 133>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + timer7@0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <55>;
> >> + st,output-triggers-names = TIM7_TRGO;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer8: gptimer8@40010400 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40010400 0x400>;
> >> + clocks = <&rcc 0 161>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm8@0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <4>;
> >> + st,complementary;
> >> + st,breakinput;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer8@0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <46>;
> >> + st,input-triggers-names = TIM1_TRGO,
> >> + TIM2_TRGO,
> >> + TIM4_TRGO,
> >> + TIM5_TRGO;
> >> + st,output-triggers-names = TIM8_TRGO,
> >> + TIM8_CH1,
> >> + TIM8_CH2,
> >> + TIM8_CH3,
> >> + TIM8_CH4;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer9: gptimer9@40014000 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40014000 0x400>;
> >> + clocks = <&rcc 0 176>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm9@0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <2>;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer9@0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <24>;
> >> + st,input-triggers-names = TIM2_TRGO,
> >> + TIM3_TRGO;
> >> + st,output-triggers-names = TIM9_TRGO,
> >> + TIM9_CH1,
> >> + TIM9_CH2;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer10: gptimer10@40014400 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40014400 0x400>;
> >> + clocks = <&rcc 0 177>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm10@0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <1>;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer11: gptimer11@40014800 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40014800 0x400>;
> >> + clocks = <&rcc 0 178>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm11@0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <1>;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer12: gptimer12@40001800 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40001800 0x400>;
> >> + clocks = <&rcc 0 134>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm12@0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <2>;
> >> + status = "disabled";
> >> + };
> >> +
> >> + timer12@0 {
> >> + compatible = "st,stm32-timer-trigger";
> >> + interrupts = <43>;
> >> + st,input-triggers-names = TIM4_TRGO,
> >> + TIM5_TRGO;
> >> + st,output-triggers-names = TIM12_TRGO,
> >> + TIM12_CH1,
> >> + TIM12_CH2;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer13: gptimer13@40001C00 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40001C00 0x400>;
> >> + clocks = <&rcc 0 135>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm13@0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <1>;
> >> + status = "disabled";
> >> + };
> >> + };
> >> +
> >> + gptimer14: gptimer14@40002000 {
> >> + compatible = "st,stm32-gptimer";
> >> + reg = <0x40002000 0x400>;
> >> + clocks = <&rcc 0 136>;
> >> + clock-names = "clk_int";
> >> + status = "disabled";
> >> +
> >> + pwm14@0 {
> >> + compatible = "st,stm32-pwm";
> >> + st,pwm-num-chan = <1>;
> >> + status = "disabled";
> >> + };
> >> + };
> >> };
> >> };
> >>
> >> diff --git a/arch/arm/boot/dts/stm32f469-disco.dts b/arch/arm/boot/dts/stm32f469-disco.dts
> >> index 8a163d7..df4ca7e 100644
> >> --- a/arch/arm/boot/dts/stm32f469-disco.dts
> >> +++ b/arch/arm/boot/dts/stm32f469-disco.dts
> >> @@ -81,3 +81,31 @@
> >> &usart3 {
> >> status = "okay";
> >> };
> >> +
> >> +&gptimer1 {
> >> + status = "okay";
> >> +
> >> + pwm1@0 {
> >> + pinctrl-0 = <&pwm1_pins>;
> >> + pinctrl-names = "default";
> >> + status = "okay";
> >> + };
> >> +
> >> + timer1@0 {
> >> + status = "okay";
> >> + };
> >> +};
> >
> > This is a much *better* format than before.
> >
> > I still don't like the '&' syntax though.
> >
> >> +&gptimer3 {
> >> + status = "okay";
> >> +
> >> + pwm3@0 {
> >> + pinctrl-0 = <&pwm3_pins>;
> >> + pinctrl-names = "default";
> >> + status = "okay";
> >> + };
> >> +
> >> + timer3@0 {
> >> + status = "okay";
> >> + };
> >> +};
> >
>
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2] arm64: dts: zx: add pcu_domain node for zx296718
From: Shawn Guo @ 2016-12-05 8:54 UTC (permalink / raw)
To: Baoyou Xie
Cc: mark.rutland, devicetree, catalin.marinas, xie.baoyou,
will.deacon, linux-kernel, robh+dt, chen.chaokai, viresh.kumar,
wang.qiang01, jun.nie, linux-arm-kernel
In-Reply-To: <1480925871-20855-1-git-send-email-baoyou.xie@linaro.org>
On Mon, Dec 05, 2016 at 04:17:51PM +0800, Baoyou Xie wrote:
> This patch adds the pcu_domain node, so it can be used
> by zte-soc's power domain driver.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
I'm fine with the patch itself, but I need to wait the driver and
bindings being accepted to apply it.
Shawn
> ---
> arch/arm64/boot/dts/zte/zx296718.dtsi | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/zte/zx296718.dtsi b/arch/arm64/boot/dts/zte/zx296718.dtsi
> index b44d1d1..1aa0587 100644
> --- a/arch/arm64/boot/dts/zte/zx296718.dtsi
> +++ b/arch/arm64/boot/dts/zte/zx296718.dtsi
> @@ -302,6 +302,11 @@
> reg = <0x116000 0x1000>;
> };
>
> + pcu_domain: pcu@117000 {
> + compatible = "zte,zx296718-pcu";
> + reg = <0x00117000 0x1000>;
> + };
> +
> uart0: uart@11f000 {
> compatible = "arm,pl011", "arm,primecell";
> arm,primecell-periphid = <0x001feffe>;
> --
> 2.7.4
>
^ permalink raw reply
* Re: [PATCH v2 2/3] ARM: dts: sunxi: add support for Orange Pi Zero board
From: Maxime Ripard @ 2016-12-05 8:52 UTC (permalink / raw)
To: Icenowy Zheng
Cc: Mark Rutland, devicetree@vger.kernel.org, Vishnu Patekar,
Arnd Bergmann, Jonathan Corbet, André Przywara,
linux-doc@vger.kernel.org, Russell King,
linux-kernel@vger.kernel.org, Hans de Goede, Chen-Yu Tsai,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <11498641480688550@web2g.yandex.ru>
[-- Attachment #1.1: Type: text/plain, Size: 1694 bytes --]
On Fri, Dec 02, 2016 at 10:22:30PM +0800, Icenowy Zheng wrote:
>
>
> 01.12.2016, 17:36, "Maxime Ripard" <maxime.ripard@free-electrons.com>:
> > On Mon, Nov 28, 2016 at 12:29:07AM +0000, André Przywara wrote:
> >> > Something more interesting happened.
> >> >
> >> > Xunlong made a add-on board for Orange Pi Zero, which exposes the
> >> > two USB Controllers exported at expansion bus as USB Type-A
> >> > connectors.
> >> >
> >> > Also it exposes a analog A/V jack and a microphone.
> >> >
> >> > Should I enable {e,o}hci{2.3} in the device tree?
> >>
> >> Actually we should do this regardless of this extension board. The USB
> >> pins are not multiplexed and are exposed on user accessible pins (just
> >> not soldered, but that's a detail), so I think they qualify for DT
> >> enablement. And even if a user can't use them, it doesn't hurt to have
> >> them (since they are not multiplexed).
> >
> > My main concern about this is that we'll leave regulators enabled by
> > default, for a minority of users. And that minority will prevent to do
> > a proper power management when the times come since we'll have to keep
> > that behaviour forever.
>
> I think these users can add a 'fdt set /xxx/xxx status "disabled" ' .
You can't ask that from the majority of users. These users will take
debian or fedora, install it, and expect everything to work
properly. I would make the opposite argument actually. If someone is
knowledgeable enough to solder the USB pins a connector, then (s)he'll
be able to make that u-boot call.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v1 1/2] Add crypto driver support for some MediaTek chips
From: Corentin Labbe @ 2016-12-05 8:52 UTC (permalink / raw)
To: Ryder Lee
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Herbert Xu, Sean Wang,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Roy Luo,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-crypto-u79uwXL29TY76Z2rM5mHXA, Matthias Brugger,
David S. Miller,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1480921284-45827-2-git-send-email-ryder.lee-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Hello
I have two minor comment.
On Mon, Dec 05, 2016 at 03:01:23PM +0800, Ryder Lee wrote:
> This adds support for the MediaTek hardware accelerator on
> mt7623/mt2701/mt8521p SoC.
>
> This driver currently implement:
> - SHA1 and SHA2 family(HMAC) hash alogrithms.
There is a typo for algorithms.
[...]
> +/**
> + * struct mtk_desc - DMA descriptor
> + * @hdr: the descriptor control header
> + * @buf: DMA address of input buffer segment
> + * @ct: DMA address of command token that control operation flow
> + * @ct_hdr: the command token control header
> + * @tag: the user-defined field
> + * @tfm: DMA address of transform state
> + * @bound: align descriptors offset boundary
> + *
> + * Structure passed to the crypto engine to describe where source
> + * data needs to be fetched and how it needs to be processed.
> + */
> +struct mtk_desc {
> + u32 hdr;
> + u32 buf;
> + u32 ct;
> + u32 ct_hdr;
> + u32 tag;
> + u32 tfm;
> + u32 bound[2];
> +};
Do you have tested this descriptor with BE/LE kernel ?
Regards
Corentin Labbe
^ permalink raw reply
* Re: [PATCH 2/2] arm: dts: sun8i: reuse the uart1 node of iNet D978 rev2 board
From: Maxime Ripard @ 2016-12-05 8:50 UTC (permalink / raw)
To: Icenowy Zheng
Cc: Chen-Yu Tsai, Hans de Goede, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20161202151913.38892-2-icenowy-ymACFijhrKM@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 520 bytes --]
On Fri, Dec 02, 2016 at 11:19:13PM +0800, Icenowy Zheng wrote:
> As a uart1 node is added into sun8i-reference-design-tablet.dtsi, simply
> use it in iNet D978 rev2 device tree.
>
> Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
I'd like to see more consolidation before that change is needed. If we
find more boards using that, it will make sense, but for a single
board it's not worth it.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* Re: [PATCH v6 1/2] mtd: arasan: Add device tree binding documentation
From: Boris Brezillon @ 2016-12-05 8:36 UTC (permalink / raw)
To: Marek Vasut
Cc: Punnaiah Choudary Kalluri, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
computersforpeace-Re5JQEeQqe8AvxtiuMwx3w, richard-/L3Ra7n9ekc,
cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, michals-gjFFaj9aHVfQT0dZR+AlfA,
kalluripunnaiahchoudary-Re5JQEeQqe8AvxtiuMwx3w,
kpc528-Re5JQEeQqe8AvxtiuMwx3w, Punnaiah Choudary Kalluri
In-Reply-To: <74842d92-840d-a7c2-fb1b-ddab1ac2cf42-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On Mon, 5 Dec 2016 05:25:54 +0100
Marek Vasut <marek.vasut-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On 12/05/2016 05:11 AM, Punnaiah Choudary Kalluri wrote:
> > This patch adds the dts binding document for arasan nand flash
> > controller.
> >
> > Signed-off-by: Punnaiah Choudary Kalluri <punnaia-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>
> > Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> > ---
> > changes in v6:
> > - Removed num-cs property
> > - Separated nandchip from nand controller
> > changes in v5:
> > - None
> > Changes in v4:
> > - Added num-cs property
> > - Added clock support
> > Changes in v3:
> > - None
> > Changes in v2:
> > - None
> > ---
> > .../devicetree/bindings/mtd/arasan_nfc.txt | 38 ++++++++++++++++++++++
> > 1 file changed, 38 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/mtd/arasan_nfc.txt
> >
> > diff --git a/Documentation/devicetree/bindings/mtd/arasan_nfc.txt b/Documentation/devicetree/bindings/mtd/arasan_nfc.txt
> > new file mode 100644
> > index 0000000..dcbe7ad
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mtd/arasan_nfc.txt
> > @@ -0,0 +1,38 @@
> > +Arasan Nand Flash Controller with ONFI 3.1 support
>
> Arasan NAND Flash ...
>
> > +Required properties:
> > +- compatible: Should be "arasan,nfc-v3p10"
>
> This v3p10 looks like version 3 patchlevel 10, but shouldn't we have
> some fallback option which doesn't encode IP version in the compat
> string ?
Not necessarily. Usually you define a generic compatible when you have
other reliable means to detect the IP version (a version register for
example).
If you can't detect that at runtime, then providing only specific
compatible strings is a good solution to avoid breaking the DT ABI.
>
> Also, shouldn't quirks be handled by DT props instead of effectively
> encoding them into the compatible string ?
Well, from my experience, it's better to hide as much as possible
behind the compatible. This way, if new quirks are needed for a
specific revision, you can update the driver without having to change
the DT.
>
> > +- reg: Memory map for module access
> > +- interrupt-parent: Interrupt controller the interrupt is routed through
> > +- interrupts: Should contain the interrupt for the device
> > +- clock-name: List of input clocks - "clk_sys", "clk_flash"
> > + (See clock bindings for details)
> > +- clocks: Clock phandles (see clock bindings for details)
> > +
> > +Optional properties:
> > +- arasan,has-mdma: Enables Dma support
>
> 'Enables DMA support' , with DMA in caps.
>
> > +for nand partition information please refer the below file
>
> For NAND ...
>
> > +Documentation/devicetree/bindings/mtd/partition.txt
> > +
> > +Example:
> > + nand0: nand@ff100000 {
> > + compatible = "arasan,nfc-v3p10"
> > + reg = <0x0 0xff100000 0x1000>;
> > + clock-name = "clk_sys", "clk_flash"
> > + clocks = <&misc_clk &misc_clk>;
> > + interrupt-parent = <&gic>;
> > + interrupts = <0 14 4>;
> > + arasan,has-mdma;
> > + #address-cells = <1>;
> > + #size-cells = <0>
> > +
> > + nand@0 {
> > + reg = <0>
> > + partition@0 {
> > + label = "filesystem";
> > + reg = <0x0 0x0 0x1000000>;
> > + };
> > + (...)
> > + };
> > + };
> >
>
>
--
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 3/7] PWM: add pwm-stm32 DT bindings
From: Lee Jones @ 2016-12-05 8:35 UTC (permalink / raw)
To: Thierry Reding
Cc: Benjamin Gaignard, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, alexandre.torgue-qxv4g6HH51o,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-pwm-u79uwXL29TY76Z2rM5mHXA, jic23-DgEjT+Ai2ygdnm+yROfE0A,
knaack.h-Mmb7MZpHnFY, lars-Qo5EllUWu/uELgA04lAiVw,
pmeerw-jW+XmwGofnusTnJN9+BGXg, linux-iio-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
fabrice.gasnier-qxv4g6HH51o, gerald.baeza-qxv4g6HH51o,
arnaud.pouliquen-qxv4g6HH51o,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
linaro-kernel-cunTk1MwBs8s++Sfvej+rw, Benjamin Gaignard
In-Reply-To: <20161205065350.GA18069-EkSeR96xj6Pcmrwk2tT4+A@public.gmane.org>
On Mon, 05 Dec 2016, Thierry Reding wrote:
> On Fri, Dec 02, 2016 at 11:17:18AM +0100, Benjamin Gaignard wrote:
> > Define bindings for pwm-stm32
> >
> > version 2:
> > - use parameters instead of compatible of handle the hardware configuration
> >
> > Signed-off-by: Benjamin Gaignard <benjamin.gaignard-qxv4g6HH51o@public.gmane.org>
> > ---
> > .../devicetree/bindings/pwm/pwm-stm32.txt | 38 ++++++++++++++++++++++
> > 1 file changed, 38 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/pwm/pwm-stm32.txt
> >
> > diff --git a/Documentation/devicetree/bindings/pwm/pwm-stm32.txt b/Documentation/devicetree/bindings/pwm/pwm-stm32.txt
> > new file mode 100644
> > index 0000000..575b9fb
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/pwm/pwm-stm32.txt
> > @@ -0,0 +1,38 @@
> > +STMicroelectronics PWM driver bindings for STM32
>
> Technically this bindings describe devices, so "driver binding" is a
> somewhat odd wording. Perhaps:
>
> STMicroelectronics STM32 General Purpose Timer PWM bindings
>
> ?
>
> > +
> > +Must be a sub-node of STM32 general purpose timer driver
> > +Parent node properties are describe in ../mfd/stm32-general-purpose-timer.txt
>
> Again, "driver parent node" is odd. Perhaps:
>
> Must be a sub-node of an STM32 General Purpose Timer device tree
> node. See ../mfd/stm32-general-purpose-timer.txt for details about
> the parent node.
>
> ?
>
> > +Required parameters:
> > +- compatible: Must be "st,stm32-pwm"
> > +- pinctrl-names: Set to "default".
> > +- pinctrl-0: List of phandles pointing to pin configuration nodes
> > + for PWM module.
> > + For Pinctrl properties, please refer to [1].
>
> Your indentation and capitalization are inconsistent. Also, please refer
> to the pinctrl bindings by relative path and inline, rather than as a
> footnote reference.
>
> > +
> > +Optional parameters:
> > +- st,breakinput: Set if the hardware have break input capabilities
> > +- st,breakinput-polarity: Set break input polarity. Default is 0
> > + The value define the active polarity:
> > + - 0 (active LOW)
> > + - 1 (active HIGH)
>
> Could we fold these into a single property? If st,breakinput-polarity is
> not present it could simply mean that there is no break input, and if it
> is present you don't have to rely on a default.
>
> > +- st,pwm-num-chan: Number of available PWM channels. Default is 0.
>
> The pwm- prefix is rather redundant since the node is already named pwm.
> Why not simply st,channels? Or simply channels, since it's not really
> anything specific to this hardware.
>
> Come to think of it, might be worth having a discussion with our DT
> gurus about what their stance is on using the # as prefix for numbers
> (such as in #address-cells or #size-cells). This could be #channels to
> mark it more explicitly as representing a count.
Unfortunately that ship has sailed.
st,pwm-num-chan already exists (with your blessing). It's usually
suggested to reuse exiting properties when writing new bindings.
> > +- st,32bits-counter: Set if the hardware have a 32 bits counter
> > +- st,complementary: Set if the hardware have complementary output channels
>
> "hardware has" and also maybe mention explicitly that this is a boolean
> property. Otherwise people might be left wondering what it should be set
> to. Or maybe word this differently to imply that it's boolean:
>
> - st,32bits-counter: if present, the hardware has a 32 bit counter
> - st,complementary: if present, the hardware has a complementary
> output channel
>
> Thierry
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ 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