* [BUG] FL1009: xHCI host not responding to stop endpoint command.
From: Arnaud Ebalard @ 2014-01-18 21:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140117205432.GB5618@xanatos>
Hi,
I have added Thomas in the recipients, because I guess he may be of some
help debugging the issue further. Thomas, the beginning of the thread is
here: http://thread.gmane.org/gmane.linux.usb.general/101531
Sarah Sharp <sarah.a.sharp@linux.intel.com> writes:
>> >>> I am slowly starting to see a bisect session coming ;-)
>> >>
>> >> Try reverting commit 60e102ac73cd40069d077014c93c86dc7205cb68.
>> >
>> > AFAICT, this commit does not exist in master (Linus tree), i.e. it is
>> > not in 3.13.0-rc8.
>>
>> That commit is a stable backport of 9df89d85b407690afa46ddfbccc80bec6869971d
>> which is in v3.13-rc8:
>>
>> bjorn at nemi:/usr/local/src/git/linux$ git tag --contains 9df89d85b407690afa46ddfbccc80bec6869971d
>> usb-3.13-rc1
>> usb-3.13-rc3
>> usb-3.13-rc5
>> v3.13-rc1
>> v3.13-rc2
>> v3.13-rc3
>> v3.13-rc4
>> v3.13-rc5
>> v3.13-rc6
>> v3.13-rc7
>> v3.13-rc8
>
> Sorry for using the stable commit ID. Arnaud, please try reverting
> commit 9df89d85b407690afa46ddfbccc80bec6869971d "usbcore: set
> lpm_capable field for LPM capable root hubs" and see if it fixes your
> issues.
Nope, 9df89d85b407690 does not fix the issue but I guess I found the
reason: I think the regression is not directly due to some usb/XHCI
related change. More below.
I started a git bisect session but I had to stop between the two
following commits, because the last ones I tested after those were just
not bootable.
bad : f9efbce6334844c7f8b9b9459f6d7a6fbc2928e0 (merge commit)
good: aac59e3efce3dca787b11e34726001603ce3d161 (merge commit)
At that point, I decided to switch to a manual review of the changes
introduced *between* those commits:
$ git log -p aac59e3efce3..f9efbce63348 | grep -c ^commit
524
I looked at which files where touched (387 in total) and dropped those
that are not use on my platform or cannot be suspected fo the bug. I
ended up w/:
drivers/irqchip/irq-armada-370-xp.c
drivers/pci/host/pci-mvebu.c
Which are modified by those commits:
commit f5072dfbac05: PCI: mvebu: make local functions static
commit 032b4c0cc321: PCI: mvebu: add I/O access wrappers
commit 9f352f0e6c0f: PCI: mvebu: Dynamically detect if the PEX link is up to enable hot plug
commit cc54ccd9a696: PCI: mvebu: add support for Marvell Dove SoCs
commit 52ba992e201f: PCI: mvebu: add support for reset on GPIO
commit e5615c30c1c9: PCI: mvebu: remove subsys_initcall
commit bf09b6ae588f: PCI: mvebu: increment nports only for registered ports
commit b42285f66f87: PCI: mvebu: move clock enable before register access
commit 5b4deb6526bd: PCI: mvebu: add support for MSI
commit 31f614edb726: irqchip: armada-370-xp: implement MSI support
commit 627dfcc249e2: irqchip: armada-370-xp: properly request resources
I started suspecting the introduction of MSI support in Marvell PCIe
host controller driver (FL1009 is on the PCIe bus) and compiled a
a 3.13.0-rc8 w/ CONFIG_PCI_MSI disabled (it was enabled in all my
previous tests): I did not manage to reproduce the issue with this
kernel. As a side note, commits 5b4deb6526bd, 31f614edb726 and
627dfcc249e2 are
ATM, I do not know if the problem is related to a bug in introduced MSI
support or some weird incompatibility of that functionality with the
FL1009 which would require some quirk in XHCI stack.
Thomas, I took a look at the changes but I am not familiar w/ how MSI
work. You may have an idea on what is going on here.
Cheers,
a+
ps: Thomas, this is completely unrelated but the code below caught my
eye at the beginning of a hunk in 31f614edb726. When CONFIG_PCI_MSI is
disabled, why is irqnr now compared to 1 instead of 0?
@@ -214,12 +365,39 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
if (irqnr > 1022)
break;
- if (irqnr > 0) {
+ if (irqnr > 1) {
irqnr = irq_find_mapping(armada_370_xp_mpic_domain,
irqnr);
handle_IRQ(irqnr, regs);
continue;
}
+
+#ifdef CONFIG_PCI_MSI
+ /* MSI handling */
+ if (irqnr == 1) {
The comparisonWhen CONFIG_PCI_MSI
^ permalink raw reply
* imx6 eSATA
From: Russell King - ARM Linux @ 2014-01-18 21:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140118190337.GK15937@n2100.arm.linux.org.uk>
On Sat, Jan 18, 2014 at 07:03:37PM +0000, Russell King - ARM Linux wrote:
> On Sat, Jan 18, 2014 at 06:44:27PM +0000, Russell King - ARM Linux wrote:
> > So, I see we have AHCI support for SATA on the iMX6. Great... but it
> > doesn't work on the cubox-i, because the phy settings are wrong.
>
> And another thing. This is wonderful... really wonderful.
>
> static int imx_ahci_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> ...
> ahci_pdev = platform_device_alloc("ahci", -1);
> ...
> ahci_dev = &ahci_pdev->dev;
> ...
> ahci_dev->of_node = dev->of_node;
>
> This is a hanging offence.
>
> Here's a lesson in how DT matching works:
>
> - A device gets declared into the device model.
> - The device is offered to each driver in turn via the bus specific
> code to see whether the driver should be bound to the device.
> - If there's an of_node present, the DT IDs for the driver are walked
> to compare the device with the driver's DT IDs. If a match is found,
> the device is passed to the driver probe function.
> - If there is no of_node present, and it's a platform device, the bare
> device name is compared the driver name(s) and if it matches the
> probe function is called.
>
> Now, what does this mean for the above monstrosity? If the driver
> model happens to find the ahci_imx driver _before_ the ahci driver
> while trying to bind the ahci_dev, it will find that the ahci_dev
> has an of_node with a compatible string which matches this driver.
> So, imx_ahci_probe() _can_ be called with the ahci_pdev that it
> just created.
>
> It doesn't take much to understand what the result will be of that.
> It will try to create another ahci device... hopefully this time
> erroring out.
>
> This is utterly disgusting. You must *never* *ever* assign an of_node
> from one device to another of the same bus type. If you need to pass
> the of_node to another device, then it _must_ be done outside of the
> child device's of_node pointer - in other words, it must be done using
> platform data.
>
> Alternatively, turn ahci into a library that both the original ahci
> and ahci_imx drivers can use without jumping through these kinds of
> games - or in this case, just get rid of that assignment - I can't
> see anything in ahci.c which needs the of_node.
Sigh. You can't get rid of the of_node there because it's needed
for clk_get() inside ahci_platform.c. So, I think ahci_platform needs
to become yet another library, and thereby avoid creating a child
platform device.
--
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up. Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".
^ permalink raw reply
* [PATCH 02/11] iommu/arm-smmu: Introduce bus notifier block
From: Varun Sethi @ 2014-01-18 20:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389876263-25759-3-git-send-email-andreas.herrmann@calxeda.com>
> -----Original Message-----
> From: iommu-bounces at lists.linux-foundation.org [mailto:iommu-
> bounces at lists.linux-foundation.org] On Behalf Of Andreas Herrmann
> Sent: Thursday, January 16, 2014 6:14 PM
> To: Will Deacon
> Cc: Andreas Herrmann; iommu at lists.linux-foundation.org; linux-arm-
> kernel at lists.infradead.org
> Subject: [PATCH 02/11] iommu/arm-smmu: Introduce bus notifier block
>
> At the moment just handle BUS_NOTIFY_BIND_DRIVER to conditionally isolate
> all master devices for an SMMU.
>
> Depending on DT information each device is put into its own protection
> domain (if possible). For configuration with one or just a few masters
> per SMMU that is easy to achieve.
>
> In case of many devices per SMMU (e.g. MMU-500 with it's distributed
> translation support) isolation of each device might not be possible --
> depending on number of available SMR groups and/or context banks.
>
> Default is that device isolation is contolled per SMMU with SMMU node
> property "arm,smmu-isolate-devices" in a DT. If this property is set for
> an SMMU node, device isolation is performed.
[Sethi Varun-B16395] What if the devices have to be assigned to different virtual machines? Would the absence of this property indicate that devices can't
Be assigned to different virtual machines i.e. devices would be in the same iommu group?
>
> W/o device isolation the driver detects SMMUs but no translation is
> configured (transactions just bypass translation process).
>
[Sethi Varun-B16395] Would SMR and S2CR still be allocated?
> Note that for device isolation dma_base and size are fixed as 0 and
> SZ_128M at the moment. Additional patches will address this restriction
> and allow automatic growth of mapping size.
>
> Cc: Andreas Herrmann <herrmann.der.user@googlemail.com>
> Signed-off-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
> ---
> drivers/iommu/arm-smmu.c | 45
> +++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 45 insertions(+)
>
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index
> 0b97d03..bc81dd0 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -46,6 +46,7 @@
> #include <linux/amba/bus.h>
>
> #include <asm/pgalloc.h>
> +#include <asm/dma-iommu.h>
>
> /* Driver options */
> #define ARM_SMMU_OPT_ISOLATE_DEVICES (1 << 0)
> @@ -1964,6 +1965,48 @@ static int arm_smmu_device_remove(struct
> platform_device *pdev)
> return 0;
> }
>
> +static int arm_smmu_device_notifier(struct notifier_block *nb,
> + unsigned long action, void *data)
> +{
> + struct device *dev = data;
> + struct dma_iommu_mapping *mapping;
> + struct arm_smmu_device *smmu;
> + int ret;
> +
> + switch (action) {
> + case BUS_NOTIFY_BIND_DRIVER:
> +
> + arm_smmu_add_device(dev);
[Sethi Varun-B16395] This would have already happened by virtue of the add_device iommu_ops.
> + smmu = dev->archdata.iommu;
> + if (!smmu || !(smmu->options & ARM_SMMU_OPT_ISOLATE_DEVICES))
> + break;
> +
> + mapping = arm_iommu_create_mapping(&platform_bus_type,
> + 0, SZ_128M, 0);
> + if (IS_ERR(mapping)) {
> + ret = PTR_ERR(mapping);
> + dev_info(dev, "arm_iommu_create_mapping failed\n");
> + break;
> + }
> +
> + ret = arm_iommu_attach_device(dev, mapping);
> + if (ret < 0) {
> + dev_info(dev, "arm_iommu_attach_device failed\n");
> + arm_iommu_release_mapping(mapping);
> + }
> +
> + break;
> + default:
> + break;
> + }
> +
> + return 0;
> +}
> +
> +static struct notifier_block device_nb = {
> + .notifier_call = arm_smmu_device_notifier, };
> +
> #ifdef CONFIG_OF
> static struct of_device_id arm_smmu_of_match[] = {
> { .compatible = "arm,smmu-v1", },
> @@ -2000,6 +2043,8 @@ static int __init arm_smmu_init(void)
> if (!iommu_present(&amba_bustype))
> bus_set_iommu(&amba_bustype, &arm_smmu_ops);
>
> + bus_register_notifier(&platform_bus_type, &device_nb);
> +
[Sethi Varun-B16395] Notifier was already registered for the platform bus via bus_set_iommu. You can actually register a iommu group (once iommu group gets created) notifier (iommu_group_register_notifier) and listen for the IOMMU_GROUP_NOTIFY_BIND_DRIVER event.
-Varun
^ permalink raw reply
* imx6 eSATA
From: Russell King - ARM Linux @ 2014-01-18 19:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140118184427.GJ15937@n2100.arm.linux.org.uk>
On Sat, Jan 18, 2014 at 06:44:27PM +0000, Russell King - ARM Linux wrote:
> So, I see we have AHCI support for SATA on the iMX6. Great... but it
> doesn't work on the cubox-i, because the phy settings are wrong.
And another thing. This is wonderful... really wonderful.
static int imx_ahci_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
...
ahci_pdev = platform_device_alloc("ahci", -1);
...
ahci_dev = &ahci_pdev->dev;
...
ahci_dev->of_node = dev->of_node;
This is a hanging offence.
Here's a lesson in how DT matching works:
- A device gets declared into the device model.
- The device is offered to each driver in turn via the bus specific
code to see whether the driver should be bound to the device.
- If there's an of_node present, the DT IDs for the driver are walked
to compare the device with the driver's DT IDs. If a match is found,
the device is passed to the driver probe function.
- If there is no of_node present, and it's a platform device, the bare
device name is compared the driver name(s) and if it matches the
probe function is called.
Now, what does this mean for the above monstrosity? If the driver
model happens to find the ahci_imx driver _before_ the ahci driver
while trying to bind the ahci_dev, it will find that the ahci_dev
has an of_node with a compatible string which matches this driver.
So, imx_ahci_probe() _can_ be called with the ahci_pdev that it
just created.
It doesn't take much to understand what the result will be of that.
It will try to create another ahci device... hopefully this time
erroring out.
This is utterly disgusting. You must *never* *ever* assign an of_node
from one device to another of the same bus type. If you need to pass
the of_node to another device, then it _must_ be done outside of the
child device's of_node pointer - in other words, it must be done using
platform data.
Alternatively, turn ahci into a library that both the original ahci
and ahci_imx drivers can use without jumping through these kinds of
games - or in this case, just get rid of that assignment - I can't
see anything in ahci.c which needs the of_node.
--
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up. Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".
^ permalink raw reply
* imx6 eSATA
From: Russell King - ARM Linux @ 2014-01-18 18:44 UTC (permalink / raw)
To: linux-arm-kernel
So, I see we have AHCI support for SATA on the iMX6. Great... but it
doesn't work on the cubox-i, because the phy settings are wrong.
The Cubox-i requires GPR13 set to 0x0593A044 - I haven't decoded what
this means yet, but it's different from the 0x0593E4A4 which is
currently hard-coded into the driver (and I've independently tested
that this is indeed required.)
So, there's presently no DT properties for this - given that these
parameters would be board specific, it surprises me that this has not
been thought about, and properties already generated, because now it
means that we need to _add_ new properties to this driver.
Also, this PDDQ mode thing, which can't be recovered except by reset.
This is another illustration why Linux is unfriendly - the thing can
silently go into this power down mode which is irrecoverable without
any messages being generated nor any hints how to avoid it - maybe
this should also be a DT property, not just a command line option.
More importantly, maybe we should print a message when we discover
that there's nothing connected and we're going to enter this mode -
maybe something like this:
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 3e23e9941dad..0a1ae7213992 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -77,6 +77,10 @@ static void ahci_imx_error_handler(struct ata_port *ap)
!IMX6Q_GPR13_SATA_MPLL_CLK_EN);
clk_disable_unprepare(imxpriv->sata_ref_clk);
imxpriv->no_device = true;
+
+ dev_info(ap->dev, "no device, link disabled until next reset.\n");
+ dev_info(ap->dev, "pass " MODULE_PARAM_PREFIX
+ ".hotplug=1 to enable link hotplug support\n");
}
static struct ata_port_operations ahci_imx_ops = {
--
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up. Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".
^ permalink raw reply related
* [PATCHv13 00/40] ARM: TI SoC clock DT conversion
From: Sebastian Reichel @ 2014-01-18 18:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52D9D6C6.2000700@ti.com>
On Fri, Jan 17, 2014 at 07:20:06PM -0600, Nishanth Menon wrote:
> On 01/17/2014 06:23 PM, Olof Johansson wrote:
> > On Fri, Jan 17, 2014 at 4:19 PM, Nishanth Menon <nm@ti.com> wrote:
> >> On 01/17/2014 06:12 PM, Olof Johansson wrote:
> >>> On Fri, Jan 17, 2014 at 4:02 PM, Nishanth Menon <nm@ti.com> wrote:
> >>>
> >>>> clk-next-6a0cad9 + next-20140117 multi_v7_defconfig + CONFIG_LPAE=y:
> >>>> 1: am335x-evm: Boot PASS: http://slexy.org/raw/s21GRhEOj4
> >>>> 2: am335x-sk: Boot PASS: http://slexy.org/raw/s20zcNsD8h
> >>>> 3: am3517-evm: Boot PASS: http://slexy.org/raw/s27U9IfRKR
> >>>> 4: am37x-evm: Boot PASS: http://slexy.org/raw/s2zYyeonec
> >>>> 5: am43xx-epos: Boot PASS: http://slexy.org/raw/s21iCRjTHK
> >>>> 6: beagleboard-xm: Boot PASS: http://slexy.org/raw/s20bPGL3Sz
> >>>> 7: beaglebone-black: Boot PASS: http://slexy.org/raw/s21AhFmkCk
> >>>> 8: crane: No Image built - Missing platform support?:
> >>>> 9: dra7: Boot FAIL: http://slexy.org/raw/s21Qh3sQRu
> >>>> * DRA7 not enabled?
> >>>> 10: ldp: Boot PASS: http://slexy.org/raw/s21fvBfBgs
> >>>> 11: panda-es: Boot FAIL: http://slexy.org/raw/s20RsgVUZJ
> >>>> * known issue (https://patchwork.kernel.org/patch/3084521/)
> >>>> 12: sdp2430: Boot FAIL: v6 platform - wont boot with multi_v7
> >>>> 13: sdp3430: Boot PASS: http://slexy.org/raw/s20rhjjBwe
> >>>> 14: sdp4430: Boot PASS: http://slexy.org/raw/s2My0UfNPm
> >>>> 15: uevm: Boot PASS: http://slexy.org/raw/s21aqF6eMN
> >>>> TOTAL = 15 boards, Booted Boards = 11, No Boot boards = 4
> >>>
> >>>
> >>> I have a hard time believing the above; A8/A9 boards are not bootable
> >>> with CONFIG_LPAE=y...
> >>
> >> You are right! Drat!! I had CONFIG_LPAE=y in my script, not
> >> CONFIG_ARM_LPAE=y! Grrr...
> >>
> >> Retest in a around 30 mins..
> >
> > It's not a huge concern though; it's unlikely that LPAE makes a
> > functional difference on this patch series. It's still useful to catch
> > warnings, etc (most likely printk formats and the like).
> >
> I suppose, as expected:
> clk-next-6a0cad9 + next-20140117 multi_v7_defconfig + CONFIG_ARM_LPAE=y
> * .config = http://slexy.org/view/s208uSeQS8
> * Build warnings: http://slexy.org/raw/s20n7YwbwN
> 1: am335x-evm: Boot FAIL: http://slexy.org/raw/s20tF2eUZG
> 2: am335x-sk: Boot FAIL: http://slexy.org/raw/s2uP65lOMQ
> 3: am3517-evm: Boot FAIL: http://slexy.org/raw/s2Lx13gsFZ
> 4: am37x-evm: Boot FAIL: http://slexy.org/raw/s2eOLXxvsT
> 5: am43xx-epos: Boot FAIL: http://slexy.org/raw/s24coJzGvR
> 6: BeagleBoard-XM: Boot FAIL: http://slexy.org/raw/s240WznuPd
> 7: BeagleBone-Black: Boot FAIL: http://slexy.org/raw/s20NG2UVTU
> 8: crane: No Image built - Missing platform support?:
> 9: dra7: Boot FAIL: http://slexy.org/raw/s21T3RpHx2
> ^^ might probably boot if we enable CONFIG_SOC_DRA7XX in multi_v7
> (this is another A15 target)
> 10: ldp: Boot FAIL: http://slexy.org/raw/s2F4VO9hDM
> 11: PandaBoard-ES: Boot FAIL: http://slexy.org/raw/s20HpzT1jW
> 12: sdp2430: Boot FAIL: http://slexy.org/raw/s21snV1EvL
> 13: sdp3430: Boot FAIL: http://slexy.org/raw/s2FwkVfG5R
> 14: sdp4430: Boot FAIL: http://slexy.org/raw/s2xiWxlpTj
> 15: uevm: Boot PASS: http://slexy.org/raw/s2LWUOmfiG
> TOTAL = 15 boards, Booted Boards = 1, No Boot boards = 14
>
> I am running a defconfig set check on next-20140117 and will do one
> with next-20140118 once that is ready for comparison results
Just for reference: I tried booting Nokia N900 using mike's
clk-next-omap branch (HEAD = 3e04915):
n900: Boot PASS: http://paste.debian.net/77085/
-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140118/d024c5da/attachment.sig>
^ permalink raw reply
* [PATCHv13 00/40] ARM: TI SoC clock DT conversion
From: Tony Lindgren @ 2014-01-18 18:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140117205832.4167.95162@quantum>
* Mike Turquette <mturquette@linaro.org> [140117 13:00]:
> Quoting Tero Kristo (2014-01-17 10:11:06)
> > On 01/17/2014 07:53 PM, Tony Lindgren wrote:
> > > * Kevin Hilman <khilman@linaro.org> [140117 09:48]:
> > >> Mike Turquette <mturquette@linaro.org> writes:
> > >>
> > >> [...]
> > >>
> > >>> I took Tony's advice and fast-forwarded clk-next to -rc7 and applied
> > >>> Tero's series. This includes the AM3517 bits now. I've pushed this
> > >>> branch to clk-next-omap (force update) on my Linaro mirror. Can you do a
> > >>> final sanity test before I merge this into clk-next?
> >
> > I think you accidentally merged wrong branch to clk-next-omap with the
> > latest refresh. This is one is missing the build-fixes now, when it
> > earlier had those in.
> >
> > The correct branch to merge was 3.13-rc7-dt-clks-v13-build-fixes.
> >
> > This also causes the build failure below for omap1.
>
> You are right. I broke the OMAPs. I force updated clk-next-omap (and
> clk-next) with the correct branch this time.
OK works for me now, thanks.
Tony
^ permalink raw reply
* [PATCH 0/3] ARM: OMAP: clk-next-omap emergency fixes
From: Tony Lindgren @ 2014-01-18 17:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140117213729.4167.55693@quantum>
* Mike Turquette <mturquette@linaro.org> [140117 13:39]:
> Quoting Tero Kristo (2014-01-17 12:25:37)
> > Hi,
> >
> > Quick emergency band-aid for the build breakages introduced in clk-next
> > by Mike. I didn't have time to test this out (Nishanth will provide some
> > logs) and I will leave the decision whether/how to use these patches or not
> > to Tony + Mike.
> >
> > I also pushed a test branch based on top of clk-next here:
> > tree: https://github.com/t-kristo/linux-pm.git
> > branch: clk-next-omap-fixes
>
> Thanks Tero. I force updated the clk tree with the right branch, so
> these should not be necessary now.
Great, and just for reference if I did not do it yet for these:
Acked-by: Tony Lindgren <tony@atomide.com>
^ permalink raw reply
* [PATCH v7 0/2] ohci and ehci-platform clks, phy and dt support
From: Hans de Goede @ 2014-01-18 16:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <Pine.LNX.4.44L0.1401171053180.1162-100000@iolanthe.rowland.org>
Hi,
On 01/17/2014 06:12 PM, Alan Stern wrote:
> On Thu, 16 Jan 2014, Florian Fainelli wrote:
>
>> Le mercredi 15 janvier 2014, 15:26:21 Alan Stern a ?crit :
>>> On Wed, 15 Jan 2014, Hans de Goede wrote:
>>>> Hi All,
>>>>
>>>> This version of my ohci and ehci-platform clks, phy and dt support
>>>> patch-set, really fixes the 2 small bugs Alan found.
>>>
>>> All okay -- this time I can't find anything to complain about. :-)
>>
>> There is one minor issue; which is that the ehci binding claims the driver
>> supports the following optional boolean properties:
>>
>> - big-endian-regs : boolean, set this for hcds with big-endian registers
>> - big-endian-desc : boolean, set this for hcds with big-endian descriptors
>> - big-endian : boolean, for hcds with big-endian-regs + big-endian-desc
>>
>> while it does not (yet) so this is misleading. Can we at get that fixed before
>> merging? Copy pasting the PPC ehci driver should do the job.
>
> I agree it needs to be fixed. This can be done in a follow-up patch,
> though. It doesn't have to be in this one because nobody is using
> ehci-platform with DT yet.
>
> A simple copy from the PPC driver isn't quite enough, because the
> platform data settings would override the DT values.
> ehci_platform_reset has to be changed so that it sets
> ehci->big_endian_desc and _mmio if the pdata flags are set, but
> otherwise leaves them alone.
>
> Hans, would you like to write another patch to take care of this?
I already took a quick look at this, setting the ehci->big_endian* flags is easy,
the problem is that they won't work unless we also define
CONFIG_USB_EHCI_BIG_ENDIAN_DESC and CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
I would like to avoid doing something like the ugliness we've with
USB_OHCI_HCD_PPC_OF_BE and USB_OHCI_HCD_PPC_OF_LE, which means just selecting these
2 config options whenever USB_EHCI_HCD_PLATFORM is enabled, but I'm not sure if that
is acceptable.
The same goes for the ohci code btw.
Regards,
Hans
^ permalink raw reply
* [PATCH v4] of: add functions to count number of elements in a property
From: Heiko Stübner @ 2014-01-18 15:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAL_JsqJord1OOjwcKk1jqF5o+XO3uw+Lc4ATtQacgwZWAoQq1g@mail.gmail.com>
Am Samstag, 18. Januar 2014, 09:07:30 schrieb Rob Herring:
> On Sat, Jan 18, 2014 at 6:02 AM, Heiko St?bner <heiko@sntech.de> wrote:
> > The need to know the number of array elements in a property is
> > a common pattern. To prevent duplication of open-coded implementations
> > add a helper static function that also centralises strict sanity
> > checking and DTB format details, as well as a set of wrapper functions
> > for u8, u16, u32 and u64.
> >
> > Suggested-by: Mark Rutland <mark.rutland@arm.com>
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > ---
>
> Looks good. Do you plan to convert some users to use this?
My plan at the moment was to "just" use it for my mmio-sram-reserve stuff -
just wanted to make sure that this change is sane, before having to sent the
whole thing for each iteration.
I haven't yet looked where the other users, that Mark mentioned, are at :-)
Heiko
> > changes since v3:
> > address more comments from Rob Herring
> > - export the base function and inline the type-specific wrappers
> > changes since v2:
> > address more comments from Mark Rutland
> > - switch to of_property_count_elems_of_size
> > - use full_name instead of name in error message
> > changes since v1:
> > address comments from Rob Herring and Mark Rutland:
> > - provide a helper and a set of wrappers for u8-u64
> > - get rid of extra len variable, prop->length is enough
> > - include node name in error message
> >
> > Mark, does your Reviewed-by holds for this variant too?
> >
> > drivers/of/base.c | 32 ++++++++++++++++++++++
> > include/linux/of.h | 76
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed,
> > 108 insertions(+)
> >
> > diff --git a/drivers/of/base.c b/drivers/of/base.c
> > index f807d0e..21646c0 100644
> > --- a/drivers/of/base.c
> > +++ b/drivers/of/base.c
> > @@ -862,6 +862,38 @@ struct device_node *of_find_node_by_phandle(phandle
> > handle)>
> > EXPORT_SYMBOL(of_find_node_by_phandle);
> >
> > /**
> >
> > + * of_property_count_elems_of_size - Count the number of elements in a
> > property + *
> > + * @np: device node from which the property value is to be
> > read. + * @propname: name of the property to be searched.
> > + * @elem_size: size of the individual element
> > + *
> > + * Search for a property in a device node and count the number of
> > elements of + * size elem_size in it. Returns number of elements on
> > sucess, -EINVAL if the + * property does not exist or its length does not
> > match a multiple of u16 and + * -ENODATA if the property does not have a
> > value.
> > + */
> > +int of_property_count_elems_of_size(const struct device_node *np,
> > + const char *propname, int elem_size)
> > +{
> > + struct property *prop = of_find_property(np, propname, NULL);
> > +
> > + if (!prop)
> > + return -EINVAL;
> > + if (!prop->value)
> > + return -ENODATA;
> > +
> > + if (prop->length % elem_size != 0) {
> > + pr_err("size of %s in node %s is not a multiple of %d\n",
> > + propname, np->full_name, elem_size);
> > + return -EINVAL;
> > + }
> > +
> > + return prop->length / elem_size;
> > +}
> > +EXPORT_SYMBOL_GPL(of_property_count_elems_of_size);
> > +
> > +/**
> >
> > * of_find_property_value_of_size
> > *
> > * @np: device node from which the property value is to be
> > read.>
> > diff --git a/include/linux/of.h b/include/linux/of.h
> > index 276c546..293920d 100644
> > --- a/include/linux/of.h
> > +++ b/include/linux/of.h
> > @@ -250,6 +250,8 @@ extern struct device_node *of_find_node_with_property(
> >
> > extern struct property *of_find_property(const struct device_node *np,
> >
> > const char *name,
> > int *lenp);
> >
> > +extern int of_property_count_elems_of_size(const struct device_node *np,
> > + const char *propname, int elem_size);
> >
> > extern int of_property_read_u32_index(const struct device_node *np,
> >
> > const char *propname,
> > u32 index, u32 *out_value);
> >
> > @@ -426,6 +428,12 @@ static inline struct device_node
> > *of_find_compatible_node(>
> > return NULL;
> >
> > }
> >
> > +static inline int of_property_count_elems_of_size(const struct
> > device_node *np, + const char *propname, int
> > elem_size)
> > +{
> > + return -ENOSYS;
> > +}
> > +
> >
> > static inline int of_property_read_u32_index(const struct device_node
> > *np,
> >
> > const char *propname, u32 index, u32 *out_value)
> >
> > {
> >
> > @@ -565,6 +573,74 @@ static inline int of_node_to_nid(struct device_node
> > *device) { return 0; }>
> > #endif
> >
> > /**
> >
> > + * of_property_count_u8_elems - Count the number of u8 elements in a
> > property + *
> > + * @np: device node from which the property value is to be
> > read. + * @propname: name of the property to be searched.
> > + *
> > + * Search for a property in a device node and count the number of u8
> > elements + * in it. Returns number of elements on sucess, -EINVAL if the
> > property does + * not exist or its length does not match a multiple of u8
> > and -ENODATA if the + * property does not have a value.
> > + */
> > +static inline int of_property_count_u8_elems(const struct device_node
> > *np,
> > + const char *propname)
> > +{
> > + return of_property_count_elems_of_size(np, propname, sizeof(u8));
> > +}
> > +
> > +/**
> > + * of_property_count_u16_elems - Count the number of u16 elements in a
> > property + *
> > + * @np: device node from which the property value is to be
> > read. + * @propname: name of the property to be searched.
> > + *
> > + * Search for a property in a device node and count the number of u16
> > elements + * in it. Returns number of elements on sucess, -EINVAL if the
> > property does + * not exist or its length does not match a multiple of
> > u16 and -ENODATA if the + * property does not have a value.
> > + */
> > +static inline int of_property_count_u16_elems(const struct device_node
> > *np, + const char *propname)
> > +{
> > + return of_property_count_elems_of_size(np, propname, sizeof(u16));
> > +}
> > +
> > +/**
> > + * of_property_count_u32_elems - Count the number of u32 elements in a
> > property + *
> > + * @np: device node from which the property value is to be
> > read. + * @propname: name of the property to be searched.
> > + *
> > + * Search for a property in a device node and count the number of u32
> > elements + * in it. Returns number of elements on sucess, -EINVAL if the
> > property does + * not exist or its length does not match a multiple of
> > u32 and -ENODATA if the + * property does not have a value.
> > + */
> > +static inline int of_property_count_u32_elems(const struct device_node
> > *np, + const char *propname)
> > +{
> > + return of_property_count_elems_of_size(np, propname, sizeof(u32));
> > +}
> > +
> > +/**
> > + * of_property_count_u64_elems - Count the number of u64 elements in a
> > property + *
> > + * @np: device node from which the property value is to be
> > read. + * @propname: name of the property to be searched.
> > + *
> > + * Search for a property in a device node and count the number of u64
> > elements + * in it. Returns number of elements on sucess, -EINVAL if the
> > property does + * not exist or its length does not match a multiple of
> > u64 and -ENODATA if the + * property does not have a value.
> > + */
> > +static inline int of_property_count_u64_elems(const struct device_node
> > *np, + const char *propname)
> > +{
> > + return of_property_count_elems_of_size(np, propname, sizeof(u64));
> > +}
> > +
> > +/**
> >
> > * of_property_read_bool - Findfrom a property
> > * @np: device node from which the property value is to be
> > read. * @propname: name of the property to be searched.
> >
> > --
> > 1.7.10.4
^ permalink raw reply
* [PATCH v2 3/7] devicetree: bindings: add cpu clock configuration data binding for Exynos4/5
From: Rob Herring @ 2014-01-18 15:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390047057-2239-4-git-send-email-thomas.ab@samsung.com>
On Sat, Jan 18, 2014 at 6:10 AM, Thomas Abraham <ta.omasab@gmail.com> wrote:
> From: Thomas Abraham <thomas.ab@samsung.com>
>
> The clk ops of the new Samsung cpu clock provider type requires configuration
> data that will be programmed in the multiple clock blocks encapsulated within
> the cpu clock provider type. This configuration data is held in the clock
> controller node. Update clock binding documentation about this configuration
> data format for Samsung Exynos4 and Exynos5 platforms.
>
> Cc: Rob Herring <robh+dt@kernel.org>
Please copy all maintainers.
> Cc: Tomasz Figa <t.figa@samsung.com>
> Cc: <devicetree@vger.kernel.org>
> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> ---
> .../devicetree/bindings/clock/exynos4-clock.txt | 30 ++++++++++++++++++++
> .../devicetree/bindings/clock/exynos5250-clock.txt | 21 ++++++++++++++
> 2 files changed, 51 insertions(+), 0 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
> index a2ac2d9..c28aabd 100644
> --- a/Documentation/devicetree/bindings/clock/exynos4-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
> @@ -15,6 +15,29 @@ Required Properties:
>
> - #clock-cells: should be 1.
>
> +- arm-frequency-table: defines the list of arm clock speeds supported and
Seems like a Samsung specific property and nothing to do with ARM, so
it should be named accordingly.
> + the associated configuration values required to setup the clock controller
> + for generating those speeds. The format of each entry included in the
> + arm-frequency-table should be as defined below (#cells per entry = 13)
> +
> + - for Exynos4210 and Exynos4212 based platforms:
> + cell #1: arm clock frequency
> + cell #2: expected arm clock parent frequency
> + cell #3 ~ cell 12#: value of clock divider in the following order
> + core_ratio, corem0_ratio, corem1_ratio, periph_ratio,
> + atb_ratio, pclk_dbg_ratio, apll_ratio, core2_ratio,
> + copy_ratio, hpm_ratio.
> + cell #13: reserved (should be zero).
> +
> + - for Exynos4412 based platforms:
> + cell #1: arm clock frequency
> + cell #2: expected arm clock parent frequency
> + cell #3 ~ cell #13: value of clock divider in the following order
> + core_ratio, corem0_ratio, corem1_ratio, periph_ratio,
> + atb_ratio, pclk_dbg_ratio, apll_ratio, core2_ratio,
> + copy_ratio, hpm_ratio, cores_ratio
You don't need voltages? Are the h/w limitations really ratios or each
clock has a max frequency that must be maintained? I would expect the
latter and think it would be better to specify maximum frequencies of
each clock. Then you can calculate the dividers to keep frequencies in
range.
How will this scale to multi-cluster chips with different frequency ranges?
Rob
> +
> +
> The following is the list of clocks generated by the controller. Each clock is
> assigned an identifier and client nodes use this identifier to specify the
> clock which they consume. Some of the clocks are available only on a particular
> @@ -275,6 +298,13 @@ Example 1: An example of a clock controller node is listed below.
> compatible = "samsung,exynos4210-clock";
> reg = <0x10030000 0x20000>;
> #clock-cells = <1>;
> +
> + arm-frequency-table = <1200000 1200000 0 3 7 3 4 1 7 0 5 0>,
> + <1000000 1000000 0 3 7 3 4 1 7 0 4 0>,
> + < 800000 800000 0 3 7 3 3 1 7 0 3 0>,
> + < 500000 500000 0 3 7 3 3 1 7 0 3 0>,
> + < 400000 400000 0 3 7 3 3 1 7 0 3 0>,
> + < 200000 200000 0 1 3 1 1 1 0 0 3 0>;
> };
>
> Example 2: UART controller node that consumes the clock generated by the clock
> diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
> index 72ce617..99eae9c 100644
> --- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
> @@ -13,6 +13,20 @@ Required Properties:
>
> - #clock-cells: should be 1.
>
> +- arm-frequency-table: defines the list of arm clock speeds supported and
> + the associated configuration values required to setup the clock controller
> + for generating those speeds. The format of each entry included in the
> + arm-frequency-table should be as defined below (#cells per entry = 13)
> +
> + cell #1: arm clock frequency
> + cell #2: expected arm clock parent frequency
> + cell #3 ~ cell #12: value of clock divider in the following order
> + arm_ratio, cpud_ratio, acp_ratio, periph_ratio,
> + atb_ratio, pclk_dbg_ratio, apll_ratio, arm2_ratio,
> + copy_ratio, hpm_ratio
> + cell #13: reserved (should be zero)
> +
> +
> The following is the list of clocks generated by the controller. Each clock is
> assigned an identifier and client nodes use this identifier to specify the
> clock which they consume.
> @@ -177,6 +191,13 @@ Example 1: An example of a clock controller node is listed below.
> compatible = "samsung,exynos5250-clock";
> reg = <0x10010000 0x30000>;
> #clock-cells = <1>;
> +
> + arm-frequency-table = <1700000 1700000 0 3 7 7 7 3 5 0 0 2>,
> + <1600000 1600000 0 3 7 7 7 1 4 0 0 2>,
> + <1500000 1500000 0 2 7 7 7 1 4 0 0 2>,
> + <1400000 1400000 0 2 7 7 6 1 4 0 0 2>,
> + <1300000 1300000 0 2 7 7 6 1 3 0 0 2>,
> + <1200000 1200000 0 2 7 7 5 1 3 0 0 2>;
> };
>
> Example 2: UART controller node that consumes the clock generated by the clock
> --
> 1.6.6.rc2
>
^ permalink raw reply
* [PATCH v4] of: add functions to count number of elements in a property
From: Rob Herring @ 2014-01-18 15:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5115255.DrcMbtXc1P@phil>
On Sat, Jan 18, 2014 at 6:02 AM, Heiko St?bner <heiko@sntech.de> wrote:
> The need to know the number of array elements in a property is
> a common pattern. To prevent duplication of open-coded implementations
> add a helper static function that also centralises strict sanity
> checking and DTB format details, as well as a set of wrapper functions
> for u8, u16, u32 and u64.
>
> Suggested-by: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
Looks good. Do you plan to convert some users to use this?
Rob
> changes since v3:
> address more comments from Rob Herring
> - export the base function and inline the type-specific wrappers
> changes since v2:
> address more comments from Mark Rutland
> - switch to of_property_count_elems_of_size
> - use full_name instead of name in error message
> changes since v1:
> address comments from Rob Herring and Mark Rutland:
> - provide a helper and a set of wrappers for u8-u64
> - get rid of extra len variable, prop->length is enough
> - include node name in error message
>
> Mark, does your Reviewed-by holds for this variant too?
>
> drivers/of/base.c | 32 ++++++++++++++++++++++
> include/linux/of.h | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 108 insertions(+)
>
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index f807d0e..21646c0 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -862,6 +862,38 @@ struct device_node *of_find_node_by_phandle(phandle handle)
> EXPORT_SYMBOL(of_find_node_by_phandle);
>
> /**
> + * of_property_count_elems_of_size - Count the number of elements in a property
> + *
> + * @np: device node from which the property value is to be read.
> + * @propname: name of the property to be searched.
> + * @elem_size: size of the individual element
> + *
> + * Search for a property in a device node and count the number of elements of
> + * size elem_size in it. Returns number of elements on sucess, -EINVAL if the
> + * property does not exist or its length does not match a multiple of u16 and
> + * -ENODATA if the property does not have a value.
> + */
> +int of_property_count_elems_of_size(const struct device_node *np,
> + const char *propname, int elem_size)
> +{
> + struct property *prop = of_find_property(np, propname, NULL);
> +
> + if (!prop)
> + return -EINVAL;
> + if (!prop->value)
> + return -ENODATA;
> +
> + if (prop->length % elem_size != 0) {
> + pr_err("size of %s in node %s is not a multiple of %d\n",
> + propname, np->full_name, elem_size);
> + return -EINVAL;
> + }
> +
> + return prop->length / elem_size;
> +}
> +EXPORT_SYMBOL_GPL(of_property_count_elems_of_size);
> +
> +/**
> * of_find_property_value_of_size
> *
> * @np: device node from which the property value is to be read.
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 276c546..293920d 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -250,6 +250,8 @@ extern struct device_node *of_find_node_with_property(
> extern struct property *of_find_property(const struct device_node *np,
> const char *name,
> int *lenp);
> +extern int of_property_count_elems_of_size(const struct device_node *np,
> + const char *propname, int elem_size);
> extern int of_property_read_u32_index(const struct device_node *np,
> const char *propname,
> u32 index, u32 *out_value);
> @@ -426,6 +428,12 @@ static inline struct device_node *of_find_compatible_node(
> return NULL;
> }
>
> +static inline int of_property_count_elems_of_size(const struct device_node *np,
> + const char *propname, int elem_size)
> +{
> + return -ENOSYS;
> +}
> +
> static inline int of_property_read_u32_index(const struct device_node *np,
> const char *propname, u32 index, u32 *out_value)
> {
> @@ -565,6 +573,74 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; }
> #endif
>
> /**
> + * of_property_count_u8_elems - Count the number of u8 elements in a property
> + *
> + * @np: device node from which the property value is to be read.
> + * @propname: name of the property to be searched.
> + *
> + * Search for a property in a device node and count the number of u8 elements
> + * in it. Returns number of elements on sucess, -EINVAL if the property does
> + * not exist or its length does not match a multiple of u8 and -ENODATA if the
> + * property does not have a value.
> + */
> +static inline int of_property_count_u8_elems(const struct device_node *np,
> + const char *propname)
> +{
> + return of_property_count_elems_of_size(np, propname, sizeof(u8));
> +}
> +
> +/**
> + * of_property_count_u16_elems - Count the number of u16 elements in a property
> + *
> + * @np: device node from which the property value is to be read.
> + * @propname: name of the property to be searched.
> + *
> + * Search for a property in a device node and count the number of u16 elements
> + * in it. Returns number of elements on sucess, -EINVAL if the property does
> + * not exist or its length does not match a multiple of u16 and -ENODATA if the
> + * property does not have a value.
> + */
> +static inline int of_property_count_u16_elems(const struct device_node *np,
> + const char *propname)
> +{
> + return of_property_count_elems_of_size(np, propname, sizeof(u16));
> +}
> +
> +/**
> + * of_property_count_u32_elems - Count the number of u32 elements in a property
> + *
> + * @np: device node from which the property value is to be read.
> + * @propname: name of the property to be searched.
> + *
> + * Search for a property in a device node and count the number of u32 elements
> + * in it. Returns number of elements on sucess, -EINVAL if the property does
> + * not exist or its length does not match a multiple of u32 and -ENODATA if the
> + * property does not have a value.
> + */
> +static inline int of_property_count_u32_elems(const struct device_node *np,
> + const char *propname)
> +{
> + return of_property_count_elems_of_size(np, propname, sizeof(u32));
> +}
> +
> +/**
> + * of_property_count_u64_elems - Count the number of u64 elements in a property
> + *
> + * @np: device node from which the property value is to be read.
> + * @propname: name of the property to be searched.
> + *
> + * Search for a property in a device node and count the number of u64 elements
> + * in it. Returns number of elements on sucess, -EINVAL if the property does
> + * not exist or its length does not match a multiple of u64 and -ENODATA if the
> + * property does not have a value.
> + */
> +static inline int of_property_count_u64_elems(const struct device_node *np,
> + const char *propname)
> +{
> + return of_property_count_elems_of_size(np, propname, sizeof(u64));
> +}
> +
> +/**
> * of_property_read_bool - Findfrom a property
> * @np: device node from which the property value is to be read.
> * @propname: name of the property to be searched.
> --
> 1.7.10.4
>
>
^ permalink raw reply
* [PATCH 2/2] ARM: dts: Add AT24C08 EEPROM support to TINY4412
From: Alex Ling @ 2014-01-18 14:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390055084-27483-1-git-send-email-kasimling@gmail.com>
This patch adds support for AT24C08 EEPROM found on TINY4412 board.
Signed-off-by: Alex Ling <kasimling@gmail.com>
---
arch/arm/boot/dts/exynos4412-tiny4412.dts | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm/boot/dts/exynos4412-tiny4412.dts b/arch/arm/boot/dts/exynos4412-tiny4412.dts
index 2c6bfe3..9f63664 100644
--- a/arch/arm/boot/dts/exynos4412-tiny4412.dts
+++ b/arch/arm/boot/dts/exynos4412-tiny4412.dts
@@ -109,4 +109,16 @@
clock-frequency = <24000000>;
};
};
+
+ i2c at 13860000 {
+ status = "okay";
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <200000>;
+
+ eeprom at 50 {
+ compatible = "atmel,24c08";
+ reg = <0x50>;
+ pagesize = <16>;
+ };
+ };
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/2] ARM: dts: Add dwmmc host for TINY4412
From: Alex Ling @ 2014-01-18 14:24 UTC (permalink / raw)
To: linux-arm-kernel
Add dwmmc host node for to support eMMC on TINY4412 board.
Signed-off-by: Alex Ling <kasimling@gmail.com>
---
arch/arm/boot/dts/exynos4412-tiny4412.dts | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm/boot/dts/exynos4412-tiny4412.dts b/arch/arm/boot/dts/exynos4412-tiny4412.dts
index 0a98312..2c6bfe3 100644
--- a/arch/arm/boot/dts/exynos4412-tiny4412.dts
+++ b/arch/arm/boot/dts/exynos4412-tiny4412.dts
@@ -63,6 +63,25 @@
status = "okay";
};
+ mmc at 12550000 {
+ num-slots = <1>;
+ supports-highspeed;
+ broken-cd;
+ non-removable;
+ card-detect-delay = <200>;
+ samsung,dw-mshc-ciu-div = <3>;
+ samsung,dw-mshc-sdr-timing = <2 3>;
+ samsung,dw-mshc-ddr-timing = <1 2>;
+ pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ slot at 0 {
+ reg = <0>;
+ bus-width = <8>;
+ };
+ };
+
serial at 13800000 {
status = "okay";
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/3] ACPI / idle: Move idle_boot_override out of the arch directory
From: Rafael J. Wysocki @ 2014-01-18 13:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52D9FA72.5020505@linaro.org>
On Saturday, January 18, 2014 11:52:18 AM Hanjun Guo wrote:
> On 2014-1-18 11:45, Hanjun Guo wrote:
> > On 2014-1-17 20:06, Sudeep Holla wrote:
> >> On 17/01/14 02:03, Hanjun Guo wrote:
> >>> Move idle_boot_override out of the arch directory to be a single enum
> >>> including both platforms values, this will make it rather easier to
> >>> avoid ifdefs around which definitions are for which processor in
> >>> generally used ACPI code.
> >>>
> >>> IDLE_FORCE_MWAIT for IA64 is not used anywhere, so romove it.
> >>>
> >>> No functional change in this patch.
> >>>
> >>> Suggested-by: Alan <gnomes@lxorguk.ukuu.org.uk>
> >>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> >>> ---
> [...]
> >>> diff --git a/include/linux/cpu.h b/include/linux/cpu.h
> >>> index 03e235ad..e324561 100644
> >>> --- a/include/linux/cpu.h
> >>> +++ b/include/linux/cpu.h
> >>> @@ -220,6 +220,14 @@ void cpu_idle(void);
> >>>
> >>> void cpu_idle_poll_ctrl(bool enable);
> >>>
> >>> +enum idle_boot_override {
> >>> + IDLE_NO_OVERRIDE = 0,
> >>> + IDLE_HALT,
> >>> + IDLE_NOMWAIT,
> >>> + IDLE_POLL,
> >>> + IDLE_POWERSAVE_OFF
> >>> +};
> >>> +
> >>
> >> I do understand the idea behind this change, but IMO HALT and MWAIT are x86
> >> specific and may not make sense for other architectures.
> >
> > yes, this is the strange part, the value is arch-dependent.
> >
> >>
> >> It will also require every architecture using ACPI to export
> >> boot_option_idle_override which may not be really required.
> >
> > so, how about forget this patch and move boot_option_idle_override
> > related code into arch directory such as arch/x86/acpi/boot.c for
> > x86?
>
> The general idea is that we can move all the arch-dependent codes
> in ACPI driver to arch directory, then make codes in drivers/acpi/
> arch independent.
Well, MWAIT is arch-dependent, so I'm not sure how IDLE_NOMWAIT fits into
include/linux/cpu.h?
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply
* [PATCH v2 7/7] cpufreq: exynos: remove all exynos specific cpufreq driver support
From: Thomas Abraham @ 2014-01-18 12:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390047057-2239-1-git-send-email-thomas.ab@samsung.com>
From: Thomas Abraham <thomas.ab@samsung.com>
Exynos4210, Exynos4x12 and Exynos5250 based platforms have switched over
to use cpufreq-cpu0 driver for cpufreq functionality. So the Exynos
specific cpufreq drivers for these platforms can be removed.
Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: Jaecheol Lee <jc.lee@samsung.com>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
drivers/cpufreq/Kconfig.arm | 36 ----
drivers/cpufreq/Makefile | 4 -
drivers/cpufreq/exynos-cpufreq.c | 292 ----------------------------------
drivers/cpufreq/exynos-cpufreq.h | 91 -----------
drivers/cpufreq/exynos4210-cpufreq.c | 157 ------------------
drivers/cpufreq/exynos4x12-cpufreq.c | 211 ------------------------
drivers/cpufreq/exynos5250-cpufreq.c | 183 ---------------------
7 files changed, 0 insertions(+), 974 deletions(-)
delete mode 100644 drivers/cpufreq/exynos-cpufreq.c
delete mode 100644 drivers/cpufreq/exynos-cpufreq.h
delete mode 100644 drivers/cpufreq/exynos4210-cpufreq.c
delete mode 100644 drivers/cpufreq/exynos4x12-cpufreq.c
delete mode 100644 drivers/cpufreq/exynos5250-cpufreq.c
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 3129749..704656d 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -16,42 +16,6 @@ config ARM_DT_BL_CPUFREQ
This enables probing via DT for Generic CPUfreq driver for ARM
big.LITTLE platform. This gets frequency tables from DT.
-config ARM_EXYNOS_CPUFREQ
- bool
-
-config ARM_EXYNOS4210_CPUFREQ
- bool "SAMSUNG EXYNOS4210"
- depends on CPU_EXYNOS4210
- default y
- select ARM_EXYNOS_CPUFREQ
- help
- This adds the CPUFreq driver for Samsung EXYNOS4210
- SoC (S5PV310 or S5PC210).
-
- If in doubt, say N.
-
-config ARM_EXYNOS4X12_CPUFREQ
- bool "SAMSUNG EXYNOS4x12"
- depends on (SOC_EXYNOS4212 || SOC_EXYNOS4412)
- default y
- select ARM_EXYNOS_CPUFREQ
- help
- This adds the CPUFreq driver for Samsung EXYNOS4X12
- SoC (EXYNOS4212 or EXYNOS4412).
-
- If in doubt, say N.
-
-config ARM_EXYNOS5250_CPUFREQ
- bool "SAMSUNG EXYNOS5250"
- depends on SOC_EXYNOS5250
- default y
- select ARM_EXYNOS_CPUFREQ
- help
- This adds the CPUFreq driver for Samsung EXYNOS5250
- SoC.
-
- If in doubt, say N.
-
config ARM_EXYNOS5440_CPUFREQ
bool "SAMSUNG EXYNOS5440"
depends on SOC_EXYNOS5440
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 7494565..3abfe05 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -49,10 +49,6 @@ obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
obj-$(CONFIG_ARCH_DAVINCI_DA850) += davinci-cpufreq.o
obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o
-obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += exynos-cpufreq.o
-obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
-obj-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o
-obj-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
deleted file mode 100644
index fcd2914..0000000
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS - CPU frequency scaling support for EXYNOS series
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/regulator/consumer.h>
-#include <linux/cpufreq.h>
-#include <linux/suspend.h>
-#include <linux/platform_device.h>
-
-#include <plat/cpu.h>
-
-#include "exynos-cpufreq.h"
-
-static struct exynos_dvfs_info *exynos_info;
-
-static struct regulator *arm_regulator;
-
-static unsigned int locking_frequency;
-static bool frequency_locked;
-static DEFINE_MUTEX(cpufreq_lock);
-
-static int exynos_cpufreq_get_index(unsigned int freq)
-{
- struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
- int index;
-
- for (index = 0;
- freq_table[index].frequency != CPUFREQ_TABLE_END; index++)
- if (freq_table[index].frequency == freq)
- break;
-
- if (freq_table[index].frequency == CPUFREQ_TABLE_END)
- return -EINVAL;
-
- return index;
-}
-
-static int exynos_cpufreq_scale(unsigned int target_freq)
-{
- struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
- unsigned int *volt_table = exynos_info->volt_table;
- struct cpufreq_policy *policy = cpufreq_cpu_get(0);
- unsigned int arm_volt, safe_arm_volt = 0;
- unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz;
- unsigned int old_freq;
- int index, old_index;
- int ret = 0;
-
- old_freq = policy->cur;
-
- /*
- * The policy max have been changed so that we cannot get proper
- * old_index with cpufreq_frequency_table_target(). Thus, ignore
- * policy and get the index from the raw frequency table.
- */
- old_index = exynos_cpufreq_get_index(old_freq);
- if (old_index < 0) {
- ret = old_index;
- goto out;
- }
-
- index = exynos_cpufreq_get_index(target_freq);
- if (index < 0) {
- ret = index;
- goto out;
- }
-
- /*
- * ARM clock source will be changed APLL to MPLL temporary
- * To support this level, need to control regulator for
- * required voltage level
- */
- if (exynos_info->need_apll_change != NULL) {
- if (exynos_info->need_apll_change(old_index, index) &&
- (freq_table[index].frequency < mpll_freq_khz) &&
- (freq_table[old_index].frequency < mpll_freq_khz))
- safe_arm_volt = volt_table[exynos_info->pll_safe_idx];
- }
- arm_volt = volt_table[index];
-
- /* When the new frequency is higher than current frequency */
- if ((target_freq > old_freq) && !safe_arm_volt) {
- /* Firstly, voltage up to increase frequency */
- ret = regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
- if (ret) {
- pr_err("%s: failed to set cpu voltage to %d\n",
- __func__, arm_volt);
- return ret;
- }
- }
-
- if (safe_arm_volt) {
- ret = regulator_set_voltage(arm_regulator, safe_arm_volt,
- safe_arm_volt);
- if (ret) {
- pr_err("%s: failed to set cpu voltage to %d\n",
- __func__, safe_arm_volt);
- return ret;
- }
- }
-
- exynos_info->set_freq(old_index, index);
-
- /* When the new frequency is lower than current frequency */
- if ((target_freq < old_freq) ||
- ((target_freq > old_freq) && safe_arm_volt)) {
- /* down the voltage after frequency change */
- ret = regulator_set_voltage(arm_regulator, arm_volt,
- arm_volt);
- if (ret) {
- pr_err("%s: failed to set cpu voltage to %d\n",
- __func__, arm_volt);
- goto out;
- }
- }
-
-out:
- cpufreq_cpu_put(policy);
-
- return ret;
-}
-
-static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
-{
- struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
- int ret = 0;
-
- mutex_lock(&cpufreq_lock);
-
- if (frequency_locked)
- goto out;
-
- ret = exynos_cpufreq_scale(freq_table[index].frequency);
-
-out:
- mutex_unlock(&cpufreq_lock);
-
- return ret;
-}
-
-#ifdef CONFIG_PM
-static int exynos_cpufreq_suspend(struct cpufreq_policy *policy)
-{
- return 0;
-}
-
-static int exynos_cpufreq_resume(struct cpufreq_policy *policy)
-{
- return 0;
-}
-#endif
-
-/**
- * exynos_cpufreq_pm_notifier - block CPUFREQ's activities in suspend-resume
- * context
- * @notifier
- * @pm_event
- * @v
- *
- * While frequency_locked == true, target() ignores every frequency but
- * locking_frequency. The locking_frequency value is the initial frequency,
- * which is set by the bootloader. In order to eliminate possible
- * inconsistency in clock values, we save and restore frequencies during
- * suspend and resume and block CPUFREQ activities. Note that the standard
- * suspend/resume cannot be used as they are too deep (syscore_ops) for
- * regulator actions.
- */
-static int exynos_cpufreq_pm_notifier(struct notifier_block *notifier,
- unsigned long pm_event, void *v)
-{
- int ret;
-
- switch (pm_event) {
- case PM_SUSPEND_PREPARE:
- mutex_lock(&cpufreq_lock);
- frequency_locked = true;
- mutex_unlock(&cpufreq_lock);
-
- ret = exynos_cpufreq_scale(locking_frequency);
- if (ret < 0)
- return NOTIFY_BAD;
-
- break;
-
- case PM_POST_SUSPEND:
- mutex_lock(&cpufreq_lock);
- frequency_locked = false;
- mutex_unlock(&cpufreq_lock);
- break;
- }
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block exynos_cpufreq_nb = {
- .notifier_call = exynos_cpufreq_pm_notifier,
-};
-
-static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
-{
- policy->clk = exynos_info->cpu_clk;
- return cpufreq_generic_init(policy, exynos_info->freq_table, 100000);
-}
-
-static struct cpufreq_driver exynos_driver = {
- .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
- .verify = cpufreq_generic_frequency_table_verify,
- .target_index = exynos_target,
- .get = cpufreq_generic_get,
- .init = exynos_cpufreq_cpu_init,
- .exit = cpufreq_generic_exit,
- .name = "exynos_cpufreq",
- .attr = cpufreq_generic_attr,
-#ifdef CONFIG_ARM_EXYNOS_CPU_FREQ_BOOST_SW
- .boost_supported = true,
-#endif
-#ifdef CONFIG_PM
- .suspend = exynos_cpufreq_suspend,
- .resume = exynos_cpufreq_resume,
-#endif
-};
-
-static int exynos_cpufreq_probe(struct platform_device *pdev)
-{
- int ret = -EINVAL;
-
- exynos_info = kzalloc(sizeof(*exynos_info), GFP_KERNEL);
- if (!exynos_info)
- return -ENOMEM;
-
- if (soc_is_exynos4210())
- ret = exynos4210_cpufreq_init(exynos_info);
- else if (soc_is_exynos4212() || soc_is_exynos4412())
- ret = exynos4x12_cpufreq_init(exynos_info);
- else if (soc_is_exynos5250())
- ret = exynos5250_cpufreq_init(exynos_info);
- else
- return 0;
-
- if (ret)
- goto err_vdd_arm;
-
- if (exynos_info->set_freq == NULL) {
- pr_err("%s: No set_freq function (ERR)\n", __func__);
- goto err_vdd_arm;
- }
-
- arm_regulator = regulator_get(NULL, "vdd_arm");
- if (IS_ERR(arm_regulator)) {
- pr_err("%s: failed to get resource vdd_arm\n", __func__);
- goto err_vdd_arm;
- }
-
- locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000;
-
- register_pm_notifier(&exynos_cpufreq_nb);
-
- if (cpufreq_register_driver(&exynos_driver)) {
- pr_err("%s: failed to register cpufreq driver\n", __func__);
- goto err_cpufreq;
- }
-
- return 0;
-err_cpufreq:
- unregister_pm_notifier(&exynos_cpufreq_nb);
-
- regulator_put(arm_regulator);
-err_vdd_arm:
- kfree(exynos_info);
- return -EINVAL;
-}
-
-static struct platform_driver exynos_cpufreq_platdrv = {
- .driver = {
- .name = "exynos-cpufreq",
- .owner = THIS_MODULE,
- },
- .probe = exynos_cpufreq_probe,
-};
-module_platform_driver(exynos_cpufreq_platdrv);
diff --git a/drivers/cpufreq/exynos-cpufreq.h b/drivers/cpufreq/exynos-cpufreq.h
deleted file mode 100644
index 3ddade8..0000000
--- a/drivers/cpufreq/exynos-cpufreq.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS - CPUFreq support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-enum cpufreq_level_index {
- L0, L1, L2, L3, L4,
- L5, L6, L7, L8, L9,
- L10, L11, L12, L13, L14,
- L15, L16, L17, L18, L19,
- L20,
-};
-
-#define APLL_FREQ(f, a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, m, p, s) \
- { \
- .freq = (f) * 1000, \
- .clk_div_cpu0 = ((a0) | (a1) << 4 | (a2) << 8 | (a3) << 12 | \
- (a4) << 16 | (a5) << 20 | (a6) << 24 | (a7) << 28), \
- .clk_div_cpu1 = (b0 << 0 | b1 << 4 | b2 << 8), \
- .mps = ((m) << 16 | (p) << 8 | (s)), \
- }
-
-struct apll_freq {
- unsigned int freq;
- u32 clk_div_cpu0;
- u32 clk_div_cpu1;
- u32 mps;
-};
-
-struct exynos_dvfs_info {
- unsigned long mpll_freq_khz;
- unsigned int pll_safe_idx;
- struct clk *cpu_clk;
- unsigned int *volt_table;
- struct cpufreq_frequency_table *freq_table;
- void (*set_freq)(unsigned int, unsigned int);
- bool (*need_apll_change)(unsigned int, unsigned int);
-};
-
-#ifdef CONFIG_ARM_EXYNOS4210_CPUFREQ
-extern int exynos4210_cpufreq_init(struct exynos_dvfs_info *);
-#else
-static inline int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
-{
- return -EOPNOTSUPP;
-}
-#endif
-#ifdef CONFIG_ARM_EXYNOS4X12_CPUFREQ
-extern int exynos4x12_cpufreq_init(struct exynos_dvfs_info *);
-#else
-static inline int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info)
-{
- return -EOPNOTSUPP;
-}
-#endif
-#ifdef CONFIG_ARM_EXYNOS5250_CPUFREQ
-extern int exynos5250_cpufreq_init(struct exynos_dvfs_info *);
-#else
-static inline int exynos5250_cpufreq_init(struct exynos_dvfs_info *info)
-{
- return -EOPNOTSUPP;
-}
-#endif
-
-#include <plat/cpu.h>
-#include <mach/map.h>
-
-#define EXYNOS4_CLKSRC_CPU (S5P_VA_CMU + 0x14200)
-#define EXYNOS4_CLKMUX_STATCPU (S5P_VA_CMU + 0x14400)
-
-#define EXYNOS4_CLKDIV_CPU (S5P_VA_CMU + 0x14500)
-#define EXYNOS4_CLKDIV_CPU1 (S5P_VA_CMU + 0x14504)
-#define EXYNOS4_CLKDIV_STATCPU (S5P_VA_CMU + 0x14600)
-#define EXYNOS4_CLKDIV_STATCPU1 (S5P_VA_CMU + 0x14604)
-
-#define EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT (16)
-#define EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK (0x7 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT)
-
-#define EXYNOS5_APLL_LOCK (S5P_VA_CMU + 0x00000)
-#define EXYNOS5_APLL_CON0 (S5P_VA_CMU + 0x00100)
-#define EXYNOS5_CLKMUX_STATCPU (S5P_VA_CMU + 0x00400)
-#define EXYNOS5_CLKDIV_CPU0 (S5P_VA_CMU + 0x00500)
-#define EXYNOS5_CLKDIV_CPU1 (S5P_VA_CMU + 0x00504)
-#define EXYNOS5_CLKDIV_STATCPU0 (S5P_VA_CMU + 0x00600)
-#define EXYNOS5_CLKDIV_STATCPU1 (S5P_VA_CMU + 0x00604)
diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
deleted file mode 100644
index 40d84c4..0000000
--- a/drivers/cpufreq/exynos4210-cpufreq.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS4210 - CPU frequency scaling support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/cpufreq.h>
-
-#include "exynos-cpufreq.h"
-
-static struct clk *cpu_clk;
-static struct clk *moutcore;
-static struct clk *mout_mpll;
-static struct clk *mout_apll;
-
-static unsigned int exynos4210_volt_table[] = {
- 1250000, 1150000, 1050000, 975000, 950000,
-};
-
-static struct cpufreq_frequency_table exynos4210_freq_table[] = {
- {L0, 1200 * 1000},
- {L1, 1000 * 1000},
- {L2, 800 * 1000},
- {L3, 500 * 1000},
- {L4, 200 * 1000},
- {0, CPUFREQ_TABLE_END},
-};
-
-static struct apll_freq apll_freq_4210[] = {
- /*
- * values:
- * freq
- * clock divider for CORE, COREM0, COREM1, PERIPH, ATB, PCLK_DBG, APLL, RESERVED
- * clock divider for COPY, HPM, RESERVED
- * PLL M, P, S
- */
- APLL_FREQ(1200, 0, 3, 7, 3, 4, 1, 7, 0, 5, 0, 0, 150, 3, 1),
- APLL_FREQ(1000, 0, 3, 7, 3, 4, 1, 7, 0, 4, 0, 0, 250, 6, 1),
- APLL_FREQ(800, 0, 3, 7, 3, 3, 1, 7, 0, 3, 0, 0, 200, 6, 1),
- APLL_FREQ(500, 0, 3, 7, 3, 3, 1, 7, 0, 3, 0, 0, 250, 6, 2),
- APLL_FREQ(200, 0, 1, 3, 1, 3, 1, 0, 0, 3, 0, 0, 200, 6, 3),
-};
-
-static void exynos4210_set_clkdiv(unsigned int div_index)
-{
- unsigned int tmp;
-
- /* Change Divider - CPU0 */
-
- tmp = apll_freq_4210[div_index].clk_div_cpu0;
-
- __raw_writel(tmp, EXYNOS4_CLKDIV_CPU);
-
- do {
- tmp = __raw_readl(EXYNOS4_CLKDIV_STATCPU);
- } while (tmp & 0x1111111);
-
- /* Change Divider - CPU1 */
-
- tmp = apll_freq_4210[div_index].clk_div_cpu1;
-
- __raw_writel(tmp, EXYNOS4_CLKDIV_CPU1);
-
- do {
- tmp = __raw_readl(EXYNOS4_CLKDIV_STATCPU1);
- } while (tmp & 0x11);
-}
-
-static void exynos4210_set_apll(unsigned int index)
-{
- unsigned int tmp, freq = apll_freq_4210[index].freq;
-
- /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
- clk_set_parent(moutcore, mout_mpll);
-
- do {
- tmp = (__raw_readl(EXYNOS4_CLKMUX_STATCPU)
- >> EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT);
- tmp &= 0x7;
- } while (tmp != 0x2);
-
- clk_set_rate(mout_apll, freq * 1000);
-
- /* MUX_CORE_SEL = APLL */
- clk_set_parent(moutcore, mout_apll);
-
- do {
- tmp = __raw_readl(EXYNOS4_CLKMUX_STATCPU);
- tmp &= EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK;
- } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT));
-}
-
-static void exynos4210_set_frequency(unsigned int old_index,
- unsigned int new_index)
-{
- if (old_index > new_index) {
- exynos4210_set_clkdiv(new_index);
- exynos4210_set_apll(new_index);
- } else if (old_index < new_index) {
- exynos4210_set_apll(new_index);
- exynos4210_set_clkdiv(new_index);
- }
-}
-
-int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
-{
- unsigned long rate;
-
- cpu_clk = clk_get(NULL, "armclk");
- if (IS_ERR(cpu_clk))
- return PTR_ERR(cpu_clk);
-
- moutcore = clk_get(NULL, "moutcore");
- if (IS_ERR(moutcore))
- goto err_moutcore;
-
- mout_mpll = clk_get(NULL, "mout_mpll");
- if (IS_ERR(mout_mpll))
- goto err_mout_mpll;
-
- rate = clk_get_rate(mout_mpll) / 1000;
-
- mout_apll = clk_get(NULL, "mout_apll");
- if (IS_ERR(mout_apll))
- goto err_mout_apll;
-
- info->mpll_freq_khz = rate;
- /* 800Mhz */
- info->pll_safe_idx = L2;
- info->cpu_clk = cpu_clk;
- info->volt_table = exynos4210_volt_table;
- info->freq_table = exynos4210_freq_table;
- info->set_freq = exynos4210_set_frequency;
-
- return 0;
-
-err_mout_apll:
- clk_put(mout_mpll);
-err_mout_mpll:
- clk_put(moutcore);
-err_moutcore:
- clk_put(cpu_clk);
-
- pr_debug("%s: failed initialization\n", __func__);
- return -EINVAL;
-}
diff --git a/drivers/cpufreq/exynos4x12-cpufreq.c b/drivers/cpufreq/exynos4x12-cpufreq.c
deleted file mode 100644
index 7c11ace..0000000
--- a/drivers/cpufreq/exynos4x12-cpufreq.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS4X12 - CPU frequency scaling support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/cpufreq.h>
-
-#include "exynos-cpufreq.h"
-
-static struct clk *cpu_clk;
-static struct clk *moutcore;
-static struct clk *mout_mpll;
-static struct clk *mout_apll;
-
-static unsigned int exynos4x12_volt_table[] = {
- 1350000, 1287500, 1250000, 1187500, 1137500, 1087500, 1037500,
- 1000000, 987500, 975000, 950000, 925000, 900000, 900000
-};
-
-static struct cpufreq_frequency_table exynos4x12_freq_table[] = {
- {CPUFREQ_BOOST_FREQ, 1500 * 1000},
- {L1, 1400 * 1000},
- {L2, 1300 * 1000},
- {L3, 1200 * 1000},
- {L4, 1100 * 1000},
- {L5, 1000 * 1000},
- {L6, 900 * 1000},
- {L7, 800 * 1000},
- {L8, 700 * 1000},
- {L9, 600 * 1000},
- {L10, 500 * 1000},
- {L11, 400 * 1000},
- {L12, 300 * 1000},
- {L13, 200 * 1000},
- {0, CPUFREQ_TABLE_END},
-};
-
-static struct apll_freq *apll_freq_4x12;
-
-static struct apll_freq apll_freq_4212[] = {
- /*
- * values:
- * freq
- * clock divider for CORE, COREM0, COREM1, PERIPH, ATB, PCLK_DBG, APLL, CORE2
- * clock divider for COPY, HPM, RESERVED
- * PLL M, P, S
- */
- APLL_FREQ(1500, 0, 3, 7, 0, 6, 1, 2, 0, 6, 2, 0, 250, 4, 0),
- APLL_FREQ(1400, 0, 3, 7, 0, 6, 1, 2, 0, 6, 2, 0, 175, 3, 0),
- APLL_FREQ(1300, 0, 3, 7, 0, 5, 1, 2, 0, 5, 2, 0, 325, 6, 0),
- APLL_FREQ(1200, 0, 3, 7, 0, 5, 1, 2, 0, 5, 2, 0, 200, 4, 0),
- APLL_FREQ(1100, 0, 3, 6, 0, 4, 1, 2, 0, 4, 2, 0, 275, 6, 0),
- APLL_FREQ(1000, 0, 2, 5, 0, 4, 1, 1, 0, 4, 2, 0, 125, 3, 0),
- APLL_FREQ(900, 0, 2, 5, 0, 3, 1, 1, 0, 3, 2, 0, 150, 4, 0),
- APLL_FREQ(800, 0, 2, 5, 0, 3, 1, 1, 0, 3, 2, 0, 100, 3, 0),
- APLL_FREQ(700, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 175, 3, 1),
- APLL_FREQ(600, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 200, 4, 1),
- APLL_FREQ(500, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 125, 3, 1),
- APLL_FREQ(400, 0, 2, 4, 0, 3, 1, 1, 0, 3, 2, 0, 100, 3, 1),
- APLL_FREQ(300, 0, 2, 4, 0, 2, 1, 1, 0, 3, 2, 0, 200, 4, 2),
- APLL_FREQ(200, 0, 1, 3, 0, 1, 1, 1, 0, 3, 2, 0, 100, 3, 2),
-};
-
-static struct apll_freq apll_freq_4412[] = {
- /*
- * values:
- * freq
- * clock divider for CORE, COREM0, COREM1, PERIPH, ATB, PCLK_DBG, APLL, CORE2
- * clock divider for COPY, HPM, CORES
- * PLL M, P, S
- */
- APLL_FREQ(1500, 0, 3, 7, 0, 6, 1, 2, 0, 6, 0, 7, 250, 4, 0),
- APLL_FREQ(1400, 0, 3, 7, 0, 6, 1, 2, 0, 6, 0, 6, 175, 3, 0),
- APLL_FREQ(1300, 0, 3, 7, 0, 5, 1, 2, 0, 5, 0, 6, 325, 6, 0),
- APLL_FREQ(1200, 0, 3, 7, 0, 5, 1, 2, 0, 5, 0, 5, 200, 4, 0),
- APLL_FREQ(1100, 0, 3, 6, 0, 4, 1, 2, 0, 4, 0, 5, 275, 6, 0),
- APLL_FREQ(1000, 0, 2, 5, 0, 4, 1, 1, 0, 4, 0, 4, 125, 3, 0),
- APLL_FREQ(900, 0, 2, 5, 0, 3, 1, 1, 0, 3, 0, 4, 150, 4, 0),
- APLL_FREQ(800, 0, 2, 5, 0, 3, 1, 1, 0, 3, 0, 3, 100, 3, 0),
- APLL_FREQ(700, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 3, 175, 3, 1),
- APLL_FREQ(600, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 2, 200, 4, 1),
- APLL_FREQ(500, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 2, 125, 3, 1),
- APLL_FREQ(400, 0, 2, 4, 0, 3, 1, 1, 0, 3, 0, 1, 100, 3, 1),
- APLL_FREQ(300, 0, 2, 4, 0, 2, 1, 1, 0, 3, 0, 1, 200, 4, 2),
- APLL_FREQ(200, 0, 1, 3, 0, 1, 1, 1, 0, 3, 0, 0, 100, 3, 2),
-};
-
-static void exynos4x12_set_clkdiv(unsigned int div_index)
-{
- unsigned int tmp;
- unsigned int stat_cpu1;
-
- /* Change Divider - CPU0 */
-
- tmp = apll_freq_4x12[div_index].clk_div_cpu0;
-
- __raw_writel(tmp, EXYNOS4_CLKDIV_CPU);
-
- while (__raw_readl(EXYNOS4_CLKDIV_STATCPU) & 0x11111111)
- cpu_relax();
-
- /* Change Divider - CPU1 */
- tmp = apll_freq_4x12[div_index].clk_div_cpu1;
-
- __raw_writel(tmp, EXYNOS4_CLKDIV_CPU1);
- if (soc_is_exynos4212())
- stat_cpu1 = 0x11;
- else
- stat_cpu1 = 0x111;
-
- while (__raw_readl(EXYNOS4_CLKDIV_STATCPU1) & stat_cpu1)
- cpu_relax();
-}
-
-static void exynos4x12_set_apll(unsigned int index)
-{
- unsigned int tmp, freq = apll_freq_4x12[index].freq;
-
- /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
- clk_set_parent(moutcore, mout_mpll);
-
- do {
- cpu_relax();
- tmp = (__raw_readl(EXYNOS4_CLKMUX_STATCPU)
- >> EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT);
- tmp &= 0x7;
- } while (tmp != 0x2);
-
- clk_set_rate(mout_apll, freq * 1000);
-
- /* MUX_CORE_SEL = APLL */
- clk_set_parent(moutcore, mout_apll);
-
- do {
- cpu_relax();
- tmp = __raw_readl(EXYNOS4_CLKMUX_STATCPU);
- tmp &= EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK;
- } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT));
-}
-
-static void exynos4x12_set_frequency(unsigned int old_index,
- unsigned int new_index)
-{
- if (old_index > new_index) {
- exynos4x12_set_clkdiv(new_index);
- exynos4x12_set_apll(new_index);
- } else if (old_index < new_index) {
- exynos4x12_set_apll(new_index);
- exynos4x12_set_clkdiv(new_index);
- }
-}
-
-int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info)
-{
- unsigned long rate;
-
- cpu_clk = clk_get(NULL, "armclk");
- if (IS_ERR(cpu_clk))
- return PTR_ERR(cpu_clk);
-
- moutcore = clk_get(NULL, "moutcore");
- if (IS_ERR(moutcore))
- goto err_moutcore;
-
- mout_mpll = clk_get(NULL, "mout_mpll");
- if (IS_ERR(mout_mpll))
- goto err_mout_mpll;
-
- rate = clk_get_rate(mout_mpll) / 1000;
-
- mout_apll = clk_get(NULL, "mout_apll");
- if (IS_ERR(mout_apll))
- goto err_mout_apll;
-
- if (soc_is_exynos4212())
- apll_freq_4x12 = apll_freq_4212;
- else
- apll_freq_4x12 = apll_freq_4412;
-
- info->mpll_freq_khz = rate;
- /* 800Mhz */
- info->pll_safe_idx = L7;
- info->cpu_clk = cpu_clk;
- info->volt_table = exynos4x12_volt_table;
- info->freq_table = exynos4x12_freq_table;
- info->set_freq = exynos4x12_set_frequency;
-
- return 0;
-
-err_mout_apll:
- clk_put(mout_mpll);
-err_mout_mpll:
- clk_put(moutcore);
-err_moutcore:
- clk_put(cpu_clk);
-
- pr_debug("%s: failed initialization\n", __func__);
- return -EINVAL;
-}
diff --git a/drivers/cpufreq/exynos5250-cpufreq.c b/drivers/cpufreq/exynos5250-cpufreq.c
deleted file mode 100644
index 5f90b82..0000000
--- a/drivers/cpufreq/exynos5250-cpufreq.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2010-20122Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * EXYNOS5250 - CPU frequency scaling support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/cpufreq.h>
-
-#include <mach/map.h>
-
-#include "exynos-cpufreq.h"
-
-static struct clk *cpu_clk;
-static struct clk *moutcore;
-static struct clk *mout_mpll;
-static struct clk *mout_apll;
-
-static unsigned int exynos5250_volt_table[] = {
- 1300000, 1250000, 1225000, 1200000, 1150000,
- 1125000, 1100000, 1075000, 1050000, 1025000,
- 1012500, 1000000, 975000, 950000, 937500,
- 925000
-};
-
-static struct cpufreq_frequency_table exynos5250_freq_table[] = {
- {L0, 1700 * 1000},
- {L1, 1600 * 1000},
- {L2, 1500 * 1000},
- {L3, 1400 * 1000},
- {L4, 1300 * 1000},
- {L5, 1200 * 1000},
- {L6, 1100 * 1000},
- {L7, 1000 * 1000},
- {L8, 900 * 1000},
- {L9, 800 * 1000},
- {L10, 700 * 1000},
- {L11, 600 * 1000},
- {L12, 500 * 1000},
- {L13, 400 * 1000},
- {L14, 300 * 1000},
- {L15, 200 * 1000},
- {0, CPUFREQ_TABLE_END},
-};
-
-static struct apll_freq apll_freq_5250[] = {
- /*
- * values:
- * freq
- * clock divider for ARM, CPUD, ACP, PERIPH, ATB, PCLK_DBG, APLL, ARM2
- * clock divider for COPY, HPM, RESERVED
- * PLL M, P, S
- */
- APLL_FREQ(1700, 0, 3, 7, 7, 7, 3, 5, 0, 0, 2, 0, 425, 6, 0),
- APLL_FREQ(1600, 0, 3, 7, 7, 7, 1, 4, 0, 0, 2, 0, 200, 3, 0),
- APLL_FREQ(1500, 0, 2, 7, 7, 7, 1, 4, 0, 0, 2, 0, 250, 4, 0),
- APLL_FREQ(1400, 0, 2, 7, 7, 6, 1, 4, 0, 0, 2, 0, 175, 3, 0),
- APLL_FREQ(1300, 0, 2, 7, 7, 6, 1, 3, 0, 0, 2, 0, 325, 6, 0),
- APLL_FREQ(1200, 0, 2, 7, 7, 5, 1, 3, 0, 0, 2, 0, 200, 4, 0),
- APLL_FREQ(1100, 0, 3, 7, 7, 5, 1, 3, 0, 0, 2, 0, 275, 6, 0),
- APLL_FREQ(1000, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 125, 3, 0),
- APLL_FREQ(900, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 150, 4, 0),
- APLL_FREQ(800, 0, 1, 7, 7, 4, 1, 2, 0, 0, 2, 0, 100, 3, 0),
- APLL_FREQ(700, 0, 1, 7, 7, 3, 1, 1, 0, 0, 2, 0, 175, 3, 1),
- APLL_FREQ(600, 0, 1, 7, 7, 3, 1, 1, 0, 0, 2, 0, 200, 4, 1),
- APLL_FREQ(500, 0, 1, 7, 7, 2, 1, 1, 0, 0, 2, 0, 125, 3, 1),
- APLL_FREQ(400, 0, 1, 7, 7, 2, 1, 1, 0, 0, 2, 0, 100, 3, 1),
- APLL_FREQ(300, 0, 1, 7, 7, 1, 1, 1, 0, 0, 2, 0, 200, 4, 2),
- APLL_FREQ(200, 0, 1, 7, 7, 1, 1, 1, 0, 0, 2, 0, 100, 3, 2),
-};
-
-static void set_clkdiv(unsigned int div_index)
-{
- unsigned int tmp;
-
- /* Change Divider - CPU0 */
-
- tmp = apll_freq_5250[div_index].clk_div_cpu0;
-
- __raw_writel(tmp, EXYNOS5_CLKDIV_CPU0);
-
- while (__raw_readl(EXYNOS5_CLKDIV_STATCPU0) & 0x11111111)
- cpu_relax();
-
- /* Change Divider - CPU1 */
- tmp = apll_freq_5250[div_index].clk_div_cpu1;
-
- __raw_writel(tmp, EXYNOS5_CLKDIV_CPU1);
-
- while (__raw_readl(EXYNOS5_CLKDIV_STATCPU1) & 0x11)
- cpu_relax();
-}
-
-static void set_apll(unsigned int index)
-{
- unsigned int tmp;
- unsigned int freq = apll_freq_5250[index].freq;
-
- /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
- clk_set_parent(moutcore, mout_mpll);
-
- do {
- cpu_relax();
- tmp = (__raw_readl(EXYNOS5_CLKMUX_STATCPU) >> 16);
- tmp &= 0x7;
- } while (tmp != 0x2);
-
- clk_set_rate(mout_apll, freq * 1000);
-
- /* MUX_CORE_SEL = APLL */
- clk_set_parent(moutcore, mout_apll);
-
- do {
- cpu_relax();
- tmp = __raw_readl(EXYNOS5_CLKMUX_STATCPU);
- tmp &= (0x7 << 16);
- } while (tmp != (0x1 << 16));
-}
-
-static void exynos5250_set_frequency(unsigned int old_index,
- unsigned int new_index)
-{
- if (old_index > new_index) {
- set_clkdiv(new_index);
- set_apll(new_index);
- } else if (old_index < new_index) {
- set_apll(new_index);
- set_clkdiv(new_index);
- }
-}
-
-int exynos5250_cpufreq_init(struct exynos_dvfs_info *info)
-{
- unsigned long rate;
-
- cpu_clk = clk_get(NULL, "armclk");
- if (IS_ERR(cpu_clk))
- return PTR_ERR(cpu_clk);
-
- moutcore = clk_get(NULL, "mout_cpu");
- if (IS_ERR(moutcore))
- goto err_moutcore;
-
- mout_mpll = clk_get(NULL, "mout_mpll");
- if (IS_ERR(mout_mpll))
- goto err_mout_mpll;
-
- rate = clk_get_rate(mout_mpll) / 1000;
-
- mout_apll = clk_get(NULL, "mout_apll");
- if (IS_ERR(mout_apll))
- goto err_mout_apll;
-
- info->mpll_freq_khz = rate;
- /* 800Mhz */
- info->pll_safe_idx = L9;
- info->cpu_clk = cpu_clk;
- info->volt_table = exynos5250_volt_table;
- info->freq_table = exynos5250_freq_table;
- info->set_freq = exynos5250_set_frequency;
-
- return 0;
-
-err_mout_apll:
- clk_put(mout_mpll);
-err_mout_mpll:
- clk_put(moutcore);
-err_moutcore:
- clk_put(cpu_clk);
-
- pr_err("%s: failed initialization\n", __func__);
- return -EINVAL;
-}
--
1.6.6.rc2
^ permalink raw reply related
* [PATCH v2 6/7] ARM: Exynos: switch to using generic cpufreq-cpu0 driver
From: Thomas Abraham @ 2014-01-18 12:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390047057-2239-1-git-send-email-thomas.ab@samsung.com>
From: Thomas Abraham <thomas.ab@samsung.com>
Remove the platform device instantiation for Exynos specific cpufreq
driver and add the platform device for cpufreq-cpu0 driver.
Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
arch/arm/mach-exynos/common.c | 5 -----
arch/arm/mach-exynos/common.h | 1 -
arch/arm/mach-exynos/mach-exynos4-dt.c | 2 +-
arch/arm/mach-exynos/mach-exynos5-dt.c | 2 +-
4 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index f18be40..72ae5d3 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -303,11 +303,6 @@ void __init exynos_cpuidle_init(void)
platform_device_register(&exynos_cpuidle);
}
-void __init exynos_cpufreq_init(void)
-{
- platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
-}
-
void __init exynos_init_late(void)
{
if (of_machine_is_compatible("samsung,exynos5440"))
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index f76967b..0c31b34 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -22,7 +22,6 @@ void exynos_init_io(void);
void exynos4_restart(enum reboot_mode mode, const char *cmd);
void exynos5_restart(enum reboot_mode mode, const char *cmd);
void exynos_cpuidle_init(void);
-void exynos_cpufreq_init(void);
void exynos_init_late(void);
void exynos_firmware_init(void);
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index d3e54b7..9a25320 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -22,8 +22,8 @@
static void __init exynos4_dt_machine_init(void)
{
exynos_cpuidle_init();
- exynos_cpufreq_init();
+ platform_device_register_simple("cpufreq-cpu0", -1, NULL, 0);
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index 37ea261..9dc3710 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -44,8 +44,8 @@ static void __init exynos5_dt_machine_init(void)
}
exynos_cpuidle_init();
- exynos_cpufreq_init();
+ platform_device_register_simple("cpufreq-cpu0", -1, NULL, 0);
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
--
1.6.6.rc2
^ permalink raw reply related
* [PATCH v2 5/7] clk: exynos: use cpu-clock provider type to represent arm clock
From: Thomas Abraham @ 2014-01-18 12:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390047057-2239-1-git-send-email-thomas.ab@samsung.com>
From: Thomas Abraham <thomas.ab@samsung.com>
With the addition of the new Samsung specific cpu-clock type, the
arm clock can be represented as a cpu-clock type and the independent
clock blocks that made up the arm clock can be removed.
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
.../devicetree/bindings/clock/exynos5250-clock.txt | 1 +
drivers/clk/samsung/clk-exynos4.c | 11 +++++------
drivers/clk/samsung/clk-exynos5250.c | 8 ++++----
include/dt-bindings/clock/exynos5250.h | 1 +
4 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
index 99eae9c..acf867a 100644
--- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
@@ -38,6 +38,7 @@ clock which they consume.
----------------------------
fin_pll 1
+ armclk 12
[Clock Gate for Special Clocks]
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 010f071..efcf4a3 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -437,8 +437,6 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
/* list of divider clocks supported in all exynos4 soc's */
static struct samsung_div_clock exynos4_div_clks[] __initdata = {
- DIV(0, "div_core", "mout_core", DIV_CPU0, 0, 3),
- DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
DIV(0, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
DIV(0, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4),
DIV(0, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4),
@@ -484,8 +482,8 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
DIV(0, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
DIV(0, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
DIV(0, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
- DIV(CLK_ARM_CLK, "arm_clk", "div_core2", DIV_CPU0, 28, 3),
- DIV(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
+ DIV_F(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3,
+ CLK_GET_RATE_NOCACHE, 0),
DIV_F(0, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
CLK_SET_RATE_PARENT, 0),
DIV_F(0, "div_mmc_pre0", "div_mmc0", DIV_FSYS1, 8, 8,
@@ -870,7 +868,6 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
static struct samsung_clock_alias exynos4_aliases[] __initdata = {
ALIAS(CLK_MOUT_CORE, NULL, "moutcore"),
- ALIAS(CLK_ARM_CLK, NULL, "armclk"),
ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"),
};
@@ -1125,12 +1122,14 @@ static void __init exynos4_clk_init(struct device_node *np,
samsung_clk_register_alias(exynos4_aliases,
ARRAY_SIZE(exynos4_aliases));
+ samsung_register_arm_clock(np, CLK_ARM_CLK, "mout_apll", reg_base);
+
pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
"\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n",
exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
_get_rate("sclk_apll"), _get_rate("sclk_mpll"),
_get_rate("sclk_epll"), _get_rate("sclk_vpll"),
- _get_rate("arm_clk"));
+ _get_rate("armclk"));
}
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index ff4beeb..487be36 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -298,9 +298,8 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
/*
* CMU_CPU
*/
- DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
- DIV(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3),
- DIV_A(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3, "armclk"),
+ DIV_F(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3,
+ CLK_GET_RATE_NOCACHE, 0),
/*
* CMU_TOP
@@ -684,8 +683,9 @@ static void __init exynos5250_clk_init(struct device_node *np)
ARRAY_SIZE(exynos5250_div_clks));
samsung_clk_register_gate(exynos5250_gate_clks,
ARRAY_SIZE(exynos5250_gate_clks));
+ samsung_register_arm_clock(np, CLK_ARM_CLK, "mout_apll", reg_base);
pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
- _get_rate("div_arm2"));
+ _get_rate("armclk"));
}
CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
diff --git a/include/dt-bindings/clock/exynos5250.h b/include/dt-bindings/clock/exynos5250.h
index 922f2dc..59a10fb 100644
--- a/include/dt-bindings/clock/exynos5250.h
+++ b/include/dt-bindings/clock/exynos5250.h
@@ -21,6 +21,7 @@
#define CLK_FOUT_CPLL 6
#define CLK_FOUT_EPLL 7
#define CLK_FOUT_VPLL 8
+#define CLK_ARM_CLK 12
/* gate for special clocks (sclk) */
#define CLK_SCLK_CAM_BAYER 128
--
1.6.6.rc2
^ permalink raw reply related
* [PATCH v2 4/7] ARM: dts: Exynos: add cpu nodes, opp and cpu clock frequency table
From: Thomas Abraham @ 2014-01-18 12:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390047057-2239-1-git-send-email-thomas.ab@samsung.com>
From: Thomas Abraham <thomas.ab@samsung.com>
For all Exynos based platforms, add CPU nodes, operating points and cpu
clock frequency table for migrating from Exynos specific cpufreq driver
to using generic cpufreq-cpu0 driver.
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
arch/arm/boot/dts/exynos4210-origen.dts | 6 +++
arch/arm/boot/dts/exynos4210-trats.dts | 6 +++
arch/arm/boot/dts/exynos4210-universal_c210.dts | 6 +++
arch/arm/boot/dts/exynos4210.dtsi | 35 ++++++++++++++++++
arch/arm/boot/dts/exynos4212.dtsi | 17 +++++++++
arch/arm/boot/dts/exynos4412-odroidx.dts | 6 +++
arch/arm/boot/dts/exynos4412-origen.dts | 6 +++
arch/arm/boot/dts/exynos4412-trats2.dts | 6 +++
arch/arm/boot/dts/exynos4412.dtsi | 30 ++++++++++++++++
arch/arm/boot/dts/exynos4x12.dtsi | 35 ++++++++++++++++++
arch/arm/boot/dts/exynos5250-arndale.dts | 6 +++
arch/arm/boot/dts/exynos5250-cros-common.dtsi | 6 +++
arch/arm/boot/dts/exynos5250-smdk5250.dts | 6 +++
arch/arm/boot/dts/exynos5250.dtsi | 43 ++++++++++++++++++++++-
14 files changed, 213 insertions(+), 1 deletions(-)
diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts
index 2aa13cb..dd17e93 100644
--- a/arch/arm/boot/dts/exynos4210-origen.dts
+++ b/arch/arm/boot/dts/exynos4210-origen.dts
@@ -32,6 +32,12 @@
bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
};
+ cpus {
+ cpu at 0 {
+ cpu0-supply = <&buck1_reg>;
+ };
+ };
+
regulators {
compatible = "simple-bus";
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index 63cc571..25487d7 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -30,6 +30,12 @@
bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rootwait earlyprintk panic=5";
};
+ cpus {
+ cpu: cpu at 0 {
+ cpu0-supply = <&varm_breg>;
+ };
+ };
+
regulators {
compatible = "simple-bus";
diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts b/arch/arm/boot/dts/exynos4210-universal_c210.dts
index d2e3f5f..74d5a70 100644
--- a/arch/arm/boot/dts/exynos4210-universal_c210.dts
+++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts
@@ -28,6 +28,12 @@
bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rw rootwait earlyprintk panic=5 maxcpus=1";
};
+ cpus {
+ cpu: cpu at 0 {
+ cpu0-supply = <&vdd_arm_reg>;
+ };
+ };
+
mct at 10050000 {
compatible = "none";
};
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 48ecd7a..40cd663 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -36,6 +36,34 @@
reg = <0x10023CA0 0x20>;
};
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu at 0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ clocks = <&clock 12>;
+ clock-names = "cpu";
+
+ operating-points = <
+ 200000 950000
+ 400000 975000
+ 500000 975000
+ 800000 1075000
+ 1000000 1150000
+ 1200000 1250000
+ >;
+ safe-opp = <800000 1075000>;
+ };
+
+ cpu at 1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <1>;
+ };
+ };
+
gic: interrupt-controller at 10490000 {
cpu-offset = <0x8000>;
};
@@ -73,6 +101,13 @@
compatible = "samsung,exynos4210-clock";
reg = <0x10030000 0x20000>;
#clock-cells = <1>;
+
+ arm-frequency-table = <1200000 1200000 0 3 7 3 4 1 7 0 5 0 0>,
+ <1000000 1000000 0 3 7 3 4 1 7 0 4 0 0>,
+ < 800000 800000 0 3 7 3 3 1 7 0 3 0 0>,
+ < 500000 500000 0 3 7 3 3 1 7 0 3 0 0>,
+ < 400000 400000 0 3 7 3 3 1 7 0 3 0 0>,
+ < 200000 200000 0 1 3 1 1 1 0 0 3 0 0>;
};
pmu {
diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi
index 94a43f9..2ea0f83 100644
--- a/arch/arm/boot/dts/exynos4212.dtsi
+++ b/arch/arm/boot/dts/exynos4212.dtsi
@@ -22,6 +22,23 @@
/ {
compatible = "samsung,exynos4212";
+ clock: clock-controller at 10030000 {
+ arm-frequency-table = <1500000 1500000 0 3 7 0 6 1 2 0 6 2 0>,
+ <1400000 1400000 0 3 7 0 6 1 2 0 6 2 0>,
+ <1300000 1300000 0 3 7 0 5 1 2 0 5 2 0>,
+ <1200000 1200000 0 3 7 0 5 1 2 0 5 2 0>,
+ <1100000 1100000 0 3 6 0 4 1 2 0 4 2 0>,
+ <1000000 1000000 0 2 5 0 4 1 1 0 4 2 0>,
+ < 900000 900000 0 2 5 0 3 1 1 0 3 2 0>,
+ < 800000 800000 0 2 5 0 3 1 1 0 3 2 0>,
+ < 700000 700000 0 2 4 0 3 1 1 0 3 2 0>,
+ < 600000 600000 0 2 4 0 3 1 1 0 3 2 0>,
+ < 500000 500000 0 2 4 0 3 1 1 0 3 2 0>,
+ < 400000 400000 0 2 4 0 3 1 1 0 3 2 0>,
+ < 300000 300000 0 2 4 0 2 1 1 0 3 2 0>,
+ < 200000 200000 0 1 3 0 1 1 1 0 3 2 0>;
+ };
+
gic: interrupt-controller at 10490000 {
cpu-offset = <0x8000>;
};
diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts
index 12459b0..1c751f9 100644
--- a/arch/arm/boot/dts/exynos4412-odroidx.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidx.dts
@@ -22,6 +22,12 @@
reg = <0x40000000 0x40000000>;
};
+ cpus {
+ cpu at 0 {
+ cpu0-supply = <&buck2_reg>;
+ };
+ };
+
leds {
compatible = "gpio-leds";
led1 {
diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts
index 388f035..36080e5 100644
--- a/arch/arm/boot/dts/exynos4412-origen.dts
+++ b/arch/arm/boot/dts/exynos4412-origen.dts
@@ -27,6 +27,12 @@
bootargs ="console=ttySAC2,115200";
};
+ cpus {
+ cpu at 0 {
+ cpu0-supply = <&buck2_reg>;
+ };
+ };
+
firmware at 0203F000 {
compatible = "samsung,secure-firmware";
reg = <0x0203F000 0x1000>;
diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts
index 4f851cc..4a4d446 100644
--- a/arch/arm/boot/dts/exynos4412-trats2.dts
+++ b/arch/arm/boot/dts/exynos4412-trats2.dts
@@ -31,6 +31,12 @@
bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rootwait earlyprintk panic=5";
};
+ cpus {
+ cpu at 0 {
+ cpu0-supply = <&buck2_reg>;
+ };
+ };
+
firmware at 0204F000 {
compatible = "samsung,secure-firmware";
reg = <0x0204F000 0x1000>;
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
index 87b339c..7e9eca7 100644
--- a/arch/arm/boot/dts/exynos4412.dtsi
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -22,6 +22,36 @@
/ {
compatible = "samsung,exynos4412";
+ cpus {
+ cpu at 2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <2>;
+ };
+ cpu at 3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <3>;
+ };
+ };
+
+ clock: clock-controller at 10030000 {
+ arm-frequency-table = <1500000 1500000 0 3 7 0 6 1 2 0 6 0 7>,
+ <1400000 1400000 0 3 7 0 6 1 2 0 6 0 6>,
+ <1300000 1300000 0 3 7 0 5 1 2 0 5 0 6>,
+ <1200000 1200000 0 3 7 0 5 1 2 0 5 0 5>,
+ <1100000 1100000 0 3 6 0 4 1 2 0 4 0 5>,
+ <1000000 1000000 0 2 5 0 4 1 1 0 4 0 4>,
+ < 900000 900000 0 2 5 0 3 1 1 0 3 0 4>,
+ < 800000 800000 0 2 5 0 3 1 1 0 3 0 3>,
+ < 700000 700000 0 2 4 0 3 1 1 0 3 0 3>,
+ < 600000 600000 0 2 4 0 3 1 1 0 3 0 2>,
+ < 500000 500000 0 2 4 0 3 1 1 0 3 0 2>,
+ < 400000 400000 0 2 4 0 3 1 1 0 3 0 1>,
+ < 300000 300000 0 2 4 0 2 1 1 0 3 0 1>,
+ < 200000 200000 0 1 3 0 1 1 1 0 3 0 0>;
+ };
+
gic: interrupt-controller at 10490000 {
cpu-offset = <0x4000>;
};
diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi
index 5c412aa..47e2195 100644
--- a/arch/arm/boot/dts/exynos4x12.dtsi
+++ b/arch/arm/boot/dts/exynos4x12.dtsi
@@ -31,6 +31,41 @@
mshc0 = &mshc_0;
};
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu at 0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ clocks = <&clock 12>;
+ clock-names = "cpu";
+
+ operating-points = <
+ 1400000 1350000
+ 1300000 1287500
+ 1200000 1250000
+ 1100000 1187500
+ 1000000 1137500
+ 900000 1087500
+ 800000 1037500
+ 700000 1000000
+ 600000 987500
+ 500000 950000
+ 400000 925000
+ 300000 900000
+ 200000 900000
+ >;
+ clock-latency = <200000>;
+ safe-opp = <800000 1037500>;
+ };
+ cpu at 1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <1>;
+ };
+ };
+
pd_isp: isp-power-domain at 10023CA0 {
compatible = "samsung,exynos4210-pd";
reg = <0x10023CA0 0x20>;
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts
index b42e658..4716eef 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -25,6 +25,12 @@
bootargs = "console=ttySAC2,115200";
};
+ cpus {
+ cpu at 0 {
+ cpu0-supply = <&buck2_reg>;
+ };
+ };
+
codec at 11000000 {
samsung,mfc-r = <0x43000000 0x800000>;
samsung,mfc-l = <0x51000000 0x800000>;
diff --git a/arch/arm/boot/dts/exynos5250-cros-common.dtsi b/arch/arm/boot/dts/exynos5250-cros-common.dtsi
index 2c1560d..4bde756 100644
--- a/arch/arm/boot/dts/exynos5250-cros-common.dtsi
+++ b/arch/arm/boot/dts/exynos5250-cros-common.dtsi
@@ -19,6 +19,12 @@
chosen {
};
+ cpus {
+ cpu at 0 {
+ cpu0-supply = <&buck2_reg>;
+ };
+ };
+
pinctrl at 11400000 {
/*
* Disabled pullups since external part has its own pullups and
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index 5c1b7d9..7c228e2 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -27,6 +27,12 @@
bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
};
+ cpus {
+ cpu at 0 {
+ cpu0-supply = <&buck2_reg>;
+ };
+ };
+
i2c at 12C60000 {
samsung,i2c-sda-delay = <100>;
samsung,i2c-max-bus-freq = <20000>;
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index b7dec41..d2f98dc 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -61,6 +61,30 @@
compatible = "arm,cortex-a15";
reg = <0>;
clock-frequency = <1700000000>;
+
+ clocks = <&clock 12>;
+ clock-names = "cpu";
+
+ operating-points = <
+ 1700000 1300000
+ 1600000 1250000
+ 1500000 1225000
+ 1400000 1200000
+ 1300000 1150000
+ 1200000 1125000
+ 1100000 1100000
+ 1000000 1075000
+ 900000 1050000
+ 800000 1025000
+ 700000 1012500
+ 600000 1000000
+ 500000 975000
+ 400000 950000
+ 300000 937500
+ 200000 925000
+ >;
+ clock-latency = <200000>;
+ safe-opp = <800000 1025000>;
};
cpu at 1 {
device_type = "cpu";
@@ -84,7 +108,24 @@
compatible = "samsung,exynos5250-clock";
reg = <0x10010000 0x30000>;
#clock-cells = <1>;
- };
+
+ arm-frequency-table = <1700000 1700000 0 3 7 7 7 3 5 0 0 2 0>,
+ <1600000 1600000 0 3 7 7 7 1 4 0 0 2 0>,
+ <1500000 1500000 0 2 7 7 7 1 4 0 0 2 0>,
+ <1400000 1400000 0 2 7 7 6 1 4 0 0 2 0>,
+ <1300000 1300000 0 2 7 7 6 1 3 0 0 2 0>,
+ <1200000 1200000 0 2 7 7 5 1 3 0 0 2 0>,
+ <1100000 1100000 0 3 7 7 5 1 3 0 0 2 0>,
+ <1000000 1000000 0 1 7 7 4 1 2 0 0 2 0>,
+ < 900000 900000 0 1 7 7 4 1 2 0 0 2 0>,
+ < 800000 800000 0 1 7 7 4 1 2 0 0 2 0>,
+ < 700000 700000 0 1 7 7 3 1 1 0 0 2 0>,
+ < 600000 600000 0 1 7 7 3 1 1 0 0 2 0>,
+ < 500000 500000 0 1 7 7 2 1 1 0 0 2 0>,
+ < 400000 400000 0 1 7 7 2 1 1 0 0 2 0>,
+ < 300000 300000 0 1 7 7 1 1 1 0 0 2 0>,
+ < 200000 200000 0 1 7 7 1 1 1 0 0 2 0>;
+ };
clock_audss: audss-clock-controller at 3810000 {
compatible = "samsung,exynos5250-audss-clock";
--
1.6.6.rc2
^ permalink raw reply related
* [PATCH v2 3/7] devicetree: bindings: add cpu clock configuration data binding for Exynos4/5
From: Thomas Abraham @ 2014-01-18 12:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390047057-2239-1-git-send-email-thomas.ab@samsung.com>
From: Thomas Abraham <thomas.ab@samsung.com>
The clk ops of the new Samsung cpu clock provider type requires configuration
data that will be programmed in the multiple clock blocks encapsulated within
the cpu clock provider type. This configuration data is held in the clock
controller node. Update clock binding documentation about this configuration
data format for Samsung Exynos4 and Exynos5 platforms.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Tomasz Figa <t.figa@samsung.com>
Cc: <devicetree@vger.kernel.org>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
.../devicetree/bindings/clock/exynos4-clock.txt | 30 ++++++++++++++++++++
.../devicetree/bindings/clock/exynos5250-clock.txt | 21 ++++++++++++++
2 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
index a2ac2d9..c28aabd 100644
--- a/Documentation/devicetree/bindings/clock/exynos4-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
@@ -15,6 +15,29 @@ Required Properties:
- #clock-cells: should be 1.
+- arm-frequency-table: defines the list of arm clock speeds supported and
+ the associated configuration values required to setup the clock controller
+ for generating those speeds. The format of each entry included in the
+ arm-frequency-table should be as defined below (#cells per entry = 13)
+
+ - for Exynos4210 and Exynos4212 based platforms:
+ cell #1: arm clock frequency
+ cell #2: expected arm clock parent frequency
+ cell #3 ~ cell 12#: value of clock divider in the following order
+ core_ratio, corem0_ratio, corem1_ratio, periph_ratio,
+ atb_ratio, pclk_dbg_ratio, apll_ratio, core2_ratio,
+ copy_ratio, hpm_ratio.
+ cell #13: reserved (should be zero).
+
+ - for Exynos4412 based platforms:
+ cell #1: arm clock frequency
+ cell #2: expected arm clock parent frequency
+ cell #3 ~ cell #13: value of clock divider in the following order
+ core_ratio, corem0_ratio, corem1_ratio, periph_ratio,
+ atb_ratio, pclk_dbg_ratio, apll_ratio, core2_ratio,
+ copy_ratio, hpm_ratio, cores_ratio
+
+
The following is the list of clocks generated by the controller. Each clock is
assigned an identifier and client nodes use this identifier to specify the
clock which they consume. Some of the clocks are available only on a particular
@@ -275,6 +298,13 @@ Example 1: An example of a clock controller node is listed below.
compatible = "samsung,exynos4210-clock";
reg = <0x10030000 0x20000>;
#clock-cells = <1>;
+
+ arm-frequency-table = <1200000 1200000 0 3 7 3 4 1 7 0 5 0>,
+ <1000000 1000000 0 3 7 3 4 1 7 0 4 0>,
+ < 800000 800000 0 3 7 3 3 1 7 0 3 0>,
+ < 500000 500000 0 3 7 3 3 1 7 0 3 0>,
+ < 400000 400000 0 3 7 3 3 1 7 0 3 0>,
+ < 200000 200000 0 1 3 1 1 1 0 0 3 0>;
};
Example 2: UART controller node that consumes the clock generated by the clock
diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
index 72ce617..99eae9c 100644
--- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
@@ -13,6 +13,20 @@ Required Properties:
- #clock-cells: should be 1.
+- arm-frequency-table: defines the list of arm clock speeds supported and
+ the associated configuration values required to setup the clock controller
+ for generating those speeds. The format of each entry included in the
+ arm-frequency-table should be as defined below (#cells per entry = 13)
+
+ cell #1: arm clock frequency
+ cell #2: expected arm clock parent frequency
+ cell #3 ~ cell #12: value of clock divider in the following order
+ arm_ratio, cpud_ratio, acp_ratio, periph_ratio,
+ atb_ratio, pclk_dbg_ratio, apll_ratio, arm2_ratio,
+ copy_ratio, hpm_ratio
+ cell #13: reserved (should be zero)
+
+
The following is the list of clocks generated by the controller. Each clock is
assigned an identifier and client nodes use this identifier to specify the
clock which they consume.
@@ -177,6 +191,13 @@ Example 1: An example of a clock controller node is listed below.
compatible = "samsung,exynos5250-clock";
reg = <0x10010000 0x30000>;
#clock-cells = <1>;
+
+ arm-frequency-table = <1700000 1700000 0 3 7 7 7 3 5 0 0 2>,
+ <1600000 1600000 0 3 7 7 7 1 4 0 0 2>,
+ <1500000 1500000 0 2 7 7 7 1 4 0 0 2>,
+ <1400000 1400000 0 2 7 7 6 1 4 0 0 2>,
+ <1300000 1300000 0 2 7 7 6 1 3 0 0 2>,
+ <1200000 1200000 0 2 7 7 5 1 3 0 0 2>;
};
Example 2: UART controller node that consumes the clock generated by the clock
--
1.6.6.rc2
^ permalink raw reply related
* [PATCH v2 2/7] clk: samsung: add infrastructure to register cpu clocks
From: Thomas Abraham @ 2014-01-18 12:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390047057-2239-1-git-send-email-thomas.ab@samsung.com>
From: Thomas Abraham <thomas.ab@samsung.com>
The CPU clock provider supplies the clock to the CPU clock domain. The
composition and organization of the CPU clock provider could vary among
Exynos SoCs. A CPU clock provider can be composed of clock mux, dividers
and gates. This patch defines a new clock type for CPU clock provider and
adds infrastructure to register the CPU clock providers for Samsung
platforms.
In addition to this, the arm cpu clock provider for Exynos4210 and
compatible SoCs is instantiated using the new cpu clock type. The clock
frequency table and the clock configuration data for this clock is
obtained from device tree. This implementation is reusable for Exynos4x12
and Exynos5250 SoCs as well.
Cc: Tomasz Figa <t.figa@samsung.com>
Cc: Lukasz Majewski <l.majewski@majess.pl>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
drivers/clk/samsung/Makefile | 2 +-
drivers/clk/samsung/clk-cpu.c | 345 +++++++++++++++++++++++++++++++++++++++++
drivers/clk/samsung/clk.h | 3 +
3 files changed, 349 insertions(+), 1 deletions(-)
create mode 100644 drivers/clk/samsung/clk-cpu.c
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 8eb4799..e2b453f 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -2,7 +2,7 @@
# Samsung Clock specific Makefile
#
-obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o
+obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o clk-cpu.o
obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c
new file mode 100644
index 0000000..92fba45
--- /dev/null
+++ b/drivers/clk/samsung/clk-cpu.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This file contains the utility functions to register the cpu clocks
+ * for samsung platforms.
+*/
+
+#include <linux/errno.h>
+#include "clk.h"
+
+#define SRC_CPU 0x0
+#define STAT_CPU 0x200
+#define DIV_CPU0 0x300
+#define DIV_CPU1 0x304
+#define DIV_STAT_CPU0 0x400
+#define DIV_STAT_CPU1 0x404
+
+/**
+ * struct samsung_cpuclk_freq_table: table of frequency supported by
+ * a cpu clock and associated data if any.
+ * @freq: points to a table of supported frequencies (in KHz)
+ * @freq_count: number of entries in the frequency table
+ * @data: cpu clock specific data, if any
+ *
+ * This structure holds the frequency options supported by the cpu clock in
+ * which this structure is contained. The data pointer is an optional data
+ * that can provide any additional configuration options for the supported
+ * frequencies. This structure is intended to be reusable for all cpu clocks
+ * in Samsung SoC based platforms
+ */
+struct samsung_cpuclk_freq_table {
+ const unsigned long *freq; /* in KHz */
+ unsigned long freq_count;
+ const void *data;
+};
+
+/**
+ * struct exynos4210_freq_data: format of auxillary data associated with
+ * each frequency supported by the cpu clock for exynos4210.
+ * @parent_freq: The frequency of the parent clock required to generate the
+ * supported cpu clock speed.
+ * @div0: value to be programmed in the div_cpu0 register.
+ * @div1: value to be programmed in the div_cpu1 register.
+ *
+ * This structure holds the auxillary configuration data for each supported
+ * cpu clock frequency on Exynos4210 and compatible SoCs.
+ */
+struct exynos4210_freq_data {
+ unsigned long parent_freq;
+ unsigned int div0;
+ unsigned int div1;
+};
+
+/**
+ * struct samsung_cpuclk: information about clock supplied to a CPU core.
+ * @hw: handle between ccf and cpu clock.
+ * @ctrl_base: base address of the clock controller.
+ * @offset: offset from the ctrl_base address where the cpu clock div/mux
+ * registers can be accessed.
+ * @parent: clock handle representing the clock output of the parent clock.
+ * @freq_table: the frequency table supported by this cpu clock.
+ */
+struct samsung_cpuclk {
+ struct clk_hw hw;
+ void __iomem *ctrl_base;
+ unsigned long offset;
+ struct clk *parent;
+ const struct samsung_cpuclk_freq_table *freq_table;
+};
+
+#define to_samsung_cpuclk(hw) container_of(hw, struct samsung_cpuclk, hw)
+
+/**
+ * struct samsung_cpuclk_match_data: soc specific data for cpu clocks.
+ * @parser: pointer to a function that can parse SoC specific cpu clock
+ * frequency and associated configuration data.
+ * @offset: optional offset from base of clock controller register base,
+ * to be used when accessing clock controller registers related to the
+ * cpu clock.
+ * @offset: offset from the ctrl_base address where the cpu clock div/mux
+ * registers can be accessed.
+ */
+struct samsung_cpuclk_match_data {
+ int (*parser)(struct device_node *,
+ struct samsung_cpuclk_freq_table **);
+ unsigned int offset;
+};
+
+/* This is a helper function to perform clock rounding for cpu clocks. */
+static long samsung_cpuclk_round_rate(struct clk_hw *hw,
+ unsigned long drate, unsigned long *prate)
+{
+ struct samsung_cpuclk *cpuclk = to_samsung_cpuclk(hw);
+ const struct samsung_cpuclk_freq_table *freq_tbl;
+ int i;
+
+ freq_tbl = cpuclk->freq_table;
+ drate /= 1000;
+
+ for (i = 0; i < freq_tbl->freq_count; i++) {
+ if (drate >= freq_tbl->freq[i])
+ return freq_tbl->freq[i] * 1000;
+ }
+ return freq_tbl->freq[i - 1] * 1000;
+}
+
+#define EXYNOS4210_ARM_DIV1(base) ((readl(base + DIV_CPU0) & 0xf) + 1)
+#define EXYNOS4210_ARM_DIV2(base) (((readl(base + DIV_CPU0) >> 28) & 0xf) + 1)
+
+/*
+ * CPU clock speed for Exynos4210 and compatible SoCs is
+ * parent clock speed / core1_ratio / core2_ratio
+ */
+static unsigned long exynos4210_armclk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct samsung_cpuclk *armclk = to_samsung_cpuclk(hw);
+ void __iomem *base = armclk->ctrl_base + armclk->offset;
+
+ return parent_rate / EXYNOS4210_ARM_DIV1(base) /
+ EXYNOS4210_ARM_DIV2(base);
+}
+
+/* set rate callback for cpuclk type on Exynos4210 and similar SoCs */
+static int exynos4210_armclk_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct samsung_cpuclk *armclk = to_samsung_cpuclk(hw);
+ const struct samsung_cpuclk_freq_table *freq_tbl;
+ const struct exynos4210_freq_data *freq_data;
+ unsigned long mux_reg, idx;
+ void __iomem *base;
+
+ if (drate == prate)
+ return 0;
+
+ freq_tbl = armclk->freq_table;
+ freq_data = freq_tbl->data;
+ base = armclk->ctrl_base + armclk->offset;
+
+ for (idx = 0; idx < freq_tbl->freq_count; idx++, freq_data++)
+ if ((freq_tbl->freq[idx] * 1000) == drate)
+ break;
+
+ if (drate < prate) {
+ mux_reg = readl(base + SRC_CPU);
+ writel(mux_reg | (1 << 16), base + SRC_CPU);
+ while (((readl(base + STAT_CPU) >> 16) & 0x7) != 2)
+ ;
+
+ clk_set_rate(armclk->parent, drate);
+ }
+
+ writel(freq_data->div0, base + DIV_CPU0);
+ while (readl(base + DIV_STAT_CPU0) != 0)
+ ;
+ writel(freq_data->div1, base + DIV_CPU1);
+ while (readl(base + DIV_STAT_CPU1) != 0)
+ ;
+
+ if (drate > prate) {
+ mux_reg = readl(base + SRC_CPU);
+ writel(mux_reg | (1 << 16), base + SRC_CPU);
+ while (((readl(base + STAT_CPU) >> 16) & 0x7) != 2)
+ ;
+
+ clk_set_rate(armclk->parent, freq_data->parent_freq * 1000);
+ }
+
+ mux_reg = readl(base + SRC_CPU);
+ writel(mux_reg & ~(1 << 16), base + SRC_CPU);
+ while (((readl(base + STAT_CPU) >> 16) & 0x7) != 1)
+ ;
+ return 0;
+}
+
+/* clock ops for armclk on Exynos4210 and compatible platforms. */
+static const struct clk_ops exynos4210_armclk_clk_ops = {
+ .recalc_rate = exynos4210_armclk_recalc_rate,
+ .round_rate = samsung_cpuclk_round_rate,
+ .set_rate = exynos4210_armclk_set_rate,
+};
+
+/* helper function to register a cpu clock */
+static void __init samsung_cpuclk_register(unsigned int lookup_id,
+ const char *name, const char *parent, const struct clk_ops *ops,
+ const struct samsung_cpuclk_freq_table *freq_tbl,
+ void __iomem *reg_base,
+ const struct samsung_cpuclk_match_data *data)
+{
+ struct samsung_cpuclk *cpuclk;
+ struct clk_init_data init;
+ struct clk *clk;
+
+ cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
+ if (!cpuclk) {
+ pr_err("%s: could not allocate memory for cpuclk %s\n",
+ __func__, name);
+ return;
+ }
+
+ init.name = name;
+ init.flags = CLK_GET_RATE_NOCACHE;
+ init.parent_names = &parent;
+ init.num_parents = 1;
+ init.ops = ops;
+
+ cpuclk->hw.init = &init;
+ cpuclk->ctrl_base = reg_base;
+ cpuclk->offset = data->offset;
+ cpuclk->freq_table = freq_tbl;
+ cpuclk->parent = __clk_lookup(parent);
+
+ clk = clk_register(NULL, &cpuclk->hw);
+ if (IS_ERR(clk)) {
+ pr_err("%s: could not register cpuclk %s\n", __func__, name);
+ kfree(cpuclk);
+ return;
+ }
+ samsung_clk_add_lookup(clk, lookup_id);
+}
+
+#define EXYNOS4210_DIV_CPU01(d0, d1, d2, d3, d4, d5, d6, d7) \
+ ((d0 << 28) | (d1 << 24) | (d2 << 20) | (d3 << 16) | \
+ (d4 << 12) | (d5 << 8) | (d6 << 4) | (d7 << 0))
+#define EXYNOS4210_DIV_CPU11(d0, d1, d2) \
+ ((d0 << 8) | (d1 << 4) | (d2 << 0))
+#define EXYNOS4210_CFG_LEN 13
+
+/*
+ * parse cpu clock frequency table and auxillary configuration data from dt
+ * for exynos4210 and compatible SoC's.
+ */
+static int exynos4210_armclk_cfg_parser(struct device_node *np,
+ struct samsung_cpuclk_freq_table **tbl)
+{
+ struct samsung_cpuclk_freq_table *freq_tbl;
+ struct exynos4210_freq_data *fdata, *t_fdata;
+ unsigned long *freqs, cfg[EXYNOS4210_CFG_LEN];
+ const struct property *prop;
+ unsigned int tbl_sz, i, j;
+ const __be32 *val;
+ int ret;
+
+ prop = of_find_property(np, "arm-frequency-table", NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -EINVAL;
+ if ((prop->length / sizeof(u32)) % EXYNOS4210_CFG_LEN)
+ return -EINVAL;
+ tbl_sz = (prop->length / sizeof(u32)) / EXYNOS4210_CFG_LEN;
+
+ freq_tbl = kzalloc(sizeof(*freq_tbl), GFP_KERNEL);
+ if (!freq_tbl)
+ return -ENOMEM;
+
+ freqs = kzalloc(sizeof(u32) * tbl_sz, GFP_KERNEL);
+ if (!freqs) {
+ ret = -ENOMEM;
+ goto free_freq_tbl;
+ }
+
+ fdata = kzalloc(sizeof(*fdata) * tbl_sz, GFP_KERNEL);
+ if (!fdata) {
+ ret = -ENOMEM;
+ goto free_freqs;
+ }
+ t_fdata = fdata;
+
+ val = prop->value;
+ for (i = 0; i < tbl_sz; i++, fdata++) {
+ for (j = 0; j < EXYNOS4210_CFG_LEN; j++)
+ cfg[j] = be32_to_cpup(val++);
+ freqs[i] = cfg[0];
+ fdata->parent_freq = cfg[1];
+ fdata->div0 = EXYNOS4210_DIV_CPU01(cfg[9], cfg[8], cfg[7],
+ cfg[6], cfg[5], cfg[4], cfg[3], cfg[2]);
+ fdata->div1 = EXYNOS4210_DIV_CPU11(cfg[12], cfg[11], cfg[10]);
+ }
+
+ freq_tbl->freq = freqs;
+ freq_tbl->freq_count = tbl_sz;
+ freq_tbl->data = t_fdata;
+ *tbl = freq_tbl;
+ return 0;
+
+free_freqs:
+ kfree(freqs);
+free_freq_tbl:
+ kfree(freq_tbl);
+ return ret;
+}
+
+static struct samsung_cpuclk_match_data exynos4210_cpuclk_match_data = {
+ .parser = exynos4210_armclk_cfg_parser,
+ .offset = 0x14200,
+};
+
+static struct samsung_cpuclk_match_data exynos5250_cpuclk_match_data = {
+ .parser = exynos4210_armclk_cfg_parser,
+ .offset = 0x200,
+};
+
+static const struct of_device_id samsung_clock_ids[] = {
+ { .compatible = "samsung,exynos4210-clock",
+ .data = &exynos4210_cpuclk_match_data, },
+ { .compatible = "samsung,exynos4412-clock",
+ .data = &exynos4210_cpuclk_match_data, },
+ { .compatible = "samsung,exynos5250-clock",
+ .data = &exynos5250_cpuclk_match_data, },
+};
+
+int __init samsung_register_arm_clock(struct device_node *np,
+ unsigned int lookup_id, const char *parent, void __iomem *base)
+{
+ const struct of_device_id *match;
+ struct samsung_cpuclk_freq_table *freq_table;
+ const struct samsung_cpuclk_match_data *data;
+ int ret;
+
+ match = of_match_node(samsung_clock_ids, np);
+ if (!match) {
+ pr_err("%s: could not determine soc type\n", __func__);
+ return -EINVAL;
+ }
+
+ data = match->data;
+ ret = data->parser(np, &freq_table);
+ if (ret) {
+ pr_err("%s: error %d in parsing arm clock freq table",
+ __func__, ret);
+ return -EINVAL;
+ }
+
+ samsung_cpuclk_register(lookup_id, "armclk", parent,
+ &exynos4210_armclk_clk_ops, freq_table, base, data);
+
+ return 0;
+}
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 31b4174..a759330 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -340,4 +340,7 @@ extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list,
extern unsigned long _get_rate(const char *clk_name);
+extern int __init samsung_register_arm_clock(struct device_node *np,
+ unsigned int lookup_id, const char *parent, void __iomem *base);
+
#endif /* __SAMSUNG_CLK_H */
--
1.6.6.rc2
^ permalink raw reply related
* [PATCH v2 1/7] cpufreq: cpufreq-cpu0: allow optional safe voltage during frequency transitions
From: Thomas Abraham @ 2014-01-18 12:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390047057-2239-1-git-send-email-thomas.ab@samsung.com>
From: Thomas Abraham <thomas.ab@samsung.com>
On some platforms such as the Samsung Exynos, changing the frequency
of the CPU clock requires changing the frequency of the PLL that is
supplying the CPU clock. To change the frequency of the PLL, the CPU
clock is temporarily reparented to another parent clock.
The clock frequency of this temporary parent clock could be much higher
than the clock frequency of the PLL at the time of reparenting. Due
to the temporary increase in the CPU clock speed, the CPU (and any other
components in the CPU clock domain such as dividers, mux, etc.) have to
to be operated at a higher voltage level, called the safe voltage level.
This patch adds optional support to temporarily switch to a safe voltage
level during CPU frequency transitions.
Cc: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
.../devicetree/bindings/cpufreq/cpufreq-cpu0.txt | 7 ++++
drivers/cpufreq/cpufreq-cpu0.c | 37 +++++++++++++++++--
2 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
index f055515..37453ab 100644
--- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
@@ -19,6 +19,12 @@ Optional properties:
- cooling-min-level:
- cooling-max-level:
Please refer to Documentation/devicetree/bindings/thermal/thermal.txt.
+- safe-opp: Certain platforms require that during a opp transition,
+ a system should not go below a particular opp level. For such systems,
+ this property specifies the minimum opp to be maintained during the
+ opp transitions. The safe-opp value is a tuple with first element
+ representing the safe frequency and the second element representing the
+ safe voltage.
Examples:
@@ -36,6 +42,7 @@ cpus {
396000 950000
198000 850000
>;
+ safe-opp = <396000 950000>
clock-latency = <61036>; /* two CLK32 periods */
#cooling-cells = <2>;
cooling-min-level = <0>;
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index 0c12ffc..075d3d1 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -27,6 +27,8 @@
static unsigned int transition_latency;
static unsigned int voltage_tolerance; /* in percentage */
+static unsigned long safe_frequency;
+static unsigned long safe_voltage;
static struct device *cpu_dev;
static struct clk *cpu_clk;
@@ -64,17 +66,30 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
volt_old = regulator_get_voltage(cpu_reg);
}
- pr_debug("%u MHz, %ld mV --> %u MHz, %ld mV\n",
+ pr_debug("\n\n%u MHz, %ld mV --> %u MHz, %ld mV\n",
old_freq / 1000, volt_old ? volt_old / 1000 : -1,
new_freq / 1000, volt ? volt / 1000 : -1);
/* scaling up? scale voltage before frequency */
- if (!IS_ERR(cpu_reg) && new_freq > old_freq) {
+ if (!IS_ERR(cpu_reg) && new_freq > old_freq &&
+ new_freq >= safe_frequency) {
ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
if (ret) {
pr_err("failed to scale voltage up: %d\n", ret);
return ret;
}
+ } else if (!IS_ERR(cpu_reg) && old_freq < safe_frequency) {
+ /*
+ * the scaled up voltage level for the new_freq is lower
+ * than the safe voltage level. so set safe_voltage
+ * as the intermediate voltage level and revert it
+ * back after the frequency has been changed.
+ */
+ ret = regulator_set_voltage_tol(cpu_reg, safe_voltage, tol);
+ if (ret) {
+ pr_err("failed to set safe voltage: %d\n", ret);
+ return ret;
+ }
}
ret = clk_set_rate(cpu_clk, freq_exact);
@@ -86,7 +101,8 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
}
/* scaling down? scale voltage after frequency */
- if (!IS_ERR(cpu_reg) && new_freq < old_freq) {
+ if (!IS_ERR(cpu_reg) &&
+ (new_freq < old_freq || new_freq < safe_frequency)) {
ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
if (ret) {
pr_err("failed to scale voltage down: %d\n", ret);
@@ -116,6 +132,8 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
static int cpu0_cpufreq_probe(struct platform_device *pdev)
{
+ const struct property *prop;
+ struct dev_pm_opp *opp;
struct device_node *np;
int ret;
@@ -165,13 +183,24 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
goto out_put_node;
}
+ prop = of_find_property(np, "safe-opp", NULL);
+ if (prop) {
+ if (prop->value && (prop->length / sizeof(u32)) == 2) {
+ const __be32 *val;
+ val = prop->value;
+ safe_frequency = be32_to_cpup(val++);
+ safe_voltage = be32_to_cpup(val);
+ } else {
+ pr_err("invalid safe-opp level specified\n");
+ }
+ }
+
of_property_read_u32(np, "voltage-tolerance", &voltage_tolerance);
if (of_property_read_u32(np, "clock-latency", &transition_latency))
transition_latency = CPUFREQ_ETERNAL;
if (!IS_ERR(cpu_reg)) {
- struct dev_pm_opp *opp;
unsigned long min_uV, max_uV;
int i;
--
1.6.6.rc2
^ permalink raw reply related
* [PATCH v2 0/7] cpufreq: use cpufreq-cpu0 driver for exynos based platforms
From: Thomas Abraham @ 2014-01-18 12:10 UTC (permalink / raw)
To: linux-arm-kernel
Changes since v1:
- Removes Exynos4x12 and Exynos5250 cpufreq driver also.
- Device tree based clock configuration lookup as suggested by Lukasz
Majewski and Tomasz Figa.
- safe operating point binding reworked as suggested by Shawn Guo.
The patch series removes the use of Exynos specific cpufreq driver and enables
the use of cpufreq-cpu0 driver for Exynos4210, Exynos4x12 and Exynos5250 based
platforms. This is being done for few reasons.
(a) The Exynos cpufreq driver reads/writes clock controller registers
bypassing the Exynos CCF driver which is sort of problematic.
(b) Removes the need for having clock controller register definitions
in the cpufreq driver and also removes the need for statically
io-remapping clock controller address space (helps in moving towards
multiplatform kernel).
In order to use cpufreq-cpu0 driver and provide fast cpu clock switching
during dvfs operations, the following apporach has been used.
(a) A new CPU clock provider type has been introduced in Samsung's CCF
support. This clock provider type can be a compostion of multiple
clock blocks such as mux, dividers and gates. Typically, in Exynos
platforms, there are multiple clock blocks in between the output
of the APLL and the CPU clock domain output. Representing these
mutiple clock blocks within a opaque CPU clock provider type helps
in reducing the time taken to perform a CPU clock frequency change
operation, which is generally required during DVFS operations.
This approach was suggested by Arnd Bergmann <arnd@arndb.de> during
LCE-2013.
(b) A new optional safe operating point property has been introduced
in the cpufreq-cpu0 driver binding. On some platforms such as the
Samsung Exynos, a change in CPU frequency requires a change in the
PLL output that drives the CPU clock. A change in PLL output
requires the PLL output be turned off, which implies that the CPU
(and other components in the CPU clock domain) be supplied with
an alternate clock source during the time the PLL output is changed.
The clock speed of this alternate clock source could be higher
than the clock speed of the PLL at the time of switching over to
the alternate clock source. This temporary increase in clock speed
of the CPU clock domain implies that the blocks within the CPU
clock domain should also be supplied with an appropriate voltage
supply level as required to drive the CPU clock domain components
at the speed of the alternative clock source. This temporary
voltage level required during switching of CPU clock speed is
called safe voltage level. And the cpufreq-cpu0 driver has been
modified to setup the safe voltage levels during the changes
in CPU clock speed.
(c) The CPU clock supply as been restructured as
[ Output of APLL -> Opaque CPU clock provider -> CPU clock output ]
And with the changes in (a) and (b) above, the cpufreq-cpu0 driver
can now be used and can remove the use of Exynos specific
cpufreq driver.
This patch series is tested on the following platforms.
- Exynos4210 based Insignal Origen board.
- Exynos4412 based Insignal Origen Quad board.
- Exynos5250 based Samsung SMDK board.
This patch series is based on linux-next master branch.
Thomas Abraham (7):
cpufreq: cpufreq-cpu0: allow optional safe voltage during frequency transitions
clk: samsung: add infrastructure to register cpu clocks
devicetree: bindings: add cpu clock configuration data binding for Exynos4/5
ARM: dts: Exynos: add cpu nodes, opp and cpu clock frequency table
clk: exynos: use cpu-clock provider type to represent arm clock
ARM: Exynos: switch to using generic cpufreq-cpu0 driver
cpufreq: exynos: remove all exynos specific cpufreq driver support
.../devicetree/bindings/clock/exynos4-clock.txt | 30 ++
.../devicetree/bindings/clock/exynos5250-clock.txt | 22 ++
.../devicetree/bindings/cpufreq/cpufreq-cpu0.txt | 7 +
arch/arm/boot/dts/exynos4210-origen.dts | 6 +
arch/arm/boot/dts/exynos4210-trats.dts | 6 +
arch/arm/boot/dts/exynos4210-universal_c210.dts | 6 +
arch/arm/boot/dts/exynos4210.dtsi | 35 ++
arch/arm/boot/dts/exynos4212.dtsi | 17 +
arch/arm/boot/dts/exynos4412-odroidx.dts | 6 +
arch/arm/boot/dts/exynos4412-origen.dts | 6 +
arch/arm/boot/dts/exynos4412-trats2.dts | 6 +
arch/arm/boot/dts/exynos4412.dtsi | 30 ++
arch/arm/boot/dts/exynos4x12.dtsi | 35 ++
arch/arm/boot/dts/exynos5250-arndale.dts | 6 +
arch/arm/boot/dts/exynos5250-cros-common.dtsi | 6 +
arch/arm/boot/dts/exynos5250-smdk5250.dts | 6 +
arch/arm/boot/dts/exynos5250.dtsi | 43 +++-
arch/arm/mach-exynos/common.c | 5 -
arch/arm/mach-exynos/common.h | 1 -
arch/arm/mach-exynos/mach-exynos4-dt.c | 2 +-
arch/arm/mach-exynos/mach-exynos5-dt.c | 2 +-
drivers/clk/samsung/Makefile | 2 +-
drivers/clk/samsung/clk-cpu.c | 345 ++++++++++++++++++++
drivers/clk/samsung/clk-exynos4.c | 11 +-
drivers/clk/samsung/clk-exynos5250.c | 8 +-
drivers/clk/samsung/clk.h | 3 +
drivers/cpufreq/Kconfig.arm | 36 --
drivers/cpufreq/Makefile | 4 -
drivers/cpufreq/cpufreq-cpu0.c | 37 ++-
drivers/cpufreq/exynos-cpufreq.c | 292 -----------------
drivers/cpufreq/exynos-cpufreq.h | 91 -----
drivers/cpufreq/exynos4210-cpufreq.c | 157 ---------
drivers/cpufreq/exynos4x12-cpufreq.c | 211 ------------
drivers/cpufreq/exynos5250-cpufreq.c | 183 -----------
include/dt-bindings/clock/exynos5250.h | 1 +
35 files changed, 666 insertions(+), 998 deletions(-)
create mode 100644 drivers/clk/samsung/clk-cpu.c
delete mode 100644 drivers/cpufreq/exynos-cpufreq.c
delete mode 100644 drivers/cpufreq/exynos-cpufreq.h
delete mode 100644 drivers/cpufreq/exynos4210-cpufreq.c
delete mode 100644 drivers/cpufreq/exynos4x12-cpufreq.c
delete mode 100644 drivers/cpufreq/exynos5250-cpufreq.c
^ permalink raw reply
* [PATCH v4] of: add functions to count number of elements in a property
From: Heiko Stübner @ 2014-01-18 12:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAL_JsqJ_St=OegpexzrTGXwmOYCz4YeWk_1S+R_q6NajmmPqSA@mail.gmail.com>
The need to know the number of array elements in a property is
a common pattern. To prevent duplication of open-coded implementations
add a helper static function that also centralises strict sanity
checking and DTB format details, as well as a set of wrapper functions
for u8, u16, u32 and u64.
Suggested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
changes since v3:
address more comments from Rob Herring
- export the base function and inline the type-specific wrappers
changes since v2:
address more comments from Mark Rutland
- switch to of_property_count_elems_of_size
- use full_name instead of name in error message
changes since v1:
address comments from Rob Herring and Mark Rutland:
- provide a helper and a set of wrappers for u8-u64
- get rid of extra len variable, prop->length is enough
- include node name in error message
Mark, does your Reviewed-by holds for this variant too?
drivers/of/base.c | 32 ++++++++++++++++++++++
include/linux/of.h | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 108 insertions(+)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index f807d0e..21646c0 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -862,6 +862,38 @@ struct device_node *of_find_node_by_phandle(phandle handle)
EXPORT_SYMBOL(of_find_node_by_phandle);
/**
+ * of_property_count_elems_of_size - Count the number of elements in a property
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @elem_size: size of the individual element
+ *
+ * Search for a property in a device node and count the number of elements of
+ * size elem_size in it. Returns number of elements on sucess, -EINVAL if the
+ * property does not exist or its length does not match a multiple of u16 and
+ * -ENODATA if the property does not have a value.
+ */
+int of_property_count_elems_of_size(const struct device_node *np,
+ const char *propname, int elem_size)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ if (prop->length % elem_size != 0) {
+ pr_err("size of %s in node %s is not a multiple of %d\n",
+ propname, np->full_name, elem_size);
+ return -EINVAL;
+ }
+
+ return prop->length / elem_size;
+}
+EXPORT_SYMBOL_GPL(of_property_count_elems_of_size);
+
+/**
* of_find_property_value_of_size
*
* @np: device node from which the property value is to be read.
diff --git a/include/linux/of.h b/include/linux/of.h
index 276c546..293920d 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -250,6 +250,8 @@ extern struct device_node *of_find_node_with_property(
extern struct property *of_find_property(const struct device_node *np,
const char *name,
int *lenp);
+extern int of_property_count_elems_of_size(const struct device_node *np,
+ const char *propname, int elem_size);
extern int of_property_read_u32_index(const struct device_node *np,
const char *propname,
u32 index, u32 *out_value);
@@ -426,6 +428,12 @@ static inline struct device_node *of_find_compatible_node(
return NULL;
}
+static inline int of_property_count_elems_of_size(const struct device_node *np,
+ const char *propname, int elem_size)
+{
+ return -ENOSYS;
+}
+
static inline int of_property_read_u32_index(const struct device_node *np,
const char *propname, u32 index, u32 *out_value)
{
@@ -565,6 +573,74 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; }
#endif
/**
+ * of_property_count_u8_elems - Count the number of u8 elements in a property
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ *
+ * Search for a property in a device node and count the number of u8 elements
+ * in it. Returns number of elements on sucess, -EINVAL if the property does
+ * not exist or its length does not match a multiple of u8 and -ENODATA if the
+ * property does not have a value.
+ */
+static inline int of_property_count_u8_elems(const struct device_node *np,
+ const char *propname)
+{
+ return of_property_count_elems_of_size(np, propname, sizeof(u8));
+}
+
+/**
+ * of_property_count_u16_elems - Count the number of u16 elements in a property
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ *
+ * Search for a property in a device node and count the number of u16 elements
+ * in it. Returns number of elements on sucess, -EINVAL if the property does
+ * not exist or its length does not match a multiple of u16 and -ENODATA if the
+ * property does not have a value.
+ */
+static inline int of_property_count_u16_elems(const struct device_node *np,
+ const char *propname)
+{
+ return of_property_count_elems_of_size(np, propname, sizeof(u16));
+}
+
+/**
+ * of_property_count_u32_elems - Count the number of u32 elements in a property
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ *
+ * Search for a property in a device node and count the number of u32 elements
+ * in it. Returns number of elements on sucess, -EINVAL if the property does
+ * not exist or its length does not match a multiple of u32 and -ENODATA if the
+ * property does not have a value.
+ */
+static inline int of_property_count_u32_elems(const struct device_node *np,
+ const char *propname)
+{
+ return of_property_count_elems_of_size(np, propname, sizeof(u32));
+}
+
+/**
+ * of_property_count_u64_elems - Count the number of u64 elements in a property
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ *
+ * Search for a property in a device node and count the number of u64 elements
+ * in it. Returns number of elements on sucess, -EINVAL if the property does
+ * not exist or its length does not match a multiple of u64 and -ENODATA if the
+ * property does not have a value.
+ */
+static inline int of_property_count_u64_elems(const struct device_node *np,
+ const char *propname)
+{
+ return of_property_count_elems_of_size(np, propname, sizeof(u64));
+}
+
+/**
* of_property_read_bool - Findfrom a property
* @np: device node from which the property value is to be read.
* @propname: name of the property to be searched.
--
1.7.10.4
^ permalink raw reply related
* [PATCH] ARM: dts: fix incorrect vdd_arm voltage range for Exynos4412 based boards
From: Thomas Abraham @ 2014-01-18 11:11 UTC (permalink / raw)
To: linux-arm-kernel
From: Thomas Abraham <thomas.ab@samsung.com>
To allow Exynos4412 based Odroidx and Origen-quad boards to operate between
200MHz to 1.4Ghz, update the vdd_arm voltage range to operate between these
cpu clock speeds.
Cc: Dongjin Kim <tobetter@gmail.com>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
---
arch/arm/boot/dts/exynos4412-odroidx.dts | 2 +-
arch/arm/boot/dts/exynos4412-origen.dts | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts
index 9804fcb..12459b0 100644
--- a/arch/arm/boot/dts/exynos4412-odroidx.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidx.dts
@@ -251,7 +251,7 @@
buck2_reg: BUCK2 {
regulator-name = "vdd_arm";
regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <1300000>;
+ regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-boot-on;
};
diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts
index 6bc0539..388f035 100644
--- a/arch/arm/boot/dts/exynos4412-origen.dts
+++ b/arch/arm/boot/dts/exynos4412-origen.dts
@@ -459,8 +459,8 @@
buck2_reg: BUCK2 {
regulator-name = "vdd_arm";
- regulator-min-microvolt = <925000>;
- regulator-max-microvolt = <1300000>;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-boot-on;
op_mode = <1>; /* Normal Mode */
--
1.6.6.rc2
^ 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