* Re: [PATCH v7 04/13] slimbus: core: Add slim controllers support
From: Vinod Koul @ 2017-11-27 5:52 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Greg KH, broonie-DgEjT+Ai2ygdnm+yROfE0A,
alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw, sdharia-sgV2jX0FEOL9JmXXK+q4OQ,
bp-l3A5Bk7waGM, poeschel-Xtl8qvBWbHwb1SvskN2V4Q,
treding-DDmLM1+adcrQT0dZR+AlfA,
andreas.noever-Re5JQEeQqe8AvxtiuMwx3w,
alan-VuQAYsv1563Yd54FQh9/CA,
mathieu.poirier-QSEj5FYQhm4dnm+yROfE0A, daniel-/w4YWyX8dFk,
jkosina-AlSwsSmVLrQ, sharon.dvir1-MQgwKvJRKlGYZoqfULhbRA,
joe-6d6DIl74uiNBDgjK7y7TUQ, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
james.hogan-1AXoQHu6uovQT0dZR+AlfA,
michael.opdenacker-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, pawel.moll-5wv7dgnIgG8,
mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4
In-Reply-To: <64797182-9244-e6e7-8044-dbc404cdda7c-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On Mon, Nov 20, 2017 at 06:47:58AM +0000, Srinivas Kandagatla wrote:
> >>>thanks for the comments.
> >>>
> >>>
> >>>On 16/11/17 16:42, Vinod Koul wrote:
> >>>>On Wed, Nov 15, 2017 at 02:10:34PM +0000,srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org wrote:
> >>>>
> >>>>>+static void slim_dev_release(struct device *dev)
> >>>>>+{
> >>>>>+ struct slim_device *sbdev = to_slim_device(dev);
> >>>>>+
> >>>>>+ put_device(sbdev->ctrl->dev);
> >>>>which device would that be?
> >>>This is controller device
> >>>
> >>>>>+static int slim_add_device(struct slim_controller *ctrl,
> >>>>>+ struct slim_device *sbdev,
> >>>>>+ struct device_node *node)
> >>>>>+{
> >>>>>+ sbdev->dev.bus = &slimbus_bus;
> >>>>>+ sbdev->dev.parent = ctrl->dev;
> >>>>>+ sbdev->dev.release = slim_dev_release;
> >>>>>+ sbdev->dev.driver = NULL;
> >>>>>+ sbdev->ctrl = ctrl;
> >>>>>+
> >>>>>+ dev_set_name(&sbdev->dev, "%x:%x:%x:%x",
> >>>>>+ sbdev->e_addr.manf_id,
> >>>>>+ sbdev->e_addr.prod_code,
> >>>>>+ sbdev->e_addr.dev_index,
> >>>>>+ sbdev->e_addr.instance);
> >>>>>+
> >>>>>+ get_device(ctrl->dev);
> >>>>is this controller device and you ensuring it doesnt go away while you have
> >>>>slaves on it?
> >>>Yes.
> >>I thought since you are marking ctrl->dev as parent, the device core should
> >>ensure that parent doesn't go off when you have child device?
> >>
> >>Greg, is that understanding correct, if so we may not need these calls.
> >That understanding should be correct, as the reference count is
> >incremented on the parent when a child is added.
> >
> >It would be trivial for this to be tested, and yes, I am pretty sure you
> >don't need this call.
>
> Thanks for suggestion, I will remove this in next version.
I think it might be helpful to test the assumption as Greg noted :)
--
~Vinod
--
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 v7 06/13] slimbus: Add messaging APIs to slimbus framework
From: Vinod Koul @ 2017-11-27 5:56 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: gregkh, broonie, alsa-devel, sdharia, bp, poeschel, treding,
andreas.noever, alan, mathieu.poirier, daniel, jkosina,
sharon.dvir1, joe, davem, james.hogan, michael.opdenacker,
robh+dt, pawel.moll, mark.rutland, devicetree, linux-kernel,
linux-arm-msm, arnd
In-Reply-To: <d58b8cca-7b28-75be-8081-dad6595f499d@linaro.org>
On Mon, Nov 20, 2017 at 06:47:52AM +0000, Srinivas Kandagatla wrote:
> >>+ * -ENOTCONN: If the transmitted message was not ACKed by destination
> >>+ * device.
> >
> >I am preferring ENODATA in SDW for this case, as Slaves didnt respond or
> >ACK.
> Isn't that a timeout error then.
>
> ENODATA is for "No data available", reporting ENODATA would be misleading.
Do you get a explict NACK or no response for this
>
> >
> >ENOTCONN is defined as /* Transport endpoint is not connected */ which is
> >not the case here, connected yes but not responded.
>
> Code as it is would not return this, so i will be deleting ENOTCONN from
> kernel doc.
ok
--
~Vinod
^ permalink raw reply
* Re: [PATCH 2/3] hwrng: exynos - add Samsung Exynos True RNG driver
From: Łukasz Stelmach @ 2017-11-27 7:23 UTC (permalink / raw)
To: PrasannaKumar Muralidharan
Cc: Rob Herring, Matt Mackall, Herbert Xu, Krzysztof Kozlowski,
devicetree, linux-crypto, linux-samsung-soc, linux-kernel,
Marek Szyprowski, Bartlomiej Zolnierkiewicz
In-Reply-To: <CANc+2y4=Eas-i0jRwgTxqFeAngpPMKoUjVwsXWeU7G24g4252w@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 630 bytes --]
It was <2017-11-24 pią 16:25>, when PrasannaKumar Muralidharan wrote:
>> +}
>> +
>> +static int exynos_trng_do_read(struct hwrng *rng, void *data, size_t max,
>> + bool wait)
>> +{
>> + struct exynos_trng_dev *trng;
>> + u32 val;
>> +
>> + max = max > (EXYNOS_TRNG_FIFO_LEN * 4) ?
>> + (EXYNOS_TRNG_FIFO_LEN * 4) : max;
>
> max is always > 32. This condition is not required.
No, it is not. http://elixir.free-electrons.com/linux/latest/source/drivers/char/hw_random/core.c#L67
--
Łukasz Stelmach
Samsung R&D Institute Poland
Samsung Electronics
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 472 bytes --]
^ permalink raw reply
* Re: [PATCH 2/2] pinctrl: sunxi: Disable strict mode for H5 driver
From: Maxime Ripard @ 2017-11-27 8:22 UTC (permalink / raw)
To: Andre Przywara
Cc: Chen-Yu Tsai, Linus Walleij, Rob Herring, Chris Obbard,
Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20171125120200.23294-3-andre.przywara-5wv7dgnIgG8@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 687 bytes --]
On Sat, Nov 25, 2017 at 12:02:00PM +0000, Andre Przywara wrote:
> All of the H5 boards in the kernel reference the MMC0 CD pin twice in
> their DT, so strict mode will make the MMC driver fail to load.
> To keep existing DTs working, disable strict mode in the H5 driver.
>
> Signed-off-by: Andre Przywara <andre.przywara-5wv7dgnIgG8@public.gmane.org>
> Reported-by: Chris Obbard <obbardc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Acked-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Sorry for missing that one...
Thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH 1/2] arm64: dts: allwinner: H5: remove redundant MMC0 card detect pin
From: Maxime Ripard @ 2017-11-27 8:23 UTC (permalink / raw)
To: Andre Przywara
Cc: Chen-Yu Tsai, Linus Walleij, Rob Herring, Chris Obbard,
Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <20171125120200.23294-2-andre.przywara-5wv7dgnIgG8@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 784 bytes --]
On Sat, Nov 25, 2017 at 12:01:59PM +0000, Andre Przywara wrote:
> PF6 is mostly used as the CD pin for the microSD slot on H5 based
> boards. So far we were referencing this pin twice: once using the
> mmc0_cd_pin phandle, and then again directly as a GPIO via the pinctrl
> phandle.
> This will cause problems if the pinctrl driver enables strict mode, as
> the second request will fail now, leading to a driver init failure.
> Remove the redundant pin reference via the mmc0_cd_pin phandle.
>
> Signed-off-by: Andre Przywara <andre.przywara-5wv7dgnIgG8@public.gmane.org>
> Reported-by: Chris Obbard <obbardc-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Applied for 4.16, thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* Re: [RFC 2/2] drivers: dma-mapping: parse per device reserved mem at probe time
From: Marek Szyprowski @ 2017-11-27 8:31 UTC (permalink / raw)
To: Peng Fan, hch-jcswGhMUV9g, robin.murphy-5wv7dgnIgG8,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
frowand.list-Re5JQEeQqe8AvxtiuMwx3w
Cc: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
van.freenix-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <20171126131346.12532-2-peng.fan-3arQi8VN3Tc@public.gmane.org>
Hi
On 2017-11-26 14:13, Peng Fan wrote:
> Invoke of_reserved_mem_device_init at dma_configure, then
> there is no need to call of_reserved_mem_device_init in device
> specific probe function.
>
> Signed-off-by: Peng Fan <peng.fan-3arQi8VN3Tc@public.gmane.org>
This has been already tried long time ago, without success:
http://patches.linaro.org/patch/33558/
> ---
> drivers/base/dma-mapping.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
> index e584eddef0a7..55dca06a7b55 100644
> --- a/drivers/base/dma-mapping.c
> +++ b/drivers/base/dma-mapping.c
> @@ -12,6 +12,7 @@
> #include <linux/export.h>
> #include <linux/gfp.h>
> #include <linux/of_device.h>
> +#include <linux/of_reserved_mem.h>
> #include <linux/slab.h>
> #include <linux/vmalloc.h>
>
> @@ -351,7 +352,9 @@ int dma_configure(struct device *dev)
> }
>
> if (dma_dev->of_node) {
> - ret = of_dma_configure(dev, dma_dev->of_node);
> + ret = of_reserved_mem_device_init(dev);
> + if (ret)
> + ret = of_dma_configure(dev, dma_dev->of_node);
> } else if (has_acpi_companion(dma_dev)) {
> attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode));
> if (attr != DEV_DMA_NOT_SUPPORTED)
> @@ -367,5 +370,6 @@ int dma_configure(struct device *dev)
> void dma_deconfigure(struct device *dev)
> {
> of_dma_deconfigure(dev);
> + of_reserved_mem_device_release(dev);
> acpi_dma_deconfigure(dev);
> }
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
--
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: [RFC PATCH 1/3] dt-bindings: pinctrl: sunxi: document new generic binding
From: Maxime Ripard @ 2017-11-27 8:34 UTC (permalink / raw)
To: Andre Przywara
Cc: Thierry Reding, Linus Walleij, Chen-Yu Tsai,
linux-gpio-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Mark Rutland,
devicetree-u79uwXL29TY76Z2rM5mHXA, Linux ARM, Arnd Bergmann,
Icenowy Zheng,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
In-Reply-To: <0c8051e6-5d8c-32d6-97e4-11c2283da5b4-5wv7dgnIgG8@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 2737 bytes --]
On Fri, Nov 24, 2017 at 05:19:24PM +0000, Andre Przywara wrote:
> > This is not the same as saying we need to be able to fully validate all
> > aspects of device tree. We can't, because some information simply does
> > not exist outside of DT. However, I think it's a big mistake to trust a
> > user to fully know about all intricacies of a pinmux and not make any
> > mistake when writing the device tree.
>
> When does a *user* write a device tree? What would a clueless Joe
> Average expect from doing so? The device tree is written by either the
> board/SoC vendor or by some kernel developers. It is not meant to be
> changed by the user, apart from carefully crafted overlays, maybe. You
> can have the same control by just changing the kernel (binary patching
> the image file or re-compiling with
> writel(MATCHES, base_addr + SET_FIRE)).
I guess the expectation should be that it's a Joe Average user in the
Allwinner case at least. It's far from the exception that someone that
never got any kernel (or electronics) experience before jumps in,
creates a DT for the shiny new board they just received and then
submits it.
I guess it's more the case in the Allwinner case than for any other
SoCs I've worked on at least, probably because of its widespread use
in the low-end consumer market and their reputation amongst hackers,
but still, this is basically our default.
> > What if one of the settings causes the board to go up in flames?
>
> Then you better not play with it. But I don't think this is a valid
> argument, really. What if gravity reverses tomorrow?
> Are there any known issues with writing mux values to pinctrl registers?
> I don't think the consequences would be different from putting low or
> high to a GPIO, which you can do already from userland.
I guess the difference would be that's it's active in your example,
while the pinmux will be set even if a user doesn't do anything. And I
can testify that you can very well permanently fry a board passively
using pinctrl :)
> > And let's face it: the really difficult part of adding pinmux support is
> > to write the driver (or subsystem if you don't have one yet). Adding the
> > data is really the easy part.
>
> I know, I did this before. But currently you have to write both the DT
> part *and* the kernel table. And check patch 3/3, that's what the table
> gets reduced to. So you avoid writing 601 lines, instead add 23 lines to
> the DT.
And I'll just add here that if the data size is of concern, as it can
be in a bootloader, you can very well have partial tables. There's
plenty of devices that will be of no use in a bootloader.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* Re: [RFC 2/2] drivers: dma-mapping: parse per device reserved mem at probe time
From: Peng Fan @ 2017-11-27 8:37 UTC (permalink / raw)
To: Marek Szyprowski
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Peng Fan,
frowand.list-Re5JQEeQqe8AvxtiuMwx3w,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, hch-jcswGhMUV9g
In-Reply-To: <875c3a8c-a857-823e-0243-487d1dd9bee7-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Hi Marek,
On Mon, Nov 27, 2017 at 09:31:00AM +0100, Marek Szyprowski wrote:
>Hi
>
>On 2017-11-26 14:13, Peng Fan wrote:
>> Invoke of_reserved_mem_device_init at dma_configure, then
>> there is no need to call of_reserved_mem_device_init in device
>> specific probe function.
>>
>> Signed-off-by: Peng Fan <peng.fan-3arQi8VN3Tc@public.gmane.org>
>
>This has been already tried long time ago, without success:
>http://patches.linaro.org/patch/33558/
Thanks for the info. I should first search mail list before
sending out patches.
Thanks,
Peng.
>
>> ---
>> drivers/base/dma-mapping.c | 6 +++++-
>> 1 file changed, 5 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
>> index e584eddef0a7..55dca06a7b55 100644
>> --- a/drivers/base/dma-mapping.c
>> +++ b/drivers/base/dma-mapping.c
>> @@ -12,6 +12,7 @@
>> #include <linux/export.h>
>> #include <linux/gfp.h>
>> #include <linux/of_device.h>
>> +#include <linux/of_reserved_mem.h>
>> #include <linux/slab.h>
>> #include <linux/vmalloc.h>
>> @@ -351,7 +352,9 @@ int dma_configure(struct device *dev)
>> }
>> if (dma_dev->of_node) {
>> - ret = of_dma_configure(dev, dma_dev->of_node);
>> + ret = of_reserved_mem_device_init(dev);
>> + if (ret)
>> + ret = of_dma_configure(dev, dma_dev->of_node);
>> } else if (has_acpi_companion(dma_dev)) {
>> attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode));
>> if (attr != DEV_DMA_NOT_SUPPORTED)
>> @@ -367,5 +370,6 @@ int dma_configure(struct device *dev)
>> void dma_deconfigure(struct device *dev)
>> {
>> of_dma_deconfigure(dev);
>> + of_reserved_mem_device_release(dev);
>> acpi_dma_deconfigure(dev);
>> }
>
>Best regards
>--
>Marek Szyprowski, PhD
>Samsung R&D Institute Poland
>
--
^ permalink raw reply
* Re: [RFC 2/2] drivers: dma-mapping: parse per device reserved mem at probe time
From: Marek Szyprowski @ 2017-11-27 8:44 UTC (permalink / raw)
To: Peng Fan
Cc: Peng Fan, hch-jcswGhMUV9g, robin.murphy-5wv7dgnIgG8,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
frowand.list-Re5JQEeQqe8AvxtiuMwx3w,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20171127083713.clh6oz5sgere4usq-MVApIMqXe9XjwJyOrGAgIJjmvxFtTJ+o0e7PPNI6Mm0@public.gmane.org>
Hi Peng,
On 2017-11-27 09:37, Peng Fan wrote:
> Hi Marek,
>
> On Mon, Nov 27, 2017 at 09:31:00AM +0100, Marek Szyprowski wrote:
>> Hi
>>
>> On 2017-11-26 14:13, Peng Fan wrote:
>>> Invoke of_reserved_mem_device_init at dma_configure, then
>>> there is no need to call of_reserved_mem_device_init in device
>>> specific probe function.
>>>
>>> Signed-off-by: Peng Fan <peng.fan-3arQi8VN3Tc@public.gmane.org>
>> This has been already tried long time ago, without success:
>> http://patches.linaro.org/patch/33558/
> Thanks for the info. I should first search mail list before
> sending out patches.
It doesn't mean that I'm against such idea. I just pointed that I've
already tried. That time, however there was no dma_configure() function
yet, which seems to be better place for of_rmem_device_init().
I would however always call of_dma_configure(), even when reserved mem
node is there. IIRC on ARM64 that function configures dma_ops, without
which no dma is possible at all.
>
> Thanks,
> Peng.
>
>>> ---
>>> drivers/base/dma-mapping.c | 6 +++++-
>>> 1 file changed, 5 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
>>> index e584eddef0a7..55dca06a7b55 100644
>>> --- a/drivers/base/dma-mapping.c
>>> +++ b/drivers/base/dma-mapping.c
>>> @@ -12,6 +12,7 @@
>>> #include <linux/export.h>
>>> #include <linux/gfp.h>
>>> #include <linux/of_device.h>
>>> +#include <linux/of_reserved_mem.h>
>>> #include <linux/slab.h>
>>> #include <linux/vmalloc.h>
>>> @@ -351,7 +352,9 @@ int dma_configure(struct device *dev)
>>> }
>>> if (dma_dev->of_node) {
>>> - ret = of_dma_configure(dev, dma_dev->of_node);
>>> + ret = of_reserved_mem_device_init(dev);
>>> + if (ret)
>>> + ret = of_dma_configure(dev, dma_dev->of_node);
>>> } else if (has_acpi_companion(dma_dev)) {
>>> attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode));
>>> if (attr != DEV_DMA_NOT_SUPPORTED)
>>> @@ -367,5 +370,6 @@ int dma_configure(struct device *dev)
>>> void dma_deconfigure(struct device *dev)
>>> {
>>> of_dma_deconfigure(dev);
>>> + of_reserved_mem_device_release(dev);
>>> acpi_dma_deconfigure(dev);
>>> }
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
--
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: [RFC 2/2] drivers: dma-mapping: parse per device reserved mem at probe time
From: Peng Fan @ 2017-11-27 9:04 UTC (permalink / raw)
To: Marek Szyprowski
Cc: Peng Fan, hch-jcswGhMUV9g, robin.murphy-5wv7dgnIgG8,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
frowand.list-Re5JQEeQqe8AvxtiuMwx3w,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <e44416ee-0f33-e310-d881-aaa3edfdf69e-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Hi Marek,
On Mon, Nov 27, 2017 at 09:44:20AM +0100, Marek Szyprowski wrote:
>Hi Peng,
>
>On 2017-11-27 09:37, Peng Fan wrote:
>> Hi Marek,
>>
>> On Mon, Nov 27, 2017 at 09:31:00AM +0100, Marek Szyprowski wrote:
>> > Hi
>> >
>> > On 2017-11-26 14:13, Peng Fan wrote:
>> > > Invoke of_reserved_mem_device_init at dma_configure, then
>> > > there is no need to call of_reserved_mem_device_init in device
>> > > specific probe function.
>> > >
>> > > Signed-off-by: Peng Fan <peng.fan-3arQi8VN3Tc@public.gmane.org>
>> > This has been already tried long time ago, without success:
>> > http://patches.linaro.org/patch/33558/
>> Thanks for the info. I should first search mail list before
>> sending out patches.
>
>It doesn't mean that I'm against such idea. I just pointed that I've
>already tried. That time, however there was no dma_configure() function
>yet, which seems to be better place for of_rmem_device_init().
>
>I would however always call of_dma_configure(), even when reserved mem
>node is there. IIRC on ARM64 that function configures dma_ops, without
>which no dma is possible at all.
So, you prefer this?
if (dma_dev->of_node) {
+ of_reserved_mem_device_init(dev);
ret = of_dma_configure(dev, dma_dev->of_node);
However in of_reserved_mem_device, there is also an call to
of_dma_configure.
"
/* ensure that dma_ops is set for virtual devices
* using reserved memory
*/
ret = of_dma_configure(dev, np);
"
If always call of_dma_configure, of_dma_configure maybe called twice.
I just checked more. of_reserved_mem_device_init only handle the first
memory-region. To nodes which have multiple memory-region, seems 2nd and etc
could not be handled, such as drivers/media/platform/s5p-mfc/s5p_mfc.c.
Thanks,
Peng.
>
>>
>> Thanks,
>> Peng.
>>
>> > > ---
>> > > drivers/base/dma-mapping.c | 6 +++++-
>> > > 1 file changed, 5 insertions(+), 1 deletion(-)
>> > >
>> > > diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
>> > > index e584eddef0a7..55dca06a7b55 100644
>> > > --- a/drivers/base/dma-mapping.c
>> > > +++ b/drivers/base/dma-mapping.c
>> > > @@ -12,6 +12,7 @@
>> > > #include <linux/export.h>
>> > > #include <linux/gfp.h>
>> > > #include <linux/of_device.h>
>> > > +#include <linux/of_reserved_mem.h>
>> > > #include <linux/slab.h>
>> > > #include <linux/vmalloc.h>
>> > > @@ -351,7 +352,9 @@ int dma_configure(struct device *dev)
>> > > }
>> > > if (dma_dev->of_node) {
>> > > - ret = of_dma_configure(dev, dma_dev->of_node);
>> > > + ret = of_reserved_mem_device_init(dev);
>> > > + if (ret)
>> > > + ret = of_dma_configure(dev, dma_dev->of_node);
>> > > } else if (has_acpi_companion(dma_dev)) {
>> > > attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode));
>> > > if (attr != DEV_DMA_NOT_SUPPORTED)
>> > > @@ -367,5 +370,6 @@ int dma_configure(struct device *dev)
>> > > void dma_deconfigure(struct device *dev)
>> > > {
>> > > of_dma_deconfigure(dev);
>> > > + of_reserved_mem_device_release(dev);
>> > > acpi_dma_deconfigure(dev);
>> > > }
>
>Best regards
>--
>Marek Szyprowski, PhD
>Samsung R&D Institute Poland
>
--
--
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 0/2] add clk controller driver for Meson-AXG SoC
From: Yixun Lan @ 2017-11-27 9:48 UTC (permalink / raw)
To: Neil Armstrong, Jerome Brunet, Kevin Hilman
Cc: Rob Herring, Mark Rutland, Michael Turquette, Stephen Boyd,
Carlo Caione, Yixun Lan, Qiufang Dai,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Add driver for the clk controller which found in Meson AXG SoC
Note, we deliberately create a seperate source file for the Meson AXG
series, instead of sharing code with previous GXBB/GXL - the file axg.c
It would help us maintaining the code more easily.
Changes since v1 [1]:
- rework register definion, use '(offset << 2)' to better match
the description from data sheet
- drop "#include dt-bindings/clock/gxbb-aoclkc.h" from dts
- rebase code to v4.15-rc1
[1]
http://lists.infradead.org/pipermail/linux-amlogic/2017-November/005239.html
http://lists.infradead.org/pipermail/linux-amlogic/2017-November/005240.html
http://lists.infradead.org/pipermail/linux-amlogic/2017-November/005241.html
Qiufang Dai (2):
clk: meson-axg: add clock controller drivers
arm64: dts: meson-axg: add clock DT info for Meson AXG SoC
arch/arm64/Kconfig.platforms | 1 +
arch/arm64/boot/dts/amlogic/meson-axg.dtsi | 15 +
drivers/clk/meson/Kconfig | 8 +
drivers/clk/meson/Makefile | 1 +
drivers/clk/meson/axg.c | 948 +++++++++++++++++++++++++++++
drivers/clk/meson/axg.h | 126 ++++
include/dt-bindings/clock/axg-clkc.h | 72 +++
7 files changed, 1171 insertions(+)
create mode 100644 drivers/clk/meson/axg.c
create mode 100644 drivers/clk/meson/axg.h
create mode 100644 include/dt-bindings/clock/axg-clkc.h
--
2.15.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 1/2] clk: meson-axg: add clock controller drivers
From: Yixun Lan @ 2017-11-27 9:48 UTC (permalink / raw)
To: Neil Armstrong, Jerome Brunet, Kevin Hilman
Cc: Rob Herring, Mark Rutland, Michael Turquette, Stephen Boyd,
Carlo Caione, Yixun Lan, Qiufang Dai, linux-amlogic, devicetree,
linux-clk, linux-arm-kernel, linux-kernel
In-Reply-To: <20171127094844.16742-1-yixun.lan@amlogic.com>
From: Qiufang Dai <qiufang.dai@amlogic.com>
Add clock controller drivers for Amlogic Meson-AXG SoC.
Signed-off-by: Qiufang Dai <qiufang.dai@amlogic.com>
Signed-off-by: Yixun Lan <yixun.lan@amlogic.com>
---
arch/arm64/Kconfig.platforms | 1 +
drivers/clk/meson/Kconfig | 8 +
drivers/clk/meson/Makefile | 1 +
drivers/clk/meson/axg.c | 948 +++++++++++++++++++++++++++++++++++
drivers/clk/meson/axg.h | 126 +++++
include/dt-bindings/clock/axg-clkc.h | 72 +++
6 files changed, 1156 insertions(+)
create mode 100644 drivers/clk/meson/axg.c
create mode 100644 drivers/clk/meson/axg.h
create mode 100644 include/dt-bindings/clock/axg-clkc.h
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 2401373565ff..fbedbd8f619a 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -105,6 +105,7 @@ config ARCH_MESON
select PINCTRL_MESON
select COMMON_CLK_AMLOGIC
select COMMON_CLK_GXBB
+ select COMMON_CLK_AXG
select MESON_IRQ_GPIO
help
This enables support for the Amlogic S905 SoCs.
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index d2d0174a6eca..7694302c70a4 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -19,3 +19,11 @@ config COMMON_CLK_GXBB
help
Support for the clock controller on AmLogic S905 devices, aka gxbb.
Say Y if you want peripherals and CPU frequency scaling to work.
+
+config COMMON_CLK_AXG
+ bool
+ depends on COMMON_CLK_AMLOGIC
+ select RESET_CONTROLLER
+ help
+ Support for the clock controller on AmLogic A113D devices, aka axg.
+ Say Y if you want peripherals and CPU frequency scaling to work.
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index b139d41b25da..3c03ce583798 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-regmap.o gxbb-aoclk-32k.o
+obj-$(CONFIG_COMMON_CLK_AXG) += axg.o
diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
new file mode 100644
index 000000000000..51c5b4062715
--- /dev/null
+++ b/drivers/clk/meson/axg.c
@@ -0,0 +1,948 @@
+/*
+ * AmLogic Meson-AXG Clock Controller Driver
+ *
+ * Copyright (c) 2016 Baylibre SAS.
+ * Author: Michael Turquette <mturquette@baylibre.com>
+ *
+ * Copyright (c) 2017 Amlogic, inc.
+ * Author: Qiufang Dai <qiufang.dai@amlogic.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+
+#include "clkc.h"
+#include "axg.h"
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static const struct pll_rate_table sys_pll_rate_table[] = {
+ PLL_RATE(24000000, 56, 1, 2),
+ PLL_RATE(48000000, 64, 1, 2),
+ PLL_RATE(72000000, 72, 1, 2),
+ PLL_RATE(96000000, 64, 1, 2),
+ PLL_RATE(120000000, 80, 1, 2),
+ PLL_RATE(144000000, 96, 1, 2),
+ PLL_RATE(168000000, 56, 1, 1),
+ PLL_RATE(192000000, 64, 1, 1),
+ PLL_RATE(216000000, 72, 1, 1),
+ PLL_RATE(240000000, 80, 1, 1),
+ PLL_RATE(264000000, 88, 1, 1),
+ PLL_RATE(288000000, 96, 1, 1),
+ PLL_RATE(312000000, 52, 1, 2),
+ PLL_RATE(336000000, 56, 1, 2),
+ PLL_RATE(360000000, 60, 1, 2),
+ PLL_RATE(384000000, 64, 1, 2),
+ PLL_RATE(408000000, 68, 1, 2),
+ PLL_RATE(432000000, 72, 1, 2),
+ PLL_RATE(456000000, 76, 1, 2),
+ PLL_RATE(480000000, 80, 1, 2),
+ PLL_RATE(504000000, 84, 1, 2),
+ PLL_RATE(528000000, 88, 1, 2),
+ PLL_RATE(552000000, 92, 1, 2),
+ PLL_RATE(576000000, 96, 1, 2),
+ PLL_RATE(600000000, 50, 1, 1),
+ PLL_RATE(624000000, 52, 1, 1),
+ PLL_RATE(648000000, 54, 1, 1),
+ PLL_RATE(672000000, 56, 1, 1),
+ PLL_RATE(696000000, 58, 1, 1),
+ PLL_RATE(720000000, 60, 1, 1),
+ PLL_RATE(744000000, 62, 1, 1),
+ PLL_RATE(768000000, 64, 1, 1),
+ PLL_RATE(792000000, 66, 1, 1),
+ PLL_RATE(816000000, 68, 1, 1),
+ PLL_RATE(840000000, 70, 1, 1),
+ PLL_RATE(864000000, 72, 1, 1),
+ PLL_RATE(888000000, 74, 1, 1),
+ PLL_RATE(912000000, 76, 1, 1),
+ PLL_RATE(936000000, 78, 1, 1),
+ PLL_RATE(960000000, 80, 1, 1),
+ PLL_RATE(984000000, 82, 1, 1),
+ PLL_RATE(1008000000, 84, 1, 1),
+ PLL_RATE(1032000000, 86, 1, 1),
+ PLL_RATE(1056000000, 88, 1, 1),
+ PLL_RATE(1080000000, 90, 1, 1),
+ PLL_RATE(1104000000, 92, 1, 1),
+ PLL_RATE(1128000000, 94, 1, 1),
+ PLL_RATE(1152000000, 96, 1, 1),
+ PLL_RATE(1176000000, 98, 1, 1),
+ PLL_RATE(1200000000, 50, 1, 0),
+ PLL_RATE(1224000000, 51, 1, 0),
+ PLL_RATE(1248000000, 52, 1, 0),
+ PLL_RATE(1272000000, 53, 1, 0),
+ PLL_RATE(1296000000, 54, 1, 0),
+ PLL_RATE(1320000000, 55, 1, 0),
+ PLL_RATE(1344000000, 56, 1, 0),
+ PLL_RATE(1368000000, 57, 1, 0),
+ PLL_RATE(1392000000, 58, 1, 0),
+ PLL_RATE(1416000000, 59, 1, 0),
+ PLL_RATE(1440000000, 60, 1, 0),
+ PLL_RATE(1464000000, 61, 1, 0),
+ PLL_RATE(1488000000, 62, 1, 0),
+ PLL_RATE(1512000000, 63, 1, 0),
+ PLL_RATE(1536000000, 64, 1, 0),
+ PLL_RATE(1560000000, 65, 1, 0),
+ PLL_RATE(1584000000, 66, 1, 0),
+ PLL_RATE(1608000000, 67, 1, 0),
+ PLL_RATE(1632000000, 68, 1, 0),
+ PLL_RATE(1656000000, 68, 1, 0),
+ PLL_RATE(1680000000, 68, 1, 0),
+ PLL_RATE(1704000000, 68, 1, 0),
+ PLL_RATE(1728000000, 69, 1, 0),
+ PLL_RATE(1752000000, 69, 1, 0),
+ PLL_RATE(1776000000, 69, 1, 0),
+ PLL_RATE(1800000000, 69, 1, 0),
+ PLL_RATE(1824000000, 70, 1, 0),
+ PLL_RATE(1848000000, 70, 1, 0),
+ PLL_RATE(1872000000, 70, 1, 0),
+ PLL_RATE(1896000000, 70, 1, 0),
+ PLL_RATE(1920000000, 71, 1, 0),
+ PLL_RATE(1944000000, 71, 1, 0),
+ PLL_RATE(1968000000, 71, 1, 0),
+ PLL_RATE(1992000000, 71, 1, 0),
+ PLL_RATE(2016000000, 72, 1, 0),
+ PLL_RATE(2040000000, 72, 1, 0),
+ PLL_RATE(2064000000, 72, 1, 0),
+ PLL_RATE(2088000000, 72, 1, 0),
+ PLL_RATE(2112000000, 73, 1, 0),
+ { /* sentinel */ },
+};
+
+static struct meson_clk_pll axg_fixed_pll = {
+ .m = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ },
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "fixed_pll",
+ .ops = &meson_clk_pll_ro_ops,
+ .parent_names = (const char *[]){ "xtal" },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct meson_clk_pll axg_sys_pll = {
+ .m = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_SYS_PLL_CNTL,
+ .shift = 10,
+ .width = 2,
+ },
+ .rate_table = sys_pll_rate_table,
+ .rate_count = ARRAY_SIZE(sys_pll_rate_table),
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "sys_pll",
+ .ops = &meson_clk_pll_ro_ops,
+ .parent_names = (const char *[]){ "xtal" },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
+ PLL_RATE(240000000, 40, 1, 2),
+ PLL_RATE(246000000, 41, 1, 2),
+ PLL_RATE(252000000, 42, 1, 2),
+ PLL_RATE(258000000, 43, 1, 2),
+ PLL_RATE(264000000, 44, 1, 2),
+ PLL_RATE(270000000, 45, 1, 2),
+ PLL_RATE(276000000, 46, 1, 2),
+ PLL_RATE(282000000, 47, 1, 2),
+ PLL_RATE(288000000, 48, 1, 2),
+ PLL_RATE(294000000, 49, 1, 2),
+ PLL_RATE(300000000, 50, 1, 2),
+ PLL_RATE(306000000, 51, 1, 2),
+ PLL_RATE(312000000, 52, 1, 2),
+ PLL_RATE(318000000, 53, 1, 2),
+ PLL_RATE(324000000, 54, 1, 2),
+ PLL_RATE(330000000, 55, 1, 2),
+ PLL_RATE(336000000, 56, 1, 2),
+ PLL_RATE(342000000, 57, 1, 2),
+ PLL_RATE(348000000, 58, 1, 2),
+ PLL_RATE(354000000, 59, 1, 2),
+ PLL_RATE(360000000, 60, 1, 2),
+ PLL_RATE(366000000, 61, 1, 2),
+ PLL_RATE(372000000, 62, 1, 2),
+ PLL_RATE(378000000, 63, 1, 2),
+ PLL_RATE(384000000, 64, 1, 2),
+ PLL_RATE(390000000, 65, 1, 3),
+ PLL_RATE(396000000, 66, 1, 3),
+ PLL_RATE(402000000, 67, 1, 3),
+ PLL_RATE(408000000, 68, 1, 3),
+ PLL_RATE(480000000, 40, 1, 1),
+ PLL_RATE(492000000, 41, 1, 1),
+ PLL_RATE(504000000, 42, 1, 1),
+ PLL_RATE(516000000, 43, 1, 1),
+ PLL_RATE(528000000, 44, 1, 1),
+ PLL_RATE(540000000, 45, 1, 1),
+ PLL_RATE(552000000, 46, 1, 1),
+ PLL_RATE(564000000, 47, 1, 1),
+ PLL_RATE(576000000, 48, 1, 1),
+ PLL_RATE(588000000, 49, 1, 1),
+ PLL_RATE(600000000, 50, 1, 1),
+ PLL_RATE(612000000, 51, 1, 1),
+ PLL_RATE(624000000, 52, 1, 1),
+ PLL_RATE(636000000, 53, 1, 1),
+ PLL_RATE(648000000, 54, 1, 1),
+ PLL_RATE(660000000, 55, 1, 1),
+ PLL_RATE(672000000, 56, 1, 1),
+ PLL_RATE(684000000, 57, 1, 1),
+ PLL_RATE(696000000, 58, 1, 1),
+ PLL_RATE(708000000, 59, 1, 1),
+ PLL_RATE(720000000, 60, 1, 1),
+ PLL_RATE(732000000, 61, 1, 1),
+ PLL_RATE(744000000, 62, 1, 1),
+ PLL_RATE(756000000, 63, 1, 1),
+ PLL_RATE(768000000, 64, 1, 1),
+ PLL_RATE(780000000, 65, 1, 1),
+ PLL_RATE(792000000, 66, 1, 1),
+ PLL_RATE(804000000, 67, 1, 1),
+ PLL_RATE(816000000, 68, 1, 1),
+ PLL_RATE(960000000, 40, 1, 0),
+ PLL_RATE(984000000, 41, 1, 0),
+ PLL_RATE(1008000000, 42, 1, 0),
+ PLL_RATE(1032000000, 43, 1, 0),
+ PLL_RATE(1056000000, 44, 1, 0),
+ PLL_RATE(1080000000, 45, 1, 0),
+ PLL_RATE(1104000000, 46, 1, 0),
+ PLL_RATE(1128000000, 47, 1, 0),
+ PLL_RATE(1152000000, 48, 1, 0),
+ PLL_RATE(1176000000, 49, 1, 0),
+ PLL_RATE(1200000000, 50, 1, 0),
+ PLL_RATE(1224000000, 51, 1, 0),
+ PLL_RATE(1248000000, 52, 1, 0),
+ PLL_RATE(1272000000, 53, 1, 0),
+ PLL_RATE(1296000000, 54, 1, 0),
+ PLL_RATE(1320000000, 55, 1, 0),
+ PLL_RATE(1344000000, 56, 1, 0),
+ PLL_RATE(1368000000, 57, 1, 0),
+ PLL_RATE(1392000000, 58, 1, 0),
+ PLL_RATE(1416000000, 59, 1, 0),
+ PLL_RATE(1440000000, 60, 1, 0),
+ PLL_RATE(1464000000, 61, 1, 0),
+ PLL_RATE(1488000000, 62, 1, 0),
+ PLL_RATE(1512000000, 63, 1, 0),
+ PLL_RATE(1536000000, 64, 1, 0),
+ PLL_RATE(1560000000, 65, 1, 0),
+ PLL_RATE(1584000000, 66, 1, 0),
+ PLL_RATE(1608000000, 67, 1, 0),
+ PLL_RATE(1632000000, 68, 1, 0),
+ { /* sentinel */ },
+};
+
+struct pll_params_table axg_gp0_params_table[] = {
+ PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250),
+ PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000),
+ PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be),
+ PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288),
+ PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d),
+ PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000),
+};
+
+static struct meson_clk_pll axg_gp0_pll = {
+ .m = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .od = {
+ .reg_off = HHI_GP0_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ },
+ .params = {
+ .params_table = axg_gp0_params_table,
+ .params_count = ARRAY_SIZE(axg_gp0_params_table),
+ .no_init_reset = true,
+ .reset_lock_loop = true,
+ },
+ .rate_table = axg_gp0_pll_rate_table,
+ .rate_count = ARRAY_SIZE(axg_gp0_pll_rate_table),
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "gp0_pll",
+ .ops = &meson_clk_pll_ops,
+ .parent_names = (const char *[]){ "xtal" },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+
+static struct clk_fixed_factor axg_fclk_div2 = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div2",
+ .ops = &clk_fixed_factor_ops,
+ .parent_names = (const char *[]){ "fixed_pll" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor axg_fclk_div3 = {
+ .mult = 1,
+ .div = 3,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div3",
+ .ops = &clk_fixed_factor_ops,
+ .parent_names = (const char *[]){ "fixed_pll" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor axg_fclk_div4 = {
+ .mult = 1,
+ .div = 4,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div4",
+ .ops = &clk_fixed_factor_ops,
+ .parent_names = (const char *[]){ "fixed_pll" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor axg_fclk_div5 = {
+ .mult = 1,
+ .div = 5,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div5",
+ .ops = &clk_fixed_factor_ops,
+ .parent_names = (const char *[]){ "fixed_pll" },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor axg_fclk_div7 = {
+ .mult = 1,
+ .div = 7,
+ .hw.init = &(struct clk_init_data){
+ .name = "fclk_div7",
+ .ops = &clk_fixed_factor_ops,
+ .parent_names = (const char *[]){ "fixed_pll" },
+ .num_parents = 1,
+ },
+};
+
+static struct meson_clk_mpll axg_mpll0 = {
+ .sdm = {
+ .reg_off = HHI_MPLL_CNTL7,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL_CNTL7,
+ .shift = 15,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL_CNTL7,
+ .shift = 16,
+ .width = 9,
+ },
+ .en = {
+ .reg_off = HHI_MPLL_CNTL7,
+ .shift = 14,
+ .width = 1,
+ },
+ .ssen = {
+ .reg_off = HHI_MPLL_CNTL,
+ .shift = 25,
+ .width = 1,
+ },
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll0",
+ .ops = &meson_clk_mpll_ops,
+ .parent_names = (const char *[]){ "fixed_pll" },
+ .num_parents = 1,
+ },
+};
+
+static struct meson_clk_mpll axg_mpll1 = {
+ .sdm = {
+ .reg_off = HHI_MPLL_CNTL8,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL_CNTL8,
+ .shift = 15,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL_CNTL8,
+ .shift = 16,
+ .width = 9,
+ },
+ .en = {
+ .reg_off = HHI_MPLL_CNTL8,
+ .shift = 14,
+ .width = 1,
+ },
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll1",
+ .ops = &meson_clk_mpll_ops,
+ .parent_names = (const char *[]){ "fixed_pll" },
+ .num_parents = 1,
+ },
+};
+
+static struct meson_clk_mpll axg_mpll2 = {
+ .sdm = {
+ .reg_off = HHI_MPLL_CNTL9,
+ .shift = 0,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL_CNTL9,
+ .shift = 15,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL_CNTL9,
+ .shift = 16,
+ .width = 9,
+ },
+ .en = {
+ .reg_off = HHI_MPLL_CNTL9,
+ .shift = 14,
+ .width = 1,
+ },
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll2",
+ .ops = &meson_clk_mpll_ops,
+ .parent_names = (const char *[]){ "fixed_pll" },
+ .num_parents = 1,
+ },
+};
+
+static struct meson_clk_mpll axg_mpll3 = {
+ .sdm = {
+ .reg_off = HHI_MPLL3_CNTL0,
+ .shift = 12,
+ .width = 14,
+ },
+ .sdm_en = {
+ .reg_off = HHI_MPLL3_CNTL0,
+ .shift = 11,
+ .width = 1,
+ },
+ .n2 = {
+ .reg_off = HHI_MPLL3_CNTL0,
+ .shift = 2,
+ .width = 9,
+ },
+ .en = {
+ .reg_off = HHI_MPLL3_CNTL0,
+ .shift = 0,
+ .width = 1,
+ },
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpll3",
+ .ops = &meson_clk_mpll_ops,
+ .parent_names = (const char *[]){ "fixed_pll" },
+ .num_parents = 1,
+ },
+};
+
+/*
+ * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers
+ * and should be modeled with their respective PLLs via the forthcoming
+ * coordinated clock rates feature
+ */
+static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
+static const char * const clk81_parent_names[] = {
+ "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
+ "fclk_div3", "fclk_div5"
+};
+
+static struct clk_mux axg_mpeg_clk_sel = {
+ .reg = (void *)HHI_MPEG_CLK_CNTL,
+ .mask = 0x7,
+ .shift = 12,
+ .flags = CLK_MUX_READ_ONLY,
+ .table = mux_table_clk81,
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpeg_clk_sel",
+ .ops = &clk_mux_ro_ops,
+ /*
+ * bits 14:12 selects from 8 possible parents:
+ * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
+ * fclk_div4, fclk_div3, fclk_div5
+ */
+ .parent_names = clk81_parent_names,
+ .num_parents = ARRAY_SIZE(clk81_parent_names),
+ .flags = CLK_SET_RATE_NO_REPARENT,
+ },
+};
+
+static struct clk_divider axg_mpeg_clk_div = {
+ .reg = (void *)HHI_MPEG_CLK_CNTL,
+ .shift = 0,
+ .width = 7,
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "mpeg_clk_div",
+ .ops = &clk_divider_ops,
+ .parent_names = (const char *[]){ "mpeg_clk_sel" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_gate axg_clk81 = {
+ .reg = (void *)HHI_MPEG_CLK_CNTL,
+ .bit_idx = 7,
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "clk81",
+ .ops = &clk_gate_ops,
+ .parent_names = (const char *[]){ "mpeg_clk_div" },
+ .num_parents = 1,
+ .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
+ },
+};
+
+static const char * const axg_sd_emmc_clk0_parent_names[] = {
+ "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
+
+ /*
+ * Following these parent clocks, we should also have had mpll2, mpll3
+ * and gp0_pll but these clocks are too precious to be used here. All
+ * the necessary rates for MMC and NAND operation can be acheived using
+ * xtal or fclk_div clocks
+ */
+};
+
+/* SDcard clock */
+static struct clk_mux axg_sd_emmc_b_clk0_sel = {
+ .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
+ .mask = 0x7,
+ .shift = 25,
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_b_clk0_sel",
+ .ops = &clk_mux_ops,
+ .parent_names = axg_sd_emmc_clk0_parent_names,
+ .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_divider axg_sd_emmc_b_clk0_div = {
+ .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
+ .shift = 16,
+ .width = 7,
+ .lock = &clk_lock,
+ .flags = CLK_DIVIDER_ROUND_CLOSEST,
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_b_clk0_div",
+ .ops = &clk_divider_ops,
+ .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_gate axg_sd_emmc_b_clk0 = {
+ .reg = (void *)HHI_SD_EMMC_CLK_CNTL,
+ .bit_idx = 23,
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "sd_emmc_b_clk0",
+ .ops = &clk_gate_ops,
+ .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* EMMC/NAND clock */
+static struct clk_mux axg_sd_emmc_c_clk0_sel = {
+ .reg = (void *)HHI_NAND_CLK_CNTL,
+ .mask = 0x7,
+ .shift = 9,
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_c_clk0_sel",
+ .ops = &clk_mux_ops,
+ .parent_names = axg_sd_emmc_clk0_parent_names,
+ .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_divider axg_sd_emmc_c_clk0_div = {
+ .reg = (void *)HHI_NAND_CLK_CNTL,
+ .shift = 0,
+ .width = 7,
+ .lock = &clk_lock,
+ .flags = CLK_DIVIDER_ROUND_CLOSEST,
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_c_clk0_div",
+ .ops = &clk_divider_ops,
+ .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_gate axg_sd_emmc_c_clk0 = {
+ .reg = (void *)HHI_NAND_CLK_CNTL,
+ .bit_idx = 7,
+ .lock = &clk_lock,
+ .hw.init = &(struct clk_init_data){
+ .name = "sd_emmc_c_clk0",
+ .ops = &clk_gate_ops,
+ .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* Everything Else (EE) domain gates */
+static MESON_GATE(axg_ddr, HHI_GCLK_MPEG0, 0);
+static MESON_GATE(axg_audio_locker, HHI_GCLK_MPEG0, 2);
+static MESON_GATE(axg_mipi_dsi_host, HHI_GCLK_MPEG0, 3);
+static MESON_GATE(axg_isa, HHI_GCLK_MPEG0, 5);
+static MESON_GATE(axg_pl301, HHI_GCLK_MPEG0, 6);
+static MESON_GATE(axg_periphs, HHI_GCLK_MPEG0, 7);
+static MESON_GATE(axg_spicc_0, HHI_GCLK_MPEG0, 8);
+static MESON_GATE(axg_i2c, HHI_GCLK_MPEG0, 9);
+static MESON_GATE(axg_rng0, HHI_GCLK_MPEG0, 12);
+static MESON_GATE(axg_uart0, HHI_GCLK_MPEG0, 13);
+static MESON_GATE(axg_mipi_dsi_phy, HHI_GCLK_MPEG0, 14);
+static MESON_GATE(axg_spicc_1, HHI_GCLK_MPEG0, 15);
+static MESON_GATE(axg_pcie_a, HHI_GCLK_MPEG0, 16);
+static MESON_GATE(axg_pcie_b, HHI_GCLK_MPEG0, 17);
+static MESON_GATE(axg_hiu_reg, HHI_GCLK_MPEG0, 19);
+static MESON_GATE(axg_assist_misc, HHI_GCLK_MPEG0, 23);
+static MESON_GATE(axg_emmc_b, HHI_GCLK_MPEG0, 25);
+static MESON_GATE(axg_emmc_c, HHI_GCLK_MPEG0, 26);
+static MESON_GATE(axg_dma, HHI_GCLK_MPEG0, 27);
+static MESON_GATE(axg_spi, HHI_GCLK_MPEG0, 30);
+
+static MESON_GATE(axg_audio, HHI_GCLK_MPEG1, 0);
+static MESON_GATE(axg_eth_core, HHI_GCLK_MPEG1, 3);
+static MESON_GATE(axg_uart1, HHI_GCLK_MPEG1, 16);
+static MESON_GATE(axg_g2d, HHI_GCLK_MPEG1, 20);
+static MESON_GATE(axg_usb0, HHI_GCLK_MPEG1, 21);
+static MESON_GATE(axg_usb1, HHI_GCLK_MPEG1, 22);
+static MESON_GATE(axg_reset, HHI_GCLK_MPEG1, 23);
+static MESON_GATE(axg_usb_general, HHI_GCLK_MPEG1, 26);
+static MESON_GATE(axg_ahb_arb0, HHI_GCLK_MPEG1, 29);
+static MESON_GATE(axg_efuse, HHI_GCLK_MPEG1, 30);
+static MESON_GATE(axg_boot_rom, HHI_GCLK_MPEG1, 31);
+
+static MESON_GATE(axg_ahb_data_bus, HHI_GCLK_MPEG2, 1);
+static MESON_GATE(axg_ahb_ctrl_bus, HHI_GCLK_MPEG2, 2);
+static MESON_GATE(axg_usb1_to_ddr, HHI_GCLK_MPEG2, 8);
+static MESON_GATE(axg_usb0_to_ddr, HHI_GCLK_MPEG2, 9);
+static MESON_GATE(axg_mmc_pclk, HHI_GCLK_MPEG2, 11);
+static MESON_GATE(axg_vpu_intr, HHI_GCLK_MPEG2, 25);
+static MESON_GATE(axg_sec_ahb_ahb3_bridge, HHI_GCLK_MPEG2, 26);
+static MESON_GATE(axg_gic, HHI_GCLK_MPEG2, 30);
+
+/* Always On (AO) domain gates */
+
+static MESON_GATE(axg_ao_media_cpu, HHI_GCLK_AO, 0);
+static MESON_GATE(axg_ao_ahb_sram, HHI_GCLK_AO, 1);
+static MESON_GATE(axg_ao_ahb_bus, HHI_GCLK_AO, 2);
+static MESON_GATE(axg_ao_iface, HHI_GCLK_AO, 3);
+static MESON_GATE(axg_ao_i2c, HHI_GCLK_AO, 4);
+
+/* Array of all clocks provided by this provider */
+
+static struct clk_hw_onecell_data axg_hw_onecell_data = {
+ .hws = {
+ [CLKID_SYS_PLL] = &axg_sys_pll.hw,
+ [CLKID_FIXED_PLL] = &axg_fixed_pll.hw,
+ [CLKID_FCLK_DIV2] = &axg_fclk_div2.hw,
+ [CLKID_FCLK_DIV3] = &axg_fclk_div3.hw,
+ [CLKID_FCLK_DIV4] = &axg_fclk_div4.hw,
+ [CLKID_FCLK_DIV5] = &axg_fclk_div5.hw,
+ [CLKID_FCLK_DIV7] = &axg_fclk_div7.hw,
+ [CLKID_GP0_PLL] = &axg_gp0_pll.hw,
+ [CLKID_MPEG_SEL] = &axg_mpeg_clk_sel.hw,
+ [CLKID_MPEG_DIV] = &axg_mpeg_clk_div.hw,
+ [CLKID_CLK81] = &axg_clk81.hw,
+ [CLKID_MPLL0] = &axg_mpll0.hw,
+ [CLKID_MPLL1] = &axg_mpll1.hw,
+ [CLKID_MPLL2] = &axg_mpll2.hw,
+ [CLKID_MPLL3] = &axg_mpll3.hw,
+ [CLKID_DDR] = &axg_ddr.hw,
+ [CLKID_AUDIO_LOCKER] = &axg_audio_locker.hw,
+ [CLKID_MIPI_DSI_HOST] = &axg_mipi_dsi_host.hw,
+ [CLKID_ISA] = &axg_isa.hw,
+ [CLKID_PL301] = &axg_pl301.hw,
+ [CLKID_PERIPHS] = &axg_periphs.hw,
+ [CLKID_SPICC0] = &axg_spicc_0.hw,
+ [CLKID_I2C] = &axg_i2c.hw,
+ [CLKID_RNG0] = &axg_rng0.hw,
+ [CLKID_UART0] = &axg_uart0.hw,
+ [CLKID_MIPI_DSI_PHY] = &axg_mipi_dsi_phy.hw,
+ [CLKID_SPICC1] = &axg_spicc_1.hw,
+ [CLKID_PCIE_A] = &axg_pcie_a.hw,
+ [CLKID_PCIE_B] = &axg_pcie_b.hw,
+ [CLKID_HIU_IFACE] = &axg_hiu_reg.hw,
+ [CLKID_ASSIST_MISC] = &axg_assist_misc.hw,
+ [CLKID_SD_EMMC_B] = &axg_emmc_b.hw,
+ [CLKID_SD_EMMC_C] = &axg_emmc_c.hw,
+ [CLKID_DMA] = &axg_dma.hw,
+ [CLKID_SPI] = &axg_spi.hw,
+ [CLKID_AUDIO] = &axg_audio.hw,
+ [CLKID_ETH] = &axg_eth_core.hw,
+ [CLKID_UART1] = &axg_uart1.hw,
+ [CLKID_G2D] = &axg_g2d.hw,
+ [CLKID_USB0] = &axg_usb0.hw,
+ [CLKID_USB1] = &axg_usb1.hw,
+ [CLKID_RESET] = &axg_reset.hw,
+ [CLKID_USB] = &axg_usb_general.hw,
+ [CLKID_AHB_ARB0] = &axg_ahb_arb0.hw,
+ [CLKID_EFUSE] = &axg_efuse.hw,
+ [CLKID_BOOT_ROM] = &axg_boot_rom.hw,
+ [CLKID_AHB_DATA_BUS] = &axg_ahb_data_bus.hw,
+ [CLKID_AHB_CTRL_BUS] = &axg_ahb_ctrl_bus.hw,
+ [CLKID_USB1_DDR_BRIDGE] = &axg_usb1_to_ddr.hw,
+ [CLKID_USB0_DDR_BRIDGE] = &axg_usb0_to_ddr.hw,
+ [CLKID_MMC_PCLK] = &axg_mmc_pclk.hw,
+ [CLKID_VPU_INTR] = &axg_vpu_intr.hw,
+ [CLKID_SEC_AHB_AHB3_BRIDGE] = &axg_sec_ahb_ahb3_bridge.hw,
+ [CLKID_GIC] = &axg_gic.hw,
+ [CLKID_AO_MEDIA_CPU] = &axg_ao_media_cpu.hw,
+ [CLKID_AO_AHB_SRAM] = &axg_ao_ahb_sram.hw,
+ [CLKID_AO_AHB_BUS] = &axg_ao_ahb_bus.hw,
+ [CLKID_AO_IFACE] = &axg_ao_iface.hw,
+ [CLKID_AO_I2C] = &axg_ao_i2c.hw,
+ [CLKID_SD_EMMC_B_CLK0_SEL] = &axg_sd_emmc_b_clk0_sel.hw,
+ [CLKID_SD_EMMC_B_CLK0_DIV] = &axg_sd_emmc_b_clk0_div.hw,
+ [CLKID_SD_EMMC_B_CLK0] = &axg_sd_emmc_b_clk0.hw,
+ [CLKID_SD_EMMC_C_CLK0_SEL] = &axg_sd_emmc_c_clk0_sel.hw,
+ [CLKID_SD_EMMC_C_CLK0_DIV] = &axg_sd_emmc_c_clk0_div.hw,
+ [CLKID_SD_EMMC_C_CLK0] = &axg_sd_emmc_c_clk0.hw,
+ [NR_CLKS] = NULL,
+ },
+ .num = NR_CLKS,
+};
+
+/* Convenience tables to populate base addresses in .probe */
+
+static struct meson_clk_pll *const axg_clk_plls[] = {
+ &axg_fixed_pll,
+ &axg_sys_pll,
+ &axg_gp0_pll,
+};
+
+static struct meson_clk_mpll *const axg_clk_mplls[] = {
+ &axg_mpll0,
+ &axg_mpll1,
+ &axg_mpll2,
+ &axg_mpll3,
+};
+
+static struct clk_gate *const axg_clk_gates[] = {
+ &axg_clk81,
+ &axg_ddr,
+ &axg_audio_locker,
+ &axg_mipi_dsi_host,
+ &axg_isa,
+ &axg_pl301,
+ &axg_periphs,
+ &axg_spicc_0,
+ &axg_i2c,
+ &axg_rng0,
+ &axg_uart0,
+ &axg_mipi_dsi_phy,
+ &axg_spicc_1,
+ &axg_pcie_a,
+ &axg_pcie_b,
+ &axg_hiu_reg,
+ &axg_assist_misc,
+ &axg_emmc_b,
+ &axg_emmc_c,
+ &axg_dma,
+ &axg_spi,
+ &axg_audio,
+ &axg_eth_core,
+ &axg_uart1,
+ &axg_g2d,
+ &axg_usb0,
+ &axg_usb1,
+ &axg_reset,
+ &axg_usb_general,
+ &axg_ahb_arb0,
+ &axg_efuse,
+ &axg_boot_rom,
+ &axg_ahb_data_bus,
+ &axg_ahb_ctrl_bus,
+ &axg_usb1_to_ddr,
+ &axg_usb0_to_ddr,
+ &axg_mmc_pclk,
+ &axg_vpu_intr,
+ &axg_sec_ahb_ahb3_bridge,
+ &axg_gic,
+ &axg_ao_media_cpu,
+ &axg_ao_ahb_sram,
+ &axg_ao_ahb_bus,
+ &axg_ao_iface,
+ &axg_ao_i2c,
+ &axg_sd_emmc_b_clk0,
+ &axg_sd_emmc_c_clk0,
+};
+
+static struct clk_mux *const axg_clk_muxes[] = {
+ &axg_mpeg_clk_sel,
+ &axg_sd_emmc_b_clk0_sel,
+ &axg_sd_emmc_c_clk0_sel,
+};
+
+static struct clk_divider *const axg_clk_dividers[] = {
+ &axg_mpeg_clk_div,
+ &axg_sd_emmc_b_clk0_div,
+ &axg_sd_emmc_c_clk0_div,
+};
+
+struct clkc_data {
+ struct clk_gate *const *clk_gates;
+ unsigned int clk_gates_count;
+ struct meson_clk_mpll *const *clk_mplls;
+ unsigned int clk_mplls_count;
+ struct meson_clk_pll *const *clk_plls;
+ unsigned int clk_plls_count;
+ struct clk_mux *const *clk_muxes;
+ unsigned int clk_muxes_count;
+ struct clk_divider *const *clk_dividers;
+ unsigned int clk_dividers_count;
+ struct clk_hw_onecell_data *hw_onecell_data;
+};
+
+static const struct clkc_data axg_clkc_data = {
+ .clk_gates = axg_clk_gates,
+ .clk_gates_count = ARRAY_SIZE(axg_clk_gates),
+ .clk_mplls = axg_clk_mplls,
+ .clk_mplls_count = ARRAY_SIZE(axg_clk_mplls),
+ .clk_plls = axg_clk_plls,
+ .clk_plls_count = ARRAY_SIZE(axg_clk_plls),
+ .clk_muxes = axg_clk_muxes,
+ .clk_muxes_count = ARRAY_SIZE(axg_clk_muxes),
+ .clk_dividers = axg_clk_dividers,
+ .clk_dividers_count = ARRAY_SIZE(axg_clk_dividers),
+ .hw_onecell_data = &axg_hw_onecell_data,
+};
+
+static const struct of_device_id clkc_match_table[] = {
+ { .compatible = "amlogic,axg-clkc", .data = &axg_clkc_data },
+ {},
+};
+
+static int axg_clkc_probe(struct platform_device *pdev)
+{
+ const struct clkc_data *clkc_data;
+ void __iomem *clk_base;
+ int ret, clkid, i;
+ struct device *dev = &pdev->dev;
+
+ clkc_data = of_device_get_match_data(&pdev->dev);
+ if (!clkc_data)
+ return -EINVAL;
+
+ /* Generic clocks and PLLs */
+ clk_base = of_iomap(dev->of_node, 0);
+ if (!clk_base) {
+ pr_err("%s: Unable to map clk base\n", __func__);
+ return -ENXIO;
+ }
+
+ /* Populate base address for PLLs */
+ for (i = 0; i < clkc_data->clk_plls_count; i++)
+ clkc_data->clk_plls[i]->base = clk_base;
+
+ /* Populate base address for MPLLs */
+ for (i = 0; i < clkc_data->clk_mplls_count; i++)
+ clkc_data->clk_mplls[i]->base = clk_base;
+
+ /* Populate base address for gates */
+ for (i = 0; i < clkc_data->clk_gates_count; i++)
+ clkc_data->clk_gates[i]->reg = clk_base +
+ (u64)clkc_data->clk_gates[i]->reg;
+
+ /* Populate base address for muxes */
+ for (i = 0; i < clkc_data->clk_muxes_count; i++)
+ clkc_data->clk_muxes[i]->reg = clk_base +
+ (u64)clkc_data->clk_muxes[i]->reg;
+
+ /* Populate base address for dividers */
+ for (i = 0; i < clkc_data->clk_dividers_count; i++)
+ clkc_data->clk_dividers[i]->reg = clk_base +
+ (u64)clkc_data->clk_dividers[i]->reg;
+
+ /*
+ * register all clks
+ */
+ for (clkid = 0; clkid < clkc_data->hw_onecell_data->num; clkid++) {
+ /* array might be sparse */
+ if (!clkc_data->hw_onecell_data->hws[clkid])
+ continue;
+
+ ret = devm_clk_hw_register(dev,
+ clkc_data->hw_onecell_data->hws[clkid]);
+ if (ret)
+ goto iounmap;
+ }
+
+ return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+ clkc_data->hw_onecell_data);
+
+iounmap:
+ iounmap(clk_base);
+ return ret;
+}
+
+static struct platform_driver axg_driver = {
+ .probe = axg_clkc_probe,
+ .driver = {
+ .name = "axg-clkc",
+ .of_match_table = clkc_match_table,
+ },
+};
+
+builtin_platform_driver(axg_driver);
diff --git a/drivers/clk/meson/axg.h b/drivers/clk/meson/axg.h
new file mode 100644
index 000000000000..e85881c6c481
--- /dev/null
+++ b/drivers/clk/meson/axg.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2016 AmLogic, Inc.
+ * Author: Michael Turquette <mturquette@baylibre.com>
+ *
+ * Copyright (c) 2017 Amlogic, inc.
+ * Author: Qiufang Dai <qiufang.dai@amlogic.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+#ifndef __AXG_H
+#define __AXG_H
+
+/*
+ * Clock controller register offsets
+ *
+ * Register offsets from the data sheet must be multiplied by 4 before
+ * adding them to the base address to get the right value.
+ */
+#define HHI_GP0_PLL_CNTL (0x10 << 2)
+#define HHI_GP0_PLL_CNTL2 (0x11 << 2)
+#define HHI_GP0_PLL_CNTL3 (0x12 << 2)
+#define HHI_GP0_PLL_CNTL4 (0x13 << 2)
+#define HHI_GP0_PLL_CNTL5 (0x14 << 2)
+#define HHI_GP0_PLL_STS (0x15 << 2)
+#define HHI_GP0_PLL_CNTL1 (0x16 << 2)
+#define HHI_HIFI_PLL_CNTL (0x20 << 2)
+#define HHI_HIFI_PLL_CNTL2 (0x21 << 2)
+#define HHI_HIFI_PLL_CNTL3 (0x22 << 2)
+#define HHI_HIFI_PLL_CNTL4 (0x23 << 2)
+#define HHI_HIFI_PLL_CNTL5 (0x24 << 2)
+#define HHI_HIFI_PLL_STS (0x25 << 2)
+#define HHI_HIFI_PLL_CNTL1 (0x26 << 2)
+
+#define HHI_XTAL_DIVN_CNTL (0x2f << 2)
+#define HHI_GCLK2_MPEG0 (0x30 << 2)
+#define HHI_GCLK2_MPEG1 (0x31 << 2)
+#define HHI_GCLK2_MPEG2 (0x32 << 2)
+#define HHI_GCLK2_OTHER (0x34 << 2)
+#define HHI_GCLK2_AO (0x35 << 2)
+#define HHI_PCIE_PLL_CNTL (0x36 << 2)
+#define HHI_PCIE_PLL_CNTL1 (0x37 << 2)
+#define HHI_PCIE_PLL_CNTL2 (0x38 << 2)
+#define HHI_PCIE_PLL_CNTL3 (0x39 << 2)
+#define HHI_PCIE_PLL_CNTL4 (0x3a << 2)
+#define HHI_PCIE_PLL_CNTL5 (0x3b << 2)
+#define HHI_PCIE_PLL_CNTL6 (0x3c << 2)
+#define HHI_PCIE_PLL_STS (0x3d << 2)
+
+#define HHI_MEM_PD_REG0 (0x40 << 2)
+#define HHI_VPU_MEM_PD_REG0 (0x41 << 2)
+#define HHI_VIID_CLK_DIV (0x4a << 2)
+#define HHI_VIID_CLK_CNTL (0x4b << 2)
+
+#define HHI_GCLK_MPEG0 (0x50 << 2)
+#define HHI_GCLK_MPEG1 (0x51 << 2)
+#define HHI_GCLK_MPEG2 (0x52 << 2)
+#define HHI_GCLK_OTHER (0x54 << 2)
+#define HHI_GCLK_AO (0x55 << 2)
+#define HHI_SYS_CPU_CLK_CNTL1 (0x57 << 2)
+#define HHI_SYS_CPU_RESET_CNTL (0x58 << 2)
+#define HHI_VID_CLK_DIV (0x59 << 2)
+#define HHI_SPICC_HCLK_CNTL (0x5a << 2)
+
+#define HHI_MPEG_CLK_CNTL (0x5d << 2)
+#define HHI_VID_CLK_CNTL (0x5f << 2)
+#define HHI_TS_CLK_CNTL (0x64 << 2)
+#define HHI_VID_CLK_CNTL2 (0x65 << 2)
+#define HHI_SYS_CPU_CLK_CNTL0 (0x67 << 2)
+#define HHI_VID_PLL_CLK_DIV (0x68 << 2)
+#define HHI_VPU_CLK_CNTL (0x6f << 2)
+
+#define HHI_VAPBCLK_CNTL (0x7d << 2)
+
+#define HHI_GEN_CLK_CNTL (0x8a << 2)
+
+#define HHI_VDIN_MEAS_CLK_CNTL (0x94 << 2)
+#define HHI_NAND_CLK_CNTL (0x97 << 2)
+#define HHI_SD_EMMC_CLK_CNTL (0x99 << 2)
+
+#define HHI_MPLL_CNTL (0xa0 << 2)
+#define HHI_MPLL_CNTL2 (0xa1 << 2)
+#define HHI_MPLL_CNTL3 (0xa2 << 2)
+#define HHI_MPLL_CNTL4 (0xa3 << 2)
+#define HHI_MPLL_CNTL5 (0xa4 << 2)
+#define HHI_MPLL_CNTL6 (0xa5 << 2)
+#define HHI_MPLL_CNTL7 (0xa6 << 2)
+#define HHI_MPLL_CNTL8 (0xa7 << 2)
+#define HHI_MPLL_CNTL9 (0xa8 << 2)
+#define HHI_MPLL_CNTL10 (0xa9 << 2)
+
+#define HHI_MPLL3_CNTL0 (0xb8 << 2)
+#define HHI_MPLL3_CNTL1 (0xb9 << 2)
+#define HHI_PLL_TOP_MISC (0xba << 2)
+
+#define HHI_SYS_PLL_CNTL1 (0xbf << 2)
+#define HHI_SYS_PLL_CNTL (0xc0 << 2)
+#define HHI_SYS_PLL_CNTL2 (0xc1 << 2)
+#define HHI_SYS_PLL_CNTL3 (0xc2 << 2)
+#define HHI_SYS_PLL_CNTL4 (0xc3 << 2)
+#define HHI_SYS_PLL_CNTL5 (0xc4 << 2)
+#define HHI_SYS_PLL_STS (0xc5 << 2)
+#define HHI_DPLL_TOP_I (0xc6 << 2)
+#define HHI_DPLL_TOP2_I (0xc7 << 2)
+
+/*
+ * CLKID index values
+ *
+ * These indices are entirely contrived and do not map onto the hardware.
+ * It has now been decided to expose everything by default in the DT header:
+ * include/dt-bindings/clock/axg-clkc.h. Only the clocks ids we don't want
+ * to expose, such as the internal muxes and dividers of composite clocks,
+ * will remain defined here.
+ */
+#define CLKID_MPEG_SEL 8
+#define CLKID_MPEG_DIV 9
+#define CLKID_SD_EMMC_B_CLK0_SEL 61
+#define CLKID_SD_EMMC_B_CLK0_DIV 62
+#define CLKID_SD_EMMC_C_CLK0_SEL 63
+#define CLKID_SD_EMMC_C_CLK0_DIV 64
+
+#define NR_CLKS 65
+
+/* include the CLKIDs that have been made part of the DT binding */
+#include <dt-bindings/clock/axg-clkc.h>
+
+#endif /* __AXG_H */
diff --git a/include/dt-bindings/clock/axg-clkc.h b/include/dt-bindings/clock/axg-clkc.h
new file mode 100644
index 000000000000..d2c0f49ba0df
--- /dev/null
+++ b/include/dt-bindings/clock/axg-clkc.h
@@ -0,0 +1,72 @@
+/*
+ * Meson-AXG clock tree IDs
+ *
+ * Copyright (c) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+#ifndef __AXG_CLKC_H
+#define __AXG_CLKC_H
+
+#define CLKID_SYS_PLL 0
+#define CLKID_FIXED_PLL 1
+#define CLKID_FCLK_DIV2 2
+#define CLKID_FCLK_DIV3 3
+#define CLKID_FCLK_DIV4 4
+#define CLKID_FCLK_DIV5 5
+#define CLKID_FCLK_DIV7 6
+#define CLKID_GP0_PLL 7
+#define CLKID_CLK81 10
+#define CLKID_MPLL0 11
+#define CLKID_MPLL1 12
+#define CLKID_MPLL2 13
+#define CLKID_MPLL3 14
+#define CLKID_DDR 15
+#define CLKID_AUDIO_LOCKER 16
+#define CLKID_MIPI_DSI_HOST 17
+#define CLKID_ISA 18
+#define CLKID_PL301 19
+#define CLKID_PERIPHS 20
+#define CLKID_SPICC0 21
+#define CLKID_I2C 22
+#define CLKID_RNG0 23
+#define CLKID_UART0 24
+#define CLKID_MIPI_DSI_PHY 25
+#define CLKID_SPICC1 26
+#define CLKID_PCIE_A 27
+#define CLKID_PCIE_B 28
+#define CLKID_HIU_IFACE 29
+#define CLKID_ASSIST_MISC 30
+#define CLKID_SD_EMMC_B 31
+#define CLKID_SD_EMMC_C 32
+#define CLKID_DMA 33
+#define CLKID_SPI 34
+#define CLKID_AUDIO 35
+#define CLKID_ETH 36
+#define CLKID_UART1 37
+#define CLKID_G2D 38
+#define CLKID_USB0 39
+#define CLKID_USB1 40
+#define CLKID_RESET 41
+#define CLKID_USB 42
+#define CLKID_AHB_ARB0 43
+#define CLKID_EFUSE 44
+#define CLKID_BOOT_ROM 45
+#define CLKID_AHB_DATA_BUS 46
+#define CLKID_AHB_CTRL_BUS 47
+#define CLKID_USB1_DDR_BRIDGE 48
+#define CLKID_USB0_DDR_BRIDGE 49
+#define CLKID_MMC_PCLK 50
+#define CLKID_VPU_INTR 51
+#define CLKID_SEC_AHB_AHB3_BRIDGE 52
+#define CLKID_GIC 53
+#define CLKID_AO_MEDIA_CPU 54
+#define CLKID_AO_AHB_SRAM 55
+#define CLKID_AO_AHB_BUS 56
+#define CLKID_AO_IFACE 57
+#define CLKID_AO_I2C 58
+#define CLKID_SD_EMMC_B_CLK0 59
+#define CLKID_SD_EMMC_C_CLK0 60
+
+#endif /* __AXG_CLKC_H */
--
2.15.0
^ permalink raw reply related
* [PATCH v2 2/2] arm64: dts: meson-axg: add clock DT info for Meson AXG SoC
From: Yixun Lan @ 2017-11-27 9:48 UTC (permalink / raw)
To: Neil Armstrong, Jerome Brunet, Kevin Hilman
Cc: Rob Herring, Mark Rutland, Michael Turquette, Stephen Boyd,
Carlo Caione, Yixun Lan, Qiufang Dai, linux-amlogic, devicetree,
linux-clk, linux-arm-kernel, linux-kernel
In-Reply-To: <20171127094844.16742-1-yixun.lan@amlogic.com>
From: Qiufang Dai <qiufang.dai@amlogic.com>
Try to add Hiubus DT info, and also enable clock DT info
for the Amlogic's Meson-AXG SoC.
Signed-off-by: Qiufang Dai <qiufang.dai@amlogic.com>
Signed-off-by: Yixun Lan <yixun.lan@amlogic.com>
---
arch/arm64/boot/dts/amlogic/meson-axg.dtsi | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
index b932a784b02a..36a2e98338a8 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -7,6 +7,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/axg-clkc.h>
/ {
compatible = "amlogic,meson-axg";
@@ -148,6 +149,20 @@
#address-cells = <0>;
};
+ hiubus: hiubus@ff63c000 {
+ compatible = "simple-bus";
+ reg = <0x0 0xff63c000 0x0 0x1c00>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x1c00>;
+
+ clkc: clock-controller@0 {
+ compatible = "amlogic,axg-clkc";
+ #clock-cells = <1>;
+ reg = <0x0 0x0 0x0 0x320>;
+ };
+ };
+
mailbox: mailbox@ff63dc00 {
compatible = "amlogic,meson-gx-mhu", "amlogic,meson-gxbb-mhu";
reg = <0 0xff63dc00 0 0x400>;
--
2.15.0
^ permalink raw reply related
* [PATCH v2 0/3] True RNG driver for Samsung Exynos 5250+ SoCs
From: Łukasz Stelmach @ 2017-11-27 9:58 UTC (permalink / raw)
To: Andrew F. Davis, PrasannaKumar Muralidharan, Rob Herring,
Matt Mackall, Herbert Xu, Krzysztof Kozlowski,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Łukasz Stelmach, Marek Szyprowski, Bartlomiej Zolnierkiewicz
In-Reply-To: <CGME20171127095808eucas1p22ded3526ec44c8b9edf3e4480a811820@eucas1p2.samsung.com>
Hello.
The following patches add support for the true random number generator
found in Samsung Exynos 5250+ SoCs.
Patch #1 adds documentation for devicetree bindings.
Patch #2 introduces the driver and appropriate changes in Makefile and Kconfig.
Patch #3 adds nodes in devicetree files for Exynos SoCs.
Changes in v2:
- Fixed indentation in drivers/char/hw_random/Kconfig.
- Defined TRNG_CTRL_RGNEN.
- Removed global variable exynos_trng_dev.
- Removed exynos_trng_{set,get}_reg() functions.
- Used the min_t() macro instead of the ternary operator in
exynos_trng_do_read().
- Moved trng initialisation to the variable declaration in
exynos_trng_init().
- Fixed comment formating.
- Removed unnecessary "TODO" comments.
- Return ENOMEM, if devm_kzalloc() devm_kstrdup() fail.
- Rephrased and unified error messages in exynos_trng_probe().
- Removed nullification of trng->mem.
- Added err_pm_get label at the end of exynos_trng_probe().
- Removed double error message at the end of exynos_trng_probe().
- Implemented exynos_trng_remove().
Thank you, Krzysztof Kozlowski, Andrew F. Davis, PrasannaKumar
Muralidharan, Rob Herring.
v1 can be found:
https://www.spinics.net/lists/linux-samsung-soc/msg61253.html
https://patchwork.kernel.org/patch/10072967/
https://patchwork.kernel.org/patch/10072971/
https://patchwork.kernel.org/patch/10072963/
Łukasz Stelmach (3):
dt-bindings: hwrng: Add Samsung Exynos 5250+ True RNG bindings
hwrng: exynos - add Samsung Exynos True RNG driver
ARM: dts: exynos: Add nodes for True Random Number Generator
.../bindings/rng/samsung,exynos5250-trng.txt | 17 ++
MAINTAINERS | 7 +
arch/arm/boot/dts/exynos5.dtsi | 5 +
arch/arm/boot/dts/exynos5250.dtsi | 5 +
arch/arm/boot/dts/exynos5410.dtsi | 5 +
arch/arm/boot/dts/exynos5420.dtsi | 5 +
drivers/char/hw_random/Kconfig | 12 +
drivers/char/hw_random/Makefile | 1 +
drivers/char/hw_random/exynos-trng.c | 245 +++++++++++++++++++++
9 files changed, 302 insertions(+)
create mode 100644 Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt
create mode 100644 drivers/char/hw_random/exynos-trng.c
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 1/3] dt-bindings: hwrng: Add Samsung Exynos 5250+ True RNG bindings
From: Łukasz Stelmach @ 2017-11-27 9:58 UTC (permalink / raw)
To: Andrew F. Davis, PrasannaKumar Muralidharan, Rob Herring,
Matt Mackall, Herbert Xu, Krzysztof Kozlowski,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Łukasz Stelmach, Marek Szyprowski, Bartlomiej Zolnierkiewicz
In-Reply-To: <20171127095804.7128-1-l.stelmach-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Add binding documentation for the True Random Number Generator
found on Samsung Exynos 5250+ SoCs.
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Reviewed-by: Krzysztof Kozlowski <krzk-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Łukasz Stelmach <l.stelmach-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
---
.../devicetree/bindings/rng/samsung,exynos5250-trng.txt | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt
diff --git a/Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt b/Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt
new file mode 100644
index 000000000000..22dfe8cb21c0
--- /dev/null
+++ b/Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt
@@ -0,0 +1,17 @@
+Exynos True Random Number Generator
+
+Required properties:
+
+- compatible : Should be "samsung,exynos5250-trng".
+- reg : Specifies base physical address and size of the registers map.
+- clocks : Phandle to clock-controller plus clock-specifier pair.
+- clock-names : "secss" as a clock name.
+
+Example:
+
+ trng@10830600 {
+ compatible = "samsung,exynos5250-trng";
+ reg = <0x10830600 0x100>;
+ clocks = <&clock CLK_SSS>;
+ clock-names = "secss";
+ };
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 2/3] hwrng: exynos - add Samsung Exynos True RNG driver
From: Łukasz Stelmach @ 2017-11-27 9:58 UTC (permalink / raw)
To: Andrew F. Davis, PrasannaKumar Muralidharan, Rob Herring,
Matt Mackall, Herbert Xu, Krzysztof Kozlowski, devicetree,
linux-crypto, linux-samsung-soc, linux-kernel
Cc: Łukasz Stelmach, Marek Szyprowski, Bartlomiej Zolnierkiewicz
In-Reply-To: <20171127095804.7128-1-l.stelmach@samsung.com>
Add support for True Random Number Generator found in Samsung Exynos
5250+ SoCs.
Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
---
MAINTAINERS | 7 +
drivers/char/hw_random/Kconfig | 12 ++
drivers/char/hw_random/Makefile | 1 +
drivers/char/hw_random/exynos-trng.c | 245 +++++++++++++++++++++++++++++++++++
4 files changed, 265 insertions(+)
create mode 100644 drivers/char/hw_random/exynos-trng.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 2811a211632c..992074cca612 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11780,6 +11780,13 @@ S: Maintained
F: drivers/crypto/exynos-rng.c
F: Documentation/devicetree/bindings/rng/samsung,exynos-rng4.txt
+SAMSUNG EXYNOS TRUE RANDOM NUMBER GENERATOR (TRNG) DRIVER
+M: Łukasz Stelmach <l.stelmach@samsung.com>
+L: linux-samsung-soc@vger.kernel.org
+S: Maintained
+F: drivers/char/hw_random/exynos-trng.c
+F: Documentation/devicetree/bindings/rng/samsung,exynos5250-trng.txt
+
SAMSUNG FRAMEBUFFER DRIVER
M: Jingoo Han <jingoohan1@gmail.com>
L: linux-fbdev@vger.kernel.org
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 95a031e9eced..292e6b36d493 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -449,6 +449,18 @@ config HW_RANDOM_S390
If unsure, say Y.
+config HW_RANDOM_EXYNOS
+ tristate "Samsung Exynos True Random Number Generator support"
+ depends on ARCH_EXYNOS || COMPILE_TEST
+ default HW_RANDOM
+ ---help---
+ This driver provides support for the True Random Number
+ Generator available in Exynos SoCs.
+
+ To compile this driver as a module, choose M here: the module
+ will be called exynos-trng.
+
+ If unsure, say Y.
endif # HW_RANDOM
config UML_RANDOM
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index f3728d008fff..5595df97da7a 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o
n2-rng-y := n2-drv.o n2-asm.o
obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
+obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-trng.o
obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
obj-$(CONFIG_HW_RANDOM_OMAP3_ROM) += omap3-rom-rng.o
diff --git a/drivers/char/hw_random/exynos-trng.c b/drivers/char/hw_random/exynos-trng.c
new file mode 100644
index 000000000000..91b2ddb249fa
--- /dev/null
+++ b/drivers/char/hw_random/exynos-trng.c
@@ -0,0 +1,245 @@
+/*
+ * RNG driver for Exynos TRNGs
+ *
+ * Author: Łukasz Stelmach <l.stelmach@samsung.com>
+ *
+ * Copyright 2017 (c) Samsung Electronics Software, Inc.
+ *
+ * Based on the Exynos PRNG driver drivers/crypto/exynos-rng by
+ * Krzysztof Kozłowski <krzk@kernel.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/crypto.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#define EXYNOS_TRNG_CLKDIV (0x0)
+#define EXYNOS_TRNG_CTRL (0x20)
+#define EXYNOS_TRNG_POST_CTRL (0x30)
+#define EXYNOS_TRNG_ONLINE_CTRL (0x40)
+#define EXYNOS_TRNG_ONLINE_STAT (0x44)
+#define EXYNOS_TRNG_ONLINE_MAXCHI2 (0x48)
+#define EXYNOS_TRNG_FIFO_CTRL (0x50)
+#define EXYNOS_TRNG_FIFO_0 (0x80)
+#define EXYNOS_TRNG_FIFO_1 (0x84)
+#define EXYNOS_TRNG_FIFO_2 (0x88)
+#define EXYNOS_TRNG_FIFO_3 (0x8c)
+#define EXYNOS_TRNG_FIFO_4 (0x90)
+#define EXYNOS_TRNG_FIFO_5 (0x94)
+#define EXYNOS_TRNG_FIFO_6 (0x98)
+#define EXYNOS_TRNG_FIFO_7 (0x9c)
+#define EXYNOS_TRNG_FIFO_LEN (8)
+#define EXYNOS_TRNG_CLOCK_RATE (500000)
+
+#define TRNG_CTRL_RGNEN BIT(31)
+
+struct exynos_trng_dev {
+ struct device *dev;
+ void __iomem *mem;
+ struct clk *clk;
+ struct hwrng rng;
+};
+
+static int exynos_trng_do_read(struct hwrng *rng, void *data, size_t max,
+ bool wait)
+{
+ struct exynos_trng_dev *trng;
+ u32 val;
+
+ max = min_t(size_t, max, (EXYNOS_TRNG_FIFO_LEN * 4));
+
+ trng = (struct exynos_trng_dev *)rng->priv;
+
+ __raw_writel(max * 8, trng->mem + EXYNOS_TRNG_FIFO_CTRL);
+ val = readl_poll_timeout(trng->mem + EXYNOS_TRNG_FIFO_CTRL, val,
+ val == 0, 200, 1000000);
+ if (val < 0)
+ return val;
+
+ memcpy_fromio(data, trng->mem + EXYNOS_TRNG_FIFO_0, max);
+
+ return max;
+}
+
+static int exynos_trng_init(struct hwrng *rng)
+{
+ struct exynos_trng_dev *trng = (struct exynos_trng_dev *)rng->priv;
+ unsigned long sss_rate;
+ u32 val;
+
+ sss_rate = clk_get_rate(trng->clk);
+
+ /*
+ * For most TRNG circuits the clock frequency of under 500 kHz
+ * is safe.
+ */
+ val = sss_rate / (EXYNOS_TRNG_CLOCK_RATE * 2);
+ if (val > 0x7fff) {
+ dev_err(trng->dev, "clock divider too large: %d", val);
+ return -ERANGE;
+ }
+ val = val << 1;
+ __raw_writel(val, trng->mem + EXYNOS_TRNG_CLKDIV);
+
+ /* Enable the generator. */
+ val = TRNG_CTRL_RGNEN;
+ __raw_writel(val, trng->mem + EXYNOS_TRNG_CTRL);
+
+ /*
+ * Disable post-processing. /dev/hwrng is supposed to deliver
+ * unprocessed data.
+ */
+ __raw_writel(0, trng->mem + EXYNOS_TRNG_POST_CTRL);
+
+ return 0;
+}
+
+static int exynos_trng_probe(struct platform_device *pdev)
+{
+ struct exynos_trng_dev *trng;
+ struct resource *res;
+ int ret = -ENOMEM;
+
+ trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL);
+ if (!trng)
+ return ret;
+
+ trng->rng.name = devm_kstrdup(&pdev->dev, dev_name(&pdev->dev),
+ GFP_KERNEL);
+ if (!trng->rng.name)
+ return ret;
+
+ trng->rng.init = exynos_trng_init;
+ trng->rng.read = exynos_trng_do_read;
+ trng->rng.priv = (unsigned long) trng;
+
+ platform_set_drvdata(pdev, trng);
+ trng->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ trng->mem = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(trng->mem)) {
+ ret = PTR_ERR(trng->mem);
+ dev_err(&pdev->dev, "Could not map IO resources.\n");
+ goto err_ioremap;
+ }
+
+ pm_runtime_enable(&pdev->dev);
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Could not get runtime PM.\n");
+ goto err_pm_get;
+ }
+
+ trng->clk = devm_clk_get(&pdev->dev, "secss");
+ if (IS_ERR(trng->clk)) {
+ ret = PTR_ERR(trng->clk);
+ dev_err(&pdev->dev, "Could not get clock.\n");
+ goto err_clock;
+ }
+
+ ret = clk_prepare_enable(trng->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not enable the clk.\n");
+ goto err_clock;
+ }
+
+ ret = hwrng_register(&trng->rng);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register hwrng device.\n");
+ goto err_register;
+ }
+
+ dev_info(&pdev->dev, "Exynos True Random Number Generator.\n");
+
+ return 0;
+
+err_register:
+ clk_disable_unprepare(trng->clk);
+
+err_clock:
+ pm_runtime_put_sync(&pdev->dev);
+
+err_pm_get:
+ pm_runtime_disable(&pdev->dev);
+
+err_ioremap:
+ return ret;
+}
+
+static int exynos_trng_remove(struct platform_device *pdev)
+{
+ struct exynos_trng_dev *trng = platform_get_drvdata(pdev);
+
+ hwrng_unregister(&trng->rng);
+ clk_disable_unprepare(trng->clk);
+
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+static int __maybe_unused exynos_trng_suspend(struct device *dev)
+{
+ pm_runtime_put_sync(dev);
+
+ return 0;
+}
+
+static int __maybe_unused exynos_trng_resume(struct device *dev)
+{
+ int ret;
+
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0) {
+ dev_err(dev, "Could not get runtime PM.\n");
+ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(exynos_trng_pm_ops, exynos_trng_suspend,
+ exynos_trng_resume);
+
+static const struct of_device_id exynos_trng_dt_match[] = {
+ {
+ .compatible = "samsung,exynos5250-trng",
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, exynos_rng_dt_match);
+
+static struct platform_driver exynos_trng_driver = {
+ .driver = {
+ .name = "exynos-trng",
+ .pm = &exynos_trng_pm_ops,
+ .of_match_table = exynos_trng_dt_match,
+ },
+ .probe = exynos_trng_probe,
+ .remove = exynos_trng_remove,
+};
+
+module_platform_driver(exynos_trng_driver);
+MODULE_AUTHOR("Łukasz Stelmach");
+MODULE_DESCRIPTION("H/W TRNG driver for Exynos chips");
+MODULE_LICENSE("GPL");
--
2.11.0
^ permalink raw reply related
* [PATCH v2 3/3] ARM: dts: exynos: Add nodes for True Random Number Generator
From: Łukasz Stelmach @ 2017-11-27 9:58 UTC (permalink / raw)
To: Andrew F. Davis, PrasannaKumar Muralidharan, Rob Herring,
Matt Mackall, Herbert Xu, Krzysztof Kozlowski, devicetree,
linux-crypto, linux-samsung-soc, linux-kernel
Cc: Łukasz Stelmach, Marek Szyprowski, Bartlomiej Zolnierkiewicz
In-Reply-To: <20171127095804.7128-1-l.stelmach@samsung.com>
Add nodes for the True Random Number Generator found in Samsung Exynos
5250+ SoCs.
Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
---
arch/arm/boot/dts/exynos5.dtsi | 5 +++++
arch/arm/boot/dts/exynos5250.dtsi | 5 +++++
arch/arm/boot/dts/exynos5410.dtsi | 5 +++++
arch/arm/boot/dts/exynos5420.dtsi | 5 +++++
4 files changed, 20 insertions(+)
diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index 7da4a4285b24..6a298b536e1c 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -210,5 +210,10 @@
reg = <0x10830000 0x300>;
interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
};
+
+ trng: trng@10830600 {
+ compatible = "samsung,exynos5250-trng";
+ reg = <0x10830600 0x100>;
+ };
};
};
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 8032d7e567fc..332fe04b772b 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -1081,4 +1081,9 @@
clock-names = "secss";
};
+&trng {
+ clocks = <&clock CLK_SSS>;
+ clock-names = "secss";
+};
+
#include "exynos5250-pinctrl.dtsi"
diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 7eab4bc07cec..f3991206a562 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -379,6 +379,11 @@
3 0 0x07000000 0x20000>;
};
+&trng {
+ clocks = <&clock CLK_SSS>;
+ clock-names = "secss";
+};
+
&usbdrd3_0 {
clocks = <&clock CLK_USBD300>;
clock-names = "usbdrd30";
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 02d2f898efa6..2f4e5542f354 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -1454,6 +1454,11 @@
clock-names = "secss";
};
+&trng {
+ clocks = <&clock CLK_SSS>;
+ clock-names = "secss";
+};
+
&usbdrd3_0 {
clocks = <&clock CLK_USBD300>;
clock-names = "usbdrd30";
--
2.11.0
^ permalink raw reply related
* Re: [RFC v1 5/8] Bluetooth: btrtl: add support for the RTL8723BS and RTL8723DS chips
From: Marcel Holtmann @ 2017-11-27 10:00 UTC (permalink / raw)
To: Martin Blumenstingl
Cc: Rob Herring, devicetree, open list:BLUETOOTH DRIVERS,
linux-serial-u79uwXL29TY76Z2rM5mHXA, Mark Rutland,
Gustavo F. Padovan, Johan Hedberg, Greg Kroah-Hartman, Jiri Slaby,
Johan Hovold, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ
In-Reply-To: <CAFBinCD+P6kBOXjp9YZf8DbsetvF+q6yfp3X+OTRfN_Pv8R88w-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hi Martin,
>>>>> The Realtek RTL8723BS and RTL8723DS chipsets are SDIO wifi chips. They
>>>>> also contain a Bluetooth module which is connected via UART to the host.
>>>>>
>>>>> Realtek's userspace initialization tool (rtk_hciattach) differentiates
>>>>> these two via the HCI version and revision returned by the
>>>>> HCI_OP_READ_LOCAL_VERSION command.
>>>>> Additionally we apply these checks only the for UART devices. Everything
>>>>> else is assumed to be a "RTL8723B" which was originally supported by the
>>>>> driver (communicating via USB).
>>>>>
>>>>> Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
>>>>> ---
>>>>> drivers/bluetooth/btrtl.c | 32 ++++++++++++++++++++++++++++++--
>>>>> 1 file changed, 30 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c
>>>>> index 45b872f5ad22..d896f9421250 100644
>>>>> --- a/drivers/bluetooth/btrtl.c
>>>>> +++ b/drivers/bluetooth/btrtl.c
>>>>> @@ -418,9 +418,33 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev)
>>>>> has_rom_version = false;
>>>>> break;
>>>>> case RTL_ROM_LMP_8723B:
>>>>> - fw_name = "rtl_bt/rtl8723b_fw.bin";
>>>>> - cfg_name = "rtl_bt/rtl8723b_config.bin";
>>>>> + /* all variants support reading the ROM version */
>>>>> has_rom_version = true;
>>>>> +
>>>>> + /*
>>>>> + * RTL8723 devices exist in different variants:
>>>>> + * - RTL8723BS (SDIO chip with UART Bluetooth)
>>>>> + * - RTL8723DS (SDIO chip with UART Bluetooth)
>>>>> + * - for backwards-compatibility everything else is assumed to
>>>>> + * be an RTL8723B communicating over USB
>>>>> + *
>>>>> + * Only UART devices really need the config because that
>>>>> + * contains the UART speed / flow control settings.
>>>>> + */
>>>>> + if (hdev->bus == HCI_UART && resp->hci_ver == 6 &&
>>>>> + le16_to_cpu(resp->hci_rev) == 0xb) {
>>>>> + fw_name = "rtl_bt/rtl8723bs_fw.bin";
>>>>> + cfg_name = "rtl_bt/rtl8723bs_config.bin";
>>>>> + cfg_needed = true;
>>>>> + } else if (hdev->bus == HCI_UART && resp->hci_ver == 8 &&
>>>>> + le16_to_cpu(resp->hci_rev) == 0xd) {
>>>>> + fw_name = "rtl_bt/rtl8723ds_fw.bin";
>>>>> + cfg_name = "rtl_bt/rtl872ds_config.bin";
>>>>> + cfg_needed = true;
>>>>> + } else {
>>>>> + fw_name = "rtl_bt/rtl8723b_fw.bin";
>>>>> + cfg_name = "rtl_bt/rtl8723b_config.bin";
>>>>> + }
>>>>
>>>> so the main question is why is this a config file in the first place? So far all other drivers have expressed UART settings via DT (or even via ACPI). If we are just getting the baudrates, then better have this in DT. Since otherwise we end up with board specific filesystems again where different config files need to be installed. That is really not useful in the end.
>>> this is an excellent question (and also the reason why it's an "RFC" patch)!
>>> I'll try to figure out whether:
>>> a) we can skip the config file completely
> skipping the config blob causes it to time out at the end of the
> firmware download (where the config seems to be applied internally)
>
>>> b) we can generate the config file in-memory
> I tried this as well with a very minimal version (where only the
> "known" bits are used)
> unfortunately this shows the same symptoms as skipping the config blob
> I'll try experimenting with this to see if I can get it to work somehow
>
>>> c) we have to stick with this config file
> I'm afraid this would be our last option if I can't get b) working
> a datasheet for these chips or some advice from someone who has access
> to the datasheet/knowledge about the internals would be of great help
since they are all HCI commands, lets add tracing support in btmon for these and then check which one is needed and which one can be done via DT information. It might be as simple as that the chip needs a special reset command and the coded it in the config blob. I have seen some manufactures do that.
For starters just run btmon -w trace.log before you load the module (or attach the device) and then see what goes on during loading phase.
Regards
Marcel
^ permalink raw reply
* [PATCH V6 00/12] add clock driver for Spreadtrum platforms
From: Chunyan Zhang @ 2017-11-27 10:01 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
From: Chunyan Zhang <zhang.chunyan@linaro.org>
This series adds Spreadtrum clock support together with its binding
documentation and devicetree data.
This patchset also added a few common clock mactos into drivers/clk/clk_common.h,
which are generally useful for all vendors' clock driver, sunxi-ng, zte, sprd
(added in this patchse) use them (or part of them) at present, once this patchset
is merged, I can help to remove the duplicated code which is under the vendors'
respective directories.
Thanks,
Chunyan
Changes from V5: (https://lkml.org/lkml/2017/11/20/21)
* Rebased the whole patch-set to 4.15-rc1;
* Fixed kbuild-test warnings;
* Switched to use devm_clk_hw_register() instead of clk_hw_register();
* Removed useless debug information from sc9860-clk.c.
Changes from V4: (https://lkml.org/lkml/2017/11/10/30)
* Added acked-by of Rob Herring;
* Removed spin lock from Spreadtrum's gate, mux, div drivers, since we have
switched to use regmap.
Changes from V3: (https://lkml.org/lkml/2017/11/2/61)
* Addressed comments from Julien Thierry:
- Clean the if branch of sprd_mux_helper_get_parent()
- Have the Gate clock macros and ops for both mode (i.e. sc_gate and gate) separate;
- Have the Mux clock macros with/without table separate, and same changes
for the composite clock.
* Switched the function name from _endisable to _toggle;
* Fixed Kbuild test error:
- Added exporting sprd_clk_regmap_init() which would be used in other module(s);
* Change the function sprd_clk_set_regmap() to the static one, and removed the
declear from the include file;
* Addressed comments from Rob:
- Separate the dt-binding include file from the driver patch;
- Documented more for the property "clocks"
* Changed the syscon device names;
* Changed the name of 'sprd_mux_internal' to 'sprd_mux_ssel'
Changes from V2: (http://lkml.iu.edu/hypermail/linux/kernel/1707.1/01504.html)
* Switch to use regmap to access registers;
* Splited all clocks into 16 separated nodes, for each belongs to a single address area;
* Rearranged the order of clock declaration in sc9860-clk.c, sorted them upon the address area;
* Added syscon device tree nodes which will be quoted by the node of clocks which are in
the same address area with the syscon device;
* Revised the binding documentation according to the dt modification.
Changes from V1: (https://lkml.org/lkml/2017/6/17/356)
* Address Stephen's comments:
- Switch to use platform device driver instead of the DT probing mechanism.
- Move the common clock macro out from vendor directory, but need to remove those
overlap code from other vendors (such as sunxi-ng) once this get merged.
- Add support to be built as a module.
- Add 'sprd_' prefix for all spin locks used in these drivers.
- Mark input parameter of sprd_x with const.
- Remove unreasonable dependencies to CONFIG_64BIT.
- Add readl() after writing the same register.
- Remove CLK_IS_BASIC which is no longer used.
- Remove unnecessery CLK_IGNORE_UNUSED when defining a clock.
- Change to expose all clock index.
- Use clk_ instead of ccu.
- Add Kconfig for sprd clocks.
- Move the fixed clocks out from the soc node.
- Switch to use 64-bit math in pll driver instead of 32-bit math.
* Revise binding documentation according to dt modification.
* Rename sc9860.c to sc9860-clk.c
Chunyan Zhang (12):
drivers: move clock common macros out from vendor directories
clk: sprd: Add common infrastructure
clk: sprd: add gate clock support
clk: sprd: add mux clock support
clk: sprd: add divider clock support
clk: sprd: add composite clock support
clk: sprd: add adjustable pll support
dt-bindings: Add Spreadtrum clock binding documentation
clk: sprd: Add dt-bindings include file for SC9860
clk: sprd: add clocks support for SC9860
arm64: dts: add syscon for whale2 platform
arm64: dts: add clocks for SC9860
Documentation/devicetree/bindings/clock/sprd.txt | 63 +
arch/arm64/boot/dts/sprd/sc9860.dtsi | 115 ++
arch/arm64/boot/dts/sprd/whale2.dtsi | 48 +-
drivers/clk/Kconfig | 1 +
drivers/clk/Makefile | 1 +
drivers/clk/clk_common.h | 60 +
drivers/clk/sprd/Kconfig | 14 +
drivers/clk/sprd/Makefile | 11 +
drivers/clk/sprd/common.c | 99 ++
drivers/clk/sprd/common.h | 52 +
drivers/clk/sprd/composite.c | 62 +
drivers/clk/sprd/composite.h | 53 +
drivers/clk/sprd/div.c | 92 +
drivers/clk/sprd/div.h | 77 +
drivers/clk/sprd/gate.c | 113 ++
drivers/clk/sprd/gate.h | 61 +
drivers/clk/sprd/mux.c | 78 +
drivers/clk/sprd/mux.h | 76 +
drivers/clk/sprd/pll.c | 268 +++
drivers/clk/sprd/pll.h | 110 ++
drivers/clk/sprd/sc9860-clk.c | 1981 ++++++++++++++++++++++
include/dt-bindings/clock/sprd,sc9860-clk.h | 408 +++++
22 files changed, 3841 insertions(+), 2 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt
create mode 100644 drivers/clk/clk_common.h
create mode 100644 drivers/clk/sprd/Kconfig
create mode 100644 drivers/clk/sprd/Makefile
create mode 100644 drivers/clk/sprd/common.c
create mode 100644 drivers/clk/sprd/common.h
create mode 100644 drivers/clk/sprd/composite.c
create mode 100644 drivers/clk/sprd/composite.h
create mode 100644 drivers/clk/sprd/div.c
create mode 100644 drivers/clk/sprd/div.h
create mode 100644 drivers/clk/sprd/gate.c
create mode 100644 drivers/clk/sprd/gate.h
create mode 100644 drivers/clk/sprd/mux.c
create mode 100644 drivers/clk/sprd/mux.h
create mode 100644 drivers/clk/sprd/pll.c
create mode 100644 drivers/clk/sprd/pll.h
create mode 100644 drivers/clk/sprd/sc9860-clk.c
create mode 100644 include/dt-bindings/clock/sprd,sc9860-clk.h
--
2.7.4
^ permalink raw reply
* [PATCH V6 01/12] drivers: move clock common macros out from vendor directories
From: Chunyan Zhang @ 2017-11-27 10:01 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171127100115.20655-1-chunyan.zhang@spreadtrum.com>
These macros are used by more than one SoC vendor platforms, avoid to
have many copies of these code, this patch moves them to the common
clock directory which every clock drivers can access to.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/clk_common.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
create mode 100644 drivers/clk/clk_common.h
diff --git a/drivers/clk/clk_common.h b/drivers/clk/clk_common.h
new file mode 100644
index 0000000..21e93d2
--- /dev/null
+++ b/drivers/clk/clk_common.h
@@ -0,0 +1,60 @@
+/*
+ * drivers/clk/clk_common.h
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _CLK_COMMON_H_
+#define _CLK_COMMON_H_
+
+#include <linux/clk-provider.h>
+
+#define CLK_HW_INIT(_name, _parent, _ops, _flags) \
+ (&(struct clk_init_data) { \
+ .flags = _flags, \
+ .name = _name, \
+ .parent_names = (const char *[]) { _parent }, \
+ .num_parents = 1, \
+ .ops = _ops, \
+ })
+
+#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags) \
+ (&(struct clk_init_data) { \
+ .flags = _flags, \
+ .name = _name, \
+ .parent_names = _parents, \
+ .num_parents = ARRAY_SIZE(_parents), \
+ .ops = _ops, \
+ })
+
+#define CLK_HW_INIT_NO_PARENT(_name, _ops, _flags) \
+ (&(struct clk_init_data) { \
+ .flags = _flags, \
+ .name = _name, \
+ .parent_names = NULL, \
+ .num_parents = 0, \
+ .ops = _ops, \
+ })
+
+#define CLK_FIXED_FACTOR(_struct, _name, _parent, \
+ _div, _mult, _flags) \
+ struct clk_fixed_factor _struct = { \
+ .div = _div, \
+ .mult = _mult, \
+ .hw.init = CLK_HW_INIT(_name, \
+ _parent, \
+ &clk_fixed_factor_ops, \
+ _flags), \
+ }
+
+#define CLK_FIXED_RATE(_struct, _name, _flags, \
+ _fixed_rate, _fixed_accuracy) \
+ struct clk_fixed_rate _struct = { \
+ .fixed_rate = _fixed_rate, \
+ .fixed_accuracy = _fixed_accuracy, \
+ .hw.init = CLK_HW_INIT_NO_PARENT(_name, \
+ &clk_fixed_rate_ops, \
+ _flags), \
+ }
+
+#endif /* _CLK_COMMON_H_ */
--
2.7.4
^ permalink raw reply related
* [PATCH V6 02/12] clk: sprd: Add common infrastructure
From: Chunyan Zhang @ 2017-11-27 10:01 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171127100115.20655-1-chunyan.zhang@spreadtrum.com>
Added Spreadtrum's clock driver framework together with common
structures and interface functions.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/Kconfig | 1 +
drivers/clk/Makefile | 1 +
drivers/clk/sprd/Kconfig | 4 ++
drivers/clk/sprd/Makefile | 3 ++
drivers/clk/sprd/common.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/sprd/common.h | 52 +++++++++++++++++++++++++
6 files changed, 160 insertions(+)
create mode 100644 drivers/clk/sprd/Kconfig
create mode 100644 drivers/clk/sprd/Makefile
create mode 100644 drivers/clk/sprd/common.c
create mode 100644 drivers/clk/sprd/common.h
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 1c4e1aa..ce1a32be 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -236,6 +236,7 @@ source "drivers/clk/mvebu/Kconfig"
source "drivers/clk/qcom/Kconfig"
source "drivers/clk/renesas/Kconfig"
source "drivers/clk/samsung/Kconfig"
+source "drivers/clk/sprd/Kconfig"
source "drivers/clk/sunxi-ng/Kconfig"
source "drivers/clk/tegra/Kconfig"
source "drivers/clk/ti/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f7f761b..d880d13 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
obj-$(CONFIG_ARCH_SIRF) += sirf/
obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
obj-$(CONFIG_PLAT_SPEAR) += spear/
+obj-$(CONFIG_ARCH_SPRD) += sprd/
obj-$(CONFIG_ARCH_STI) += st/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-$(CONFIG_ARCH_SUNXI) += sunxi-ng/
diff --git a/drivers/clk/sprd/Kconfig b/drivers/clk/sprd/Kconfig
new file mode 100644
index 0000000..67a3287
--- /dev/null
+++ b/drivers/clk/sprd/Kconfig
@@ -0,0 +1,4 @@
+config SPRD_COMMON_CLK
+ tristate "Clock support for Spreadtrum SoCs"
+ depends on ARCH_SPRD || COMPILE_TEST
+ default ARCH_SPRD
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
new file mode 100644
index 0000000..74f4b80
--- /dev/null
+++ b/drivers/clk/sprd/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o
+
+clk-sprd-y += common.o
diff --git a/drivers/clk/sprd/common.c b/drivers/clk/sprd/common.c
new file mode 100644
index 0000000..4e38b74a
--- /dev/null
+++ b/drivers/clk/sprd/common.c
@@ -0,0 +1,99 @@
+/*
+ * Spreadtrum clock infrastructure
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+
+#include "common.h"
+
+static const struct regmap_config sprdclk_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xffff,
+ .fast_io = true,
+};
+
+static void sprd_clk_set_regmap(const struct sprd_clk_desc *desc,
+ struct regmap *regmap)
+{
+ int i;
+ struct sprd_clk_common *cclk;
+
+ for (i = 0; i < desc->num_clk_clks; i++) {
+ cclk = desc->clk_clks[i];
+ if (!cclk)
+ continue;
+
+ cclk->regmap = regmap;
+ }
+}
+
+int sprd_clk_regmap_init(struct platform_device *pdev,
+ const struct sprd_clk_desc *desc)
+{
+ void __iomem *base;
+ struct device_node *node = pdev->dev.of_node;
+ struct regmap *regmap = NULL;
+
+ if (of_find_property(node, "sprd,syscon", NULL)) {
+ regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon");
+ if (IS_ERR(regmap)) {
+ pr_err("%s: failed to get syscon regmap\n", __func__);
+ return PTR_ERR(regmap);
+ }
+ } else {
+ base = of_iomap(node, 0);
+ regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &sprdclk_regmap_config);
+ if (IS_ERR(regmap)) {
+ pr_err("failed to init regmap.\n");
+ return PTR_ERR(regmap);
+ }
+ }
+
+ sprd_clk_set_regmap(desc, regmap);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sprd_clk_regmap_init);
+
+int sprd_clk_probe(struct device *dev, struct clk_hw_onecell_data *clkhw)
+{
+ int i, ret = 0;
+ struct clk_hw *hw;
+
+ for (i = 0; i < clkhw->num; i++) {
+
+ hw = clkhw->hws[i];
+
+ if (!hw)
+ continue;
+
+ ret = devm_clk_hw_register(dev, hw);
+ if (ret) {
+ dev_err(dev, "Couldn't register clock %d - %s\n",
+ i, hw->init->name);
+ return ret;
+ }
+ }
+
+ ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+ clkhw);
+ if (ret)
+ dev_err(dev, "Failed to add clock provider.\n");
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(sprd_clk_probe);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/sprd/common.h b/drivers/clk/sprd/common.h
new file mode 100644
index 0000000..8cd774e
--- /dev/null
+++ b/drivers/clk/sprd/common.h
@@ -0,0 +1,52 @@
+/*
+ * Spreadtrum clock infrastructure
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _SPRD_CLK_COMMON_H_
+#define _SPRD_CLK_COMMON_H_
+
+#include <linux/clk-provider.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+
+#include "../clk_common.h"
+
+struct device_node;
+
+struct sprd_clk_common {
+ struct regmap *regmap;
+ u32 reg;
+ struct clk_hw hw;
+};
+
+struct sprd_clk_desc {
+ struct sprd_clk_common **clk_clks;
+ unsigned long num_clk_clks;
+ struct clk_hw_onecell_data *hw_clks;
+};
+
+#define sprd_regmap_read(map, reg, val) \
+({ \
+ (map) ? regmap_read((map), (reg), (val)) : (-EINVAL); \
+})
+
+#define sprd_regmap_write(map, reg, val) \
+({ \
+ (map) ? regmap_write((map), (reg), (val)) : (-EINVAL); \
+})
+
+static inline struct sprd_clk_common *
+ hw_to_sprd_clk_common(const struct clk_hw *hw)
+{
+ return container_of(hw, struct sprd_clk_common, hw);
+}
+int sprd_clk_regmap_init(struct platform_device *pdev,
+ const struct sprd_clk_desc *desc);
+int sprd_clk_probe(struct device *dev, struct clk_hw_onecell_data *clkhw);
+
+#endif /* _SPRD_CLK_COMMON_H_ */
--
2.7.4
^ permalink raw reply related
* [PATCH V6 03/12] clk: sprd: add gate clock support
From: Chunyan Zhang @ 2017-11-27 10:01 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171127100115.20655-1-chunyan.zhang@spreadtrum.com>
Some clocks on the Spreadtrum's SoCs are just simple gates. Add
support for those clocks.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/sprd/Makefile | 1 +
drivers/clk/sprd/gate.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/sprd/gate.h | 61 +++++++++++++++++++++++++
3 files changed, 175 insertions(+)
create mode 100644 drivers/clk/sprd/gate.c
create mode 100644 drivers/clk/sprd/gate.h
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 74f4b80..8cd5592 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o
clk-sprd-y += common.o
+clk-sprd-y += gate.o
diff --git a/drivers/clk/sprd/gate.c b/drivers/clk/sprd/gate.c
new file mode 100644
index 0000000..5dcc6a8
--- /dev/null
+++ b/drivers/clk/sprd/gate.c
@@ -0,0 +1,113 @@
+/*
+ * Spreadtrum gate clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+#include "gate.h"
+
+static void clk_gate_toggle(const struct sprd_gate *sg, bool en)
+{
+ const struct sprd_clk_common *common = &sg->common;
+ unsigned int reg;
+ bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? true : false;
+
+ set ^= en;
+
+ sprd_regmap_read(common->regmap, common->reg, ®);
+
+ if (set)
+ reg |= sg->enable_mask;
+ else
+ reg &= ~sg->enable_mask;
+
+ sprd_regmap_write(common->regmap, common->reg, reg);
+}
+
+static void clk_sc_gate_toggle(const struct sprd_gate *sg, bool en)
+{
+ const struct sprd_clk_common *common = &sg->common;
+ bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+ unsigned int offset;
+
+ set ^= en;
+
+ /*
+ * Each set/clear gate clock has three registers:
+ * common->reg - base register
+ * common->reg + offset - set register
+ * common->reg + 2 * offset - clear register
+ */
+ offset = set ? sg->sc_offset : sg->sc_offset * 2;
+
+ sprd_regmap_write(common->regmap, common->reg + offset,
+ sg->enable_mask);
+}
+
+static void sprd_gate_disable(struct clk_hw *hw)
+{
+ struct sprd_gate *sg = hw_to_sprd_gate(hw);
+
+ clk_gate_toggle(sg, false);
+}
+
+static int sprd_gate_enable(struct clk_hw *hw)
+{
+ struct sprd_gate *sg = hw_to_sprd_gate(hw);
+
+ clk_gate_toggle(sg, true);
+
+ return 0;
+}
+
+static void sprd_sc_gate_disable(struct clk_hw *hw)
+{
+ struct sprd_gate *sg = hw_to_sprd_gate(hw);
+
+ clk_sc_gate_toggle(sg, false);
+}
+
+static int sprd_sc_gate_enable(struct clk_hw *hw)
+{
+ struct sprd_gate *sg = hw_to_sprd_gate(hw);
+
+ clk_sc_gate_toggle(sg, true);
+
+ return 0;
+}
+static int sprd_gate_is_enabled(struct clk_hw *hw)
+{
+ struct sprd_gate *sg = hw_to_sprd_gate(hw);
+ struct sprd_clk_common *common = &sg->common;
+ unsigned int reg;
+
+ sprd_regmap_read(common->regmap, common->reg, ®);
+
+ if (sg->flags & CLK_GATE_SET_TO_DISABLE)
+ reg ^= sg->enable_mask;
+
+ reg &= sg->enable_mask;
+
+ return reg ? 1 : 0;
+}
+
+const struct clk_ops sprd_gate_ops = {
+ .disable = sprd_gate_disable,
+ .enable = sprd_gate_enable,
+ .is_enabled = sprd_gate_is_enabled,
+};
+EXPORT_SYMBOL_GPL(sprd_gate_ops);
+
+const struct clk_ops sprd_sc_gate_ops = {
+ .disable = sprd_sc_gate_disable,
+ .enable = sprd_sc_gate_enable,
+ .is_enabled = sprd_gate_is_enabled,
+};
+EXPORT_SYMBOL_GPL(sprd_sc_gate_ops);
+
diff --git a/drivers/clk/sprd/gate.h b/drivers/clk/sprd/gate.h
new file mode 100644
index 0000000..72e5b1a5
--- /dev/null
+++ b/drivers/clk/sprd/gate.h
@@ -0,0 +1,61 @@
+/*
+ * Spreadtrum gate clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _SPRD_GATE_H_
+#define _SPRD_GATE_H_
+
+#include "common.h"
+
+struct sprd_gate {
+ u32 enable_mask;
+ u16 flags;
+ u16 sc_offset;
+
+ struct sprd_clk_common common;
+};
+
+#define SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, _sc_offset, \
+ _enable_mask, _flags, _gate_flags, _ops) \
+ struct sprd_gate _struct = { \
+ .enable_mask = _enable_mask, \
+ .sc_offset = _sc_offset, \
+ .flags = _gate_flags, \
+ .common = { \
+ .regmap = NULL, \
+ .reg = _reg, \
+ .hw.init = CLK_HW_INIT(_name, \
+ _parent, \
+ _ops, \
+ _flags), \
+ } \
+ }
+
+#define SPRD_GATE_CLK(_struct, _name, _parent, _reg, \
+ _enable_mask, _flags, _gate_flags) \
+ SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, 0, \
+ _enable_mask, _flags, _gate_flags, \
+ &sprd_gate_ops)
+
+#define SPRD_SC_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset, \
+ _enable_mask, _flags, _gate_flags) \
+ SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, _sc_offset, \
+ _enable_mask, _flags, _gate_flags, \
+ &sprd_sc_gate_ops)
+
+static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw)
+{
+ struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+ return container_of(common, struct sprd_gate, common);
+}
+
+extern const struct clk_ops sprd_gate_ops;
+extern const struct clk_ops sprd_sc_gate_ops;
+
+#endif /* _SPRD_GATE_H_ */
--
2.7.4
^ permalink raw reply related
* [PATCH V6 04/12] clk: sprd: add mux clock support
From: Chunyan Zhang @ 2017-11-27 10:01 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171127100115.20655-1-chunyan.zhang@spreadtrum.com>
This patch adds clock multiplexor support for Spreadtrum platforms,
the mux clocks also can be found in sprd composite clocks, so
provides two helpers that can be reused later on.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/sprd/Makefile | 1 +
drivers/clk/sprd/mux.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/sprd/mux.h | 76 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 155 insertions(+)
create mode 100644 drivers/clk/sprd/mux.c
create mode 100644 drivers/clk/sprd/mux.h
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 8cd5592..cee36b5 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o
clk-sprd-y += common.o
clk-sprd-y += gate.o
+clk-sprd-y += mux.o
diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c
new file mode 100644
index 0000000..05ef9f0
--- /dev/null
+++ b/drivers/clk/sprd/mux.c
@@ -0,0 +1,78 @@
+/*
+ * Spreadtrum multiplexer clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+#include "mux.h"
+
+u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common,
+ const struct sprd_mux_ssel *mux)
+{
+ unsigned int reg;
+ u8 parent;
+ int num_parents;
+ int i;
+
+ sprd_regmap_read(common->regmap, common->reg, ®);
+ parent = reg >> mux->shift;
+ parent &= (1 << mux->width) - 1;
+
+ if (!mux->table)
+ return parent;
+
+ num_parents = clk_hw_get_num_parents(&common->hw);
+
+ for (i = 0; i < num_parents - 1; i++)
+ if (parent >= mux->table[i] && parent < mux->table[i + 1])
+ return i;
+
+ return num_parents - 1;
+}
+EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent);
+
+static u8 sprd_mux_get_parent(struct clk_hw *hw)
+{
+ struct sprd_mux *cm = hw_to_sprd_mux(hw);
+
+ return sprd_mux_helper_get_parent(&cm->common, &cm->mux);
+}
+
+int sprd_mux_helper_set_parent(const struct sprd_clk_common *common,
+ const struct sprd_mux_ssel *mux,
+ u8 index)
+{
+ unsigned int reg;
+
+ if (mux->table)
+ index = mux->table[index];
+
+ sprd_regmap_read(common->regmap, common->reg, ®);
+ reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift);
+ sprd_regmap_write(common->regmap, common->reg,
+ reg | (index << mux->shift));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent);
+
+static int sprd_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct sprd_mux *cm = hw_to_sprd_mux(hw);
+
+ return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index);
+}
+
+const struct clk_ops sprd_mux_ops = {
+ .get_parent = sprd_mux_get_parent,
+ .set_parent = sprd_mux_set_parent,
+ .determine_rate = __clk_mux_determine_rate,
+};
+EXPORT_SYMBOL_GPL(sprd_mux_ops);
diff --git a/drivers/clk/sprd/mux.h b/drivers/clk/sprd/mux.h
new file mode 100644
index 0000000..683d63a
--- /dev/null
+++ b/drivers/clk/sprd/mux.h
@@ -0,0 +1,76 @@
+/*
+ * Spreadtrum multiplexer clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _SPRD_MUX_H_
+#define _SPRD_MUX_H_
+
+#include "common.h"
+
+/**
+ * struct sprd_mux_ssel - Mux clock's source select bits in its register
+ * @shift: Bit offset of the divider in its register
+ * @width: Width of the divider field in its register
+ * @table: For some mux clocks, not all sources are used on some special
+ * chips, this matches the value of mux clock's register and the
+ * sources which are used for this mux clock
+ */
+struct sprd_mux_ssel {
+ u8 shift;
+ u8 width;
+ const u8 *table;
+};
+
+struct sprd_mux {
+ struct sprd_mux_ssel mux;
+ struct sprd_clk_common common;
+};
+
+#define _SPRD_MUX_CLK(_shift, _width, _table) \
+ { \
+ .shift = _shift, \
+ .width = _width, \
+ .table = _table, \
+ }
+
+#define SPRD_MUX_CLK_TABLE(_struct, _name, _parents, _table, \
+ _reg, _shift, _width, \
+ _flags) \
+ struct sprd_mux _struct = { \
+ .mux = _SPRD_MUX_CLK(_shift, _width, _table), \
+ .common = { \
+ .regmap = NULL, \
+ .reg = _reg, \
+ .hw.init = CLK_HW_INIT_PARENTS(_name, \
+ _parents, \
+ &sprd_mux_ops, \
+ _flags), \
+ } \
+ }
+
+#define SPRD_MUX_CLK(_struct, _name, _parents, _reg, \
+ _shift, _width, _flags) \
+ SPRD_MUX_CLK_TABLE(_struct, _name, _parents, NULL, \
+ _reg, _shift, _width, _flags)
+
+static inline struct sprd_mux *hw_to_sprd_mux(const struct clk_hw *hw)
+{
+ struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+ return container_of(common, struct sprd_mux, common);
+}
+
+extern const struct clk_ops sprd_mux_ops;
+
+u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common,
+ const struct sprd_mux_ssel *mux);
+int sprd_mux_helper_set_parent(const struct sprd_clk_common *common,
+ const struct sprd_mux_ssel *mux,
+ u8 index);
+
+#endif /* _SPRD_MUX_H_ */
--
2.7.4
^ permalink raw reply related
* [PATCH V6 05/12] clk: sprd: add divider clock support
From: Chunyan Zhang @ 2017-11-27 10:01 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171127100115.20655-1-chunyan.zhang@spreadtrum.com>
This is a feature that can also be found in sprd composite clocks,
provide a bunch of helpers that can be reused later on.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/sprd/Makefile | 1 +
drivers/clk/sprd/div.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/sprd/div.h | 77 +++++++++++++++++++++++++++++++++++++++
3 files changed, 170 insertions(+)
create mode 100644 drivers/clk/sprd/div.c
create mode 100644 drivers/clk/sprd/div.h
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index cee36b5..80e6039 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK) += clk-sprd.o
clk-sprd-y += common.o
clk-sprd-y += gate.o
clk-sprd-y += mux.o
+clk-sprd-y += div.o
diff --git a/drivers/clk/sprd/div.c b/drivers/clk/sprd/div.c
new file mode 100644
index 0000000..8c7196f
--- /dev/null
+++ b/drivers/clk/sprd/div.c
@@ -0,0 +1,92 @@
+/*
+ * Spreadtrum divider clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+
+#include "div.h"
+
+long sprd_div_helper_round_rate(struct sprd_clk_common *common,
+ const struct sprd_div_internal *div,
+ unsigned long rate,
+ unsigned long *parent_rate)
+{
+ return divider_round_rate(&common->hw, rate, parent_rate,
+ NULL, div->width, 0);
+}
+EXPORT_SYMBOL_GPL(sprd_div_helper_round_rate);
+
+static long sprd_div_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct sprd_div *cd = hw_to_sprd_div(hw);
+
+ return sprd_div_helper_round_rate(&cd->common, &cd->div,
+ rate, parent_rate);
+}
+
+unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
+ const struct sprd_div_internal *div,
+ unsigned long parent_rate)
+{
+ unsigned long val;
+ unsigned int reg;
+
+ sprd_regmap_read(common->regmap, common->reg, ®);
+ val = reg >> div->shift;
+ val &= (1 << div->width) - 1;
+
+ return divider_recalc_rate(&common->hw, parent_rate, val, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(sprd_div_helper_recalc_rate);
+
+static unsigned long sprd_div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct sprd_div *cd = hw_to_sprd_div(hw);
+
+ return sprd_div_helper_recalc_rate(&cd->common, &cd->div, parent_rate);
+}
+
+int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
+ const struct sprd_div_internal *div,
+ unsigned long rate,
+ unsigned long parent_rate)
+{
+ unsigned long val;
+ unsigned int reg;
+
+ val = divider_get_val(rate, parent_rate, NULL,
+ div->width, 0);
+
+ sprd_regmap_read(common->regmap, common->reg, ®);
+ reg &= ~GENMASK(div->width + div->shift - 1, div->shift);
+
+ sprd_regmap_write(common->regmap, common->reg,
+ reg | (val << div->shift));
+
+ return 0;
+
+}
+EXPORT_SYMBOL_GPL(sprd_div_helper_set_rate);
+
+static int sprd_div_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct sprd_div *cd = hw_to_sprd_div(hw);
+
+ return sprd_div_helper_set_rate(&cd->common, &cd->div,
+ rate, parent_rate);
+}
+
+const struct clk_ops sprd_div_ops = {
+ .recalc_rate = sprd_div_recalc_rate,
+ .round_rate = sprd_div_round_rate,
+ .set_rate = sprd_div_set_rate,
+};
+EXPORT_SYMBOL_GPL(sprd_div_ops);
diff --git a/drivers/clk/sprd/div.h b/drivers/clk/sprd/div.h
new file mode 100644
index 0000000..fb59fe5
--- /dev/null
+++ b/drivers/clk/sprd/div.h
@@ -0,0 +1,77 @@
+/*
+ * Spreadtrum divider clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _SPRD_DIV_H_
+#define _SPRD_DIV_H_
+
+#include "common.h"
+
+/**
+ * struct sprd_div_internal - Internal divider description
+ * @shift: Bit offset of the divider in its register
+ * @width: Width of the divider field in its register
+ *
+ * That structure represents a single divider, and is meant to be
+ * embedded in other structures representing the various clock
+ * classes.
+ */
+struct sprd_div_internal {
+ u8 shift;
+ u8 width;
+};
+
+#define _SPRD_DIV_CLK(_shift, _width) \
+ { \
+ .shift = _shift, \
+ .width = _width, \
+ }
+
+struct sprd_div {
+ struct sprd_div_internal div;
+ struct sprd_clk_common common;
+};
+
+#define SPRD_DIV_CLK(_struct, _name, _parent, _reg, \
+ _shift, _width, _flags) \
+ struct sprd_div _struct = { \
+ .div = _SPRD_DIV_CLK(_shift, _width), \
+ .common = { \
+ .regmap = NULL, \
+ .reg = _reg, \
+ .hw.init = CLK_HW_INIT(_name, \
+ _parent, \
+ &sprd_div_ops, \
+ _flags), \
+ } \
+ }
+
+static inline struct sprd_div *hw_to_sprd_div(const struct clk_hw *hw)
+{
+ struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+ return container_of(common, struct sprd_div, common);
+}
+
+long sprd_div_helper_round_rate(struct sprd_clk_common *common,
+ const struct sprd_div_internal *div,
+ unsigned long rate,
+ unsigned long *parent_rate);
+
+unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
+ const struct sprd_div_internal *div,
+ unsigned long parent_rate);
+
+int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
+ const struct sprd_div_internal *div,
+ unsigned long rate,
+ unsigned long parent_rate);
+
+extern const struct clk_ops sprd_div_ops;
+
+#endif /* _SPRD_DIV_H_ */
--
2.7.4
^ permalink raw reply related
* [PATCH V6 06/12] clk: sprd: add composite clock support
From: Chunyan Zhang @ 2017-11-27 10:01 UTC (permalink / raw)
To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171127100115.20655-1-chunyan.zhang@spreadtrum.com>
This patch introduced composite driver for Spreadtrum's SoCs. The
functions of this composite clock simply consist of divider and
mux clocks.
Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
drivers/clk/sprd/Makefile | 1 +
drivers/clk/sprd/composite.c | 62 ++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/sprd/composite.h | 53 +++++++++++++++++++++++++++++++++++++
3 files changed, 116 insertions(+)
create mode 100644 drivers/clk/sprd/composite.c
create mode 100644 drivers/clk/sprd/composite.h
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 80e6039..2262e76 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -4,3 +4,4 @@ clk-sprd-y += common.o
clk-sprd-y += gate.o
clk-sprd-y += mux.o
clk-sprd-y += div.o
+clk-sprd-y += composite.o
diff --git a/drivers/clk/sprd/composite.c b/drivers/clk/sprd/composite.c
new file mode 100644
index 0000000..218e17c
--- /dev/null
+++ b/drivers/clk/sprd/composite.c
@@ -0,0 +1,62 @@
+/*
+ * Spreadtrum composite clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <linux/clk-provider.h>
+
+#include "composite.h"
+
+static long sprd_comp_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+ return sprd_div_helper_round_rate(&cc->common, &cc->div,
+ rate, parent_rate);
+}
+
+static unsigned long sprd_comp_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+ return sprd_div_helper_recalc_rate(&cc->common, &cc->div, parent_rate);
+}
+
+static int sprd_comp_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+ return sprd_div_helper_set_rate(&cc->common, &cc->div,
+ rate, parent_rate);
+}
+
+static u8 sprd_comp_get_parent(struct clk_hw *hw)
+{
+ struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+ return sprd_mux_helper_get_parent(&cc->common, &cc->mux);
+}
+
+static int sprd_comp_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+ return sprd_mux_helper_set_parent(&cc->common, &cc->mux, index);
+}
+
+const struct clk_ops sprd_comp_ops = {
+ .get_parent = sprd_comp_get_parent,
+ .set_parent = sprd_comp_set_parent,
+
+ .round_rate = sprd_comp_round_rate,
+ .recalc_rate = sprd_comp_recalc_rate,
+ .set_rate = sprd_comp_set_rate,
+};
+EXPORT_SYMBOL_GPL(sprd_comp_ops);
diff --git a/drivers/clk/sprd/composite.h b/drivers/clk/sprd/composite.h
new file mode 100644
index 0000000..b337bda
--- /dev/null
+++ b/drivers/clk/sprd/composite.h
@@ -0,0 +1,53 @@
+/*
+ * Spreadtrum composite clock driver
+ *
+ * Copyright (C) 2017 Spreadtrum, Inc.
+ * Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _SPRD_COMPOSITE_H_
+#define _SPRD_COMPOSITE_H_
+
+#include "common.h"
+#include "mux.h"
+#include "div.h"
+
+struct sprd_comp {
+ struct sprd_mux_ssel mux;
+ struct sprd_div_internal div;
+ struct sprd_clk_common common;
+};
+
+#define SPRD_COMP_CLK_TABLE(_struct, _name, _parent, _reg, _table, \
+ _mshift, _mwidth, _dshift, _dwidth, _flags) \
+ struct sprd_comp _struct = { \
+ .mux = _SPRD_MUX_CLK(_mshift, _mwidth, _table), \
+ .div = _SPRD_DIV_CLK(_dshift, _dwidth), \
+ .common = { \
+ .regmap = NULL, \
+ .reg = _reg, \
+ .hw.init = CLK_HW_INIT_PARENTS(_name, \
+ _parent, \
+ &sprd_comp_ops, \
+ _flags), \
+ } \
+ }
+
+#define SPRD_COMP_CLK(_struct, _name, _parent, _reg, _mshift, \
+ _mwidth, _dshift, _dwidth, _flags) \
+ SPRD_COMP_CLK_TABLE(_struct, _name, _parent, _reg, \
+ NULL, _mshift, _mwidth, \
+ _dshift, _dwidth, _flags)
+
+static inline struct sprd_comp *hw_to_sprd_comp(const struct clk_hw *hw)
+{
+ struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+ return container_of(common, struct sprd_comp, common);
+}
+
+extern const struct clk_ops sprd_comp_ops;
+
+#endif /* _SPRD_COMPOSITE_H_ */
--
2.7.4
^ permalink raw reply related
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