* [PATCH v6 17/19] watchdog: orion: Enable the build on ARCH_MVEBU
From: Ezequiel Garcia @ 2014-02-06 17:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391707226-18258-1-git-send-email-ezequiel.garcia@free-electrons.com>
After adding support for Armada 370/XP SoC let's enable the build on
these platforms.
Tested-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
drivers/watchdog/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 4c4c566..2dda6c0 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -291,7 +291,7 @@ config DAVINCI_WATCHDOG
config ORION_WATCHDOG
tristate "Orion watchdog"
- depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE
+ depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU
select WATCHDOG_CORE
help
Say Y here if to include support for the watchdog timer
--
1.8.1.5
^ permalink raw reply related
* [PATCH v6 18/19] ARM: mvebu: Enable watchdog support in defconfig
From: Ezequiel Garcia @ 2014-02-06 17:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391707226-18258-1-git-send-email-ezequiel.garcia@free-electrons.com>
Now that we have proper support for Armada 370/XP watchdog
let's enable it in the defconfig.
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
arch/arm/configs/mvebu_defconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig
index 0f4511d..31bdc6f 100644
--- a/arch/arm/configs/mvebu_defconfig
+++ b/arch/arm/configs/mvebu_defconfig
@@ -62,6 +62,8 @@ CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
CONFIG_THERMAL=y
CONFIG_ARMADA_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
CONFIG_USB_SUPPORT=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
--
1.8.1.5
^ permalink raw reply related
* [PATCH v6 19/19] ARM: dove: Enable watchdog support in the defconfig
From: Ezequiel Garcia @ 2014-02-06 17:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391707226-18258-1-git-send-email-ezequiel.garcia@free-electrons.com>
Now that we have watchdog support, let's add it to the defconfig.
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
arch/arm/configs/dove_defconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/configs/dove_defconfig b/arch/arm/configs/dove_defconfig
index 1101054..a330690 100644
--- a/arch/arm/configs/dove_defconfig
+++ b/arch/arm/configs/dove_defconfig
@@ -80,6 +80,8 @@ CONFIG_SPI_ORION=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
CONFIG_DOVE_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_EHCI_HCD=y
--
1.8.1.5
^ permalink raw reply related
* [PATCH 4/4] ARM: Kirkwood: Add support for many Synology NAS devices
From: Jason Cooper @ 2014-02-06 17:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140206170333.GK29860@lunn.ch>
On Thu, Feb 06, 2014 at 06:03:33PM +0100, Andrew Lunn wrote:
> On Thu, Feb 06, 2014 at 05:38:28PM +0100, Arnd Bergmann wrote:
> > On Thursday 06 February 2014 17:01:26 Andrew Lunn wrote:
> >
> > > , but this is, imho,
> > > > over-fragmenting. I'm sure there's a reason you chose this path, but
> > > > you haven't explained why in your commit log. So I'm left guessing...
> > >
> > > Synology seem to build there devices like lego. They have two
> > > different RTC blocks. They have three different fan alarm blocks, four
> > > different led blocks, etc. And to build a product, the just select a
> > > group of blocks and put them together.
> >
> > I guess the Armada-370 and newer based ds213j and dsx14 will also be
> > able to reuse some of the blocks, right?
>
> Hi Arnd
>
> I've not looked at any sources for those yet. I guess the RTC .dtsi
> files should be reusable. The ethernet driver on 370 is different so
> no re-use there. Maybe the fan controller, but the rest will depend on
> what GPIO lines they have used, if they are compatible.
perhaps all of the pinctrl nodes should be moved into synology-6281,
synology-6282, and synology-370 ?
thx,
Jason.
^ permalink raw reply
* [PATCH V4 0/8]PCI:Add SPEAr13xx PCie support
From: Pratyush Anand @ 2014-02-06 17:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1391661589.git.pratyush.anand@st.com>
Hi Arnd,
Do you see any more improvement in this series.
Else we will send V5 (probably the final one) with modifications for
Kishon's comment.
Regards
Pratyush
On Thu, Feb 6, 2014 at 10:14 AM, Pratyush Anand <pratyush.anand@st.com> wrote:
> First three patches are improvement and fixes for SPEAr13xx support.
> Patches 4-6 add miphy40lp skelten driver and support for spear1310/40 miphy
> wrapper. Patch 7 add support for SPEAr13xx PCIe.
>
> These pathes are tested with linux-3.14-rc1 with following patch on the top of
> it:
> Author: Balaji T K <balajitk@ti.com>
> Date: Mon Jan 20 16:41:27 2014 +0200
>
> ata: ahci_platform: Manage SATA PHY
>
> Tested with SPEAr1310 evaluation board:
> - INTEL PRO 100/100 EP card
> - USB xhci gen2 card
> - Above cards connected through LeCROY PTC switch
>
> Modifications for SATA are tested with SPEAr1340-evb board
>
> Changes since v3:
> - Phy driver renamed to phy-miphy40lp
> - ahci phy hook patch used as suggested by Arnd
> - Incorporated other minor comments from v3
>
> Changes since v2:
> - Incorporated comments to move SPEAr13xx PCIe and SATA phy specific routines to
> the phy framework
> - Modify ahci driver to include phy hooks
> - phy-core driver modifications for subsys_initcall()
>
> Changes since v1:
> - Few patches of the series are already accepted and applied to mainline e.g.
> pcie designware driver improvements,fixes for IO translation bug, PCIe dw
> driver maintainer. So dropped these from v2.
> - Incorporated comment to move the common/reset PCIe code to the seperate driver
> - PCIe and SATA share common PHY configuration registers, so move SATA
> platform code to the system config driver
> Fourth patch is improves pcie designware driver and fixes the IO
> translation bug. IO translation bug fix leads to the working of PCIe EP devices
> connected to RC through switch.
>
> PCIe driver support for SPEAr1310/40 platform board is added.
>
> These patches are tested with SPEAr1310 evaluation board:
> - INTEL PRO 100/100 EP card
> - USB xhci gen2 card
> - Above cards connected through LeCROY PTC switch
>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: devicetree at vger.kernel.org
> Cc: linux-ide at vger.kernel.org
> Cc: linux-pci at vger.kernel.org
> Cc: spear-devel at list.st.com
> Cc: linux-kernel at vger.kernel.org
>
> Mohit Kumar (2):
> SPEAr13xx: defconfig: Update
> MAINTAINERS: Add ST SPEAr13xx PCIe driver maintainer
>
> Pratyush Anand (6):
> clk: SPEAr13xx: Fix pcie clock name
> SPEAr13xx: Fix static mapping table
> phy: st-miphy-40lp: Add skeleton driver
> SPEAr13xx: Fixup: Move SPEAr1340 SATA platform code to phy driver
> phy: st-miphy-40lp: Add SPEAr1310 and SPEAr1340 PCIe phy support
> pcie: SPEAr13xx: Add designware pcie support
>
> .../devicetree/bindings/arm/spear-misc.txt | 4 +
> .../devicetree/bindings/pci/spear13xx-pcie.txt | 7 +
> .../devicetree/bindings/phy/st-miphy40lp.txt | 12 +
> MAINTAINERS | 6 +
> arch/arm/boot/dts/spear1310-evb.dts | 4 +
> arch/arm/boot/dts/spear1310.dtsi | 96 +++-
> arch/arm/boot/dts/spear1340-evb.dts | 4 +
> arch/arm/boot/dts/spear1340.dtsi | 32 +-
> arch/arm/boot/dts/spear13xx.dtsi | 10 +-
> arch/arm/configs/spear13xx_defconfig | 15 +
> arch/arm/mach-spear/Kconfig | 3 +
> arch/arm/mach-spear/include/mach/spear.h | 4 +-
> arch/arm/mach-spear/spear1340.c | 127 +----
> arch/arm/mach-spear/spear13xx.c | 2 +-
> drivers/clk/spear/spear1310_clock.c | 6 +-
> drivers/clk/spear/spear1340_clock.c | 2 +-
> drivers/pci/host/Kconfig | 5 +
> drivers/pci/host/Makefile | 1 +
> drivers/pci/host/pcie-spear13xx.c | 414 ++++++++++++++++
> drivers/phy/Kconfig | 6 +
> drivers/phy/Makefile | 1 +
> drivers/phy/phy-miphy40lp.c | 544 +++++++++++++++++++++
> 22 files changed, 1166 insertions(+), 139 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/arm/spear-misc.txt
> create mode 100644 Documentation/devicetree/bindings/pci/spear13xx-pcie.txt
> create mode 100644 Documentation/devicetree/bindings/phy/st-miphy40lp.txt
> create mode 100644 drivers/pci/host/pcie-spear13xx.c
> create mode 100644 drivers/phy/phy-miphy40lp.c
>
> --
> 1.8.1.2
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v6 18/19] ARM: mvebu: Enable watchdog support in defconfig
From: Jason Cooper @ 2014-02-06 17:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391707226-18258-19-git-send-email-ezequiel.garcia@free-electrons.com>
On Thu, Feb 06, 2014 at 02:20:25PM -0300, Ezequiel Garcia wrote:
> Now that we have proper support for Armada 370/XP watchdog
> let's enable it in the defconfig.
>
> Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
> ---
> arch/arm/configs/mvebu_defconfig | 2 ++
> 1 file changed, 2 insertions(+)
If this ends up being the last version for this series, I'll add a patch
for multi_v7_defconfig. Otherwise, please add for the next round.
thx,
Jason.
^ permalink raw reply
* [PATCH 0/3] irqchip: orion: bridge irq fixes for v3.14-rc1
From: Jason Cooper @ 2014-02-06 18:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140206171039.GC12542@localhost>
On Thu, Feb 06, 2014 at 02:10:40PM -0300, Ezequiel Garcia wrote:
> On Tue, Feb 04, 2014 at 11:54:15PM -0500, Jason Cooper wrote:
> > On Thu, Jan 23, 2014 at 11:38:03PM +0100, Sebastian Hesselbarth wrote:
> > > This is a small patch set to fix some shortcomings how Orion bridge
> > > irqs are handled. The patches are based on v3.13-rc8 and should go
> > > into v3.14. They can possibly also marked for -stable down to v3.10.
> > >
> > > This patches are the result of a discussion about a stale watchdog irq,
> > > that can accidentially trigger the watchdog's irq handler and cause a
> > > reset [1].
> > >
> > > The first patch will add a write to clear already pending interrupts
> > > on init. The second patch replaces handle_level_irq with handle_edge_irq
> > > which is more appropriate for bridge irqs which are edge-triggered.
> > > The last patch finally, fixes stale interrupts by installing an
> > > .irq_enable callback, that will clear a possible pending interrupt
> > > before unmasking it.
> > >
> > > [1] http://www.spinics.net/lists/arm-kernel/msg302106.html
> > >
> > > Sebastian Hesselbarth (3):
> > > irqchip: orion: clear bridge cause register on init
> > > irqchip: orion: use handle_edge_irq on bridge irqs
> > > irqchip: orion: clear stale interrupts in irq_enable
> > >
> > > drivers/irqchip/irq-orion.c | 18 ++++++++++++++++--
> > > 1 file changed, 16 insertions(+), 2 deletions(-)
> >
> > Whole series applied to mvebu-next/irqchip-fixes (v2 for 3/3). Once I
> > see that the outstanding pull requests for mvebu/irqchip have been
> > merged into mainline, I'll be changing the name of this branch to
> > mvebu/irqchip-fixes. I just don't want to upset the applecart atm.
> >
> > Oh yeah, Cc'd for stable back to v3.10.
> >
>
> If you want to pick this:
>
> Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Added, thanks for testing!
thx,
Jason.
^ permalink raw reply
* [PATCH 0/4] clk: mvebu: fix clk init order
From: Jason Cooper @ 2014-02-06 18:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140206170838.GB12542@localhost>
On Thu, Feb 06, 2014 at 02:08:39PM -0300, Ezequiel Garcia wrote:
> On Wed, Feb 05, 2014 at 01:34:57PM -0500, Jason Cooper wrote:
> > On Sat, Jan 25, 2014 at 07:19:06PM +0100, Sebastian Hesselbarth wrote:
> > > This patch set fixes clk init order that went upside-down with
> > > v3.14. I haven't really investigated what caused this, but I assume
> > > it is related with DT node reordering by addresses.
> > >
> > > Anyway, with v3.14 for MVEBU SoCs, the clock gating driver gets
> > > registered before core clocks driver. Unfortunately, we cannot
> > > return -EPROBE_DEFER in drivers initialized by clk_of_init. As the
> > > init order for our drivers is always core clocks before clock gating,
> > > we maintain init order ourselves by hooking CLK_OF_DECLARE to one
> > > init function that will register core clocks before clock gating
> > > driver.
> > >
> > > This patch is based on pre-v3.14-rc1 mainline and should go in as
> > > fixes for it. As we now send MVEBU clk pull-requests to Mike directly,
> > > I suggest Jason picks it up as a topic branch.
> > >
> > > The patches have been boot tested on Dove and compile-tested only
> > > for Kirkwood, Armada 370 and XP.
> > >
> > > Sebastian Hesselbarth (4):
> > > clk: mvebu: armada-370: maintain clock init order
> > > clk: mvebu: armada-xp: maintain clock init order
> > > clk: mvebu: dove: maintain clock init order
> > > clk: mvebu: kirkwood: maintain clock init order
> > >
> > > drivers/clk/mvebu/armada-370.c | 21 ++++++++++-----------
> > > drivers/clk/mvebu/armada-xp.c | 20 +++++++++-----------
> > > drivers/clk/mvebu/dove.c | 19 +++++++++----------
> > > drivers/clk/mvebu/kirkwood.c | 34 ++++++++++++++++------------------
> > > 4 files changed, 44 insertions(+), 50 deletions(-)
> >
> > Whole series applied to mvebu/clk-fixes.
> >
>
> FWIW, Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
>
> Observed "division by zero" get fixed by this, on A370 Mirabox, Kirkwood
> Topkick and Dove Cubox.
Added for patches 1, 3, and 4 (all but armada-xp.c) Thanks for testing.
thx,
Jason.
^ permalink raw reply
* [PATCH 0/5] iommu/arm-smmu: fixes for 3.14
From: Will Deacon @ 2014-02-06 18:09 UTC (permalink / raw)
To: linux-arm-kernel
Hi all,
This is the set of fixes I plan to send to Joerg for 3.14. There a quite
a few scary looking commits here, for a number of reasons:
- Andreas Herrmann took the driver for a run with a real SATA
controller, which caused the new mutex-based locking to explode
since we require mappings in atomic context
- Yifan fixed an issue with the page table creation, which then caused
breakages with the way in which we flush descriptors out to the
table walker
- I ran the driver on a system where the SMMU is hooked into a
coherent interconnect for table walks, and noticed a shareability
mismatch between the CPU and the SMMU
These issues are all fixed here and have been tests on both arm and
arm64 based systems.
All feedback welcome,
Will
Will Deacon (4):
iommu/arm-smmu: really fix page table locking
iommu/arm-smmu: fix table flushing during initial allocations
iommu/arm-smmu: set CBARn.BPSHCFG to NSH for s1-s2-bypass contexts
iommu/arm-smmu: fix compilation issue when !CONFIG_ARM_AMBA
Yifan Zhang (1):
iommu/arm-smmu: fix pud/pmd entry fill sequence
drivers/iommu/arm-smmu.c | 103 ++++++++++++++++++++++++++++-------------------
1 file changed, 61 insertions(+), 42 deletions(-)
--
1.8.2.2
^ permalink raw reply
* [PATCH 1/5] iommu/arm-smmu: fix pud/pmd entry fill sequence
From: Will Deacon @ 2014-02-06 18:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710173-4343-1-git-send-email-will.deacon@arm.com>
From: Yifan Zhang <zhangyf@marvell.com>
The ARM SMMU driver's population of puds and pmds is broken, since we
iterate over the next level of table repeatedly setting the current
level descriptor to point at the pmd being initialised. This is clearly
wrong when dealing with multiple pmds/puds.
This patch fixes the problem by moving the pud/pmd population out of the
loop and instead performing it when we allocate the next level (like we
correctly do for ptes already). The starting address for the next level
is then calculated prior to entering the loop.
Cc: <stable@vger.kernel.org>
Signed-off-by: Yifan Zhang <zhangyf@marvell.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
drivers/iommu/arm-smmu.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 8911850c9444..9f210de6537e 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1320,6 +1320,11 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud,
pmd = pmd_alloc_one(NULL, addr);
if (!pmd)
return -ENOMEM;
+
+ pud_populate(NULL, pud, pmd);
+ arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud));
+
+ pmd += pmd_index(addr);
} else
#endif
pmd = pmd_offset(pud, addr);
@@ -1328,8 +1333,6 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud,
next = pmd_addr_end(addr, end);
ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, end, pfn,
flags, stage);
- pud_populate(NULL, pud, pmd);
- arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud));
phys += next - addr;
} while (pmd++, addr = next, addr < end);
@@ -1349,6 +1352,11 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd,
pud = pud_alloc_one(NULL, addr);
if (!pud)
return -ENOMEM;
+
+ pgd_populate(NULL, pgd, pud);
+ arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd));
+
+ pud += pud_index(addr);
} else
#endif
pud = pud_offset(pgd, addr);
@@ -1357,8 +1365,6 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd,
next = pud_addr_end(addr, end);
ret = arm_smmu_alloc_init_pmd(smmu, pud, addr, next, phys,
flags, stage);
- pgd_populate(NULL, pud, pgd);
- arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd));
phys += next - addr;
} while (pud++, addr = next, addr < end);
--
1.8.2.2
^ permalink raw reply related
* [PATCH 2/5] iommu/arm-smmu: really fix page table locking
From: Will Deacon @ 2014-02-06 18:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710173-4343-1-git-send-email-will.deacon@arm.com>
Commit a44a9791e778 ("iommu/arm-smmu: use mutex instead of spinlock for
locking page tables") replaced the page table spinlock with a mutex, to
allow blocking allocations to satisfy lazy mapping requests.
Unfortunately, it turns out that IOMMU mappings are created from atomic
context (e.g. spinlock held during a dma_map), so this change doesn't
really help us in practice.
This patch is a partial revert of the offending commit, bringing back
the original spinlock but replacing our page table allocations for any
levels below the pgd (which is allocated during domain init) with
GFP_ATOMIC instead of GFP_KERNEL.
Cc: <stable@vger.kernel.org>
Reported-by: Andreas Herrmann <andreas.herrmann@calxeda.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
drivers/iommu/arm-smmu.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 9f210de6537e..6eb54ae97470 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -393,7 +393,7 @@ struct arm_smmu_domain {
struct arm_smmu_cfg root_cfg;
phys_addr_t output_mask;
- struct mutex lock;
+ spinlock_t lock;
};
static DEFINE_SPINLOCK(arm_smmu_devices_lock);
@@ -901,7 +901,7 @@ static int arm_smmu_domain_init(struct iommu_domain *domain)
goto out_free_domain;
smmu_domain->root_cfg.pgd = pgd;
- mutex_init(&smmu_domain->lock);
+ spin_lock_init(&smmu_domain->lock);
domain->priv = smmu_domain;
return 0;
@@ -1138,7 +1138,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
* Sanity check the domain. We don't currently support domains
* that cross between different SMMU chains.
*/
- mutex_lock(&smmu_domain->lock);
+ spin_lock(&smmu_domain->lock);
if (!smmu_domain->leaf_smmu) {
/* Now that we have a master, we can finalise the domain */
ret = arm_smmu_init_domain_context(domain, dev);
@@ -1153,7 +1153,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
dev_name(device_smmu->dev));
goto err_unlock;
}
- mutex_unlock(&smmu_domain->lock);
+ spin_unlock(&smmu_domain->lock);
/* Looks ok, so add the device to the domain */
master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node);
@@ -1163,7 +1163,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
return arm_smmu_domain_add_master(smmu_domain, master);
err_unlock:
- mutex_unlock(&smmu_domain->lock);
+ spin_unlock(&smmu_domain->lock);
return ret;
}
@@ -1210,7 +1210,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd,
if (pmd_none(*pmd)) {
/* Allocate a new set of tables */
- pgtable_t table = alloc_page(PGALLOC_GFP);
+ pgtable_t table = alloc_page(GFP_ATOMIC|__GFP_ZERO);
if (!table)
return -ENOMEM;
@@ -1317,7 +1317,7 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud,
#ifndef __PAGETABLE_PMD_FOLDED
if (pud_none(*pud)) {
- pmd = pmd_alloc_one(NULL, addr);
+ pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC);
if (!pmd)
return -ENOMEM;
@@ -1349,7 +1349,7 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd,
#ifndef __PAGETABLE_PUD_FOLDED
if (pgd_none(*pgd)) {
- pud = pud_alloc_one(NULL, addr);
+ pud = (pud_t *)get_zeroed_page(GFP_ATOMIC);
if (!pud)
return -ENOMEM;
@@ -1403,7 +1403,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
if (paddr & ~output_mask)
return -ERANGE;
- mutex_lock(&smmu_domain->lock);
+ spin_lock(&smmu_domain->lock);
pgd += pgd_index(iova);
end = iova + size;
do {
@@ -1419,7 +1419,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
} while (pgd++, iova != end);
out_unlock:
- mutex_unlock(&smmu_domain->lock);
+ spin_unlock(&smmu_domain->lock);
/* Ensure new page tables are visible to the hardware walker */
if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
--
1.8.2.2
^ permalink raw reply related
* [PATCH 3/5] iommu/arm-smmu: fix table flushing during initial allocations
From: Will Deacon @ 2014-02-06 18:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710173-4343-1-git-send-email-will.deacon@arm.com>
Now that we populate page tables as we traverse them ("iommu/arm-smmu:
fix pud/pmd entry fill sequence"), we need to ensure that we flush out
our zeroed tables after initial allocation, to prevent speculative TLB
fills using bogus data.
This patch adds additional calls to arm_smmu_flush_pgtable during
initial table allocation, and moves the dsb required by coherent table
walkers into the helper.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
drivers/iommu/arm-smmu.c | 51 +++++++++++++++++++++++++-----------------------
1 file changed, 27 insertions(+), 24 deletions(-)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 6eb54ae97470..509f01f054d9 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -79,7 +79,6 @@
#define ARM_SMMU_PTE_CONT_SIZE (PAGE_SIZE * ARM_SMMU_PTE_CONT_ENTRIES)
#define ARM_SMMU_PTE_CONT_MASK (~(ARM_SMMU_PTE_CONT_SIZE - 1))
-#define ARM_SMMU_PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(pte_t))
/* Stage-1 PTE */
#define ARM_SMMU_PTE_AP_UNPRIV (((pteval_t)1) << 6)
@@ -632,6 +631,28 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev)
return IRQ_HANDLED;
}
+static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr,
+ size_t size)
+{
+ unsigned long offset = (unsigned long)addr & ~PAGE_MASK;
+
+
+ /* Ensure new page tables are visible to the hardware walker */
+ if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) {
+ dsb();
+ } else {
+ /*
+ * If the SMMU can't walk tables in the CPU caches, treat them
+ * like non-coherent DMA since we need to flush the new entries
+ * all the way out to memory. There's no possibility of
+ * recursion here as the SMMU table walker will not be wired
+ * through another SMMU.
+ */
+ dma_map_page(smmu->dev, virt_to_page(addr), offset, size,
+ DMA_TO_DEVICE);
+ }
+}
+
static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
{
u32 reg;
@@ -715,6 +736,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
}
/* TTBR0 */
+ arm_smmu_flush_pgtable(smmu, root_cfg->pgd,
+ PTRS_PER_PGD * sizeof(pgd_t));
reg = __pa(root_cfg->pgd);
writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO);
reg = (phys_addr_t)__pa(root_cfg->pgd) >> 32;
@@ -1177,23 +1200,6 @@ static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev)
arm_smmu_domain_remove_master(smmu_domain, master);
}
-static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr,
- size_t size)
-{
- unsigned long offset = (unsigned long)addr & ~PAGE_MASK;
-
- /*
- * If the SMMU can't walk tables in the CPU caches, treat them
- * like non-coherent DMA since we need to flush the new entries
- * all the way out to memory. There's no possibility of recursion
- * here as the SMMU table walker will not be wired through another
- * SMMU.
- */
- if (!(smmu->features & ARM_SMMU_FEAT_COHERENT_WALK))
- dma_map_page(smmu->dev, virt_to_page(addr), offset, size,
- DMA_TO_DEVICE);
-}
-
static bool arm_smmu_pte_is_contiguous_range(unsigned long addr,
unsigned long end)
{
@@ -1214,8 +1220,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd,
if (!table)
return -ENOMEM;
- arm_smmu_flush_pgtable(smmu, page_address(table),
- ARM_SMMU_PTE_HWTABLE_SIZE);
+ arm_smmu_flush_pgtable(smmu, page_address(table), PAGE_SIZE);
if (!pgtable_page_ctor(table)) {
__free_page(table);
return -ENOMEM;
@@ -1321,6 +1326,7 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud,
if (!pmd)
return -ENOMEM;
+ arm_smmu_flush_pgtable(smmu, pmd, PAGE_SIZE);
pud_populate(NULL, pud, pmd);
arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud));
@@ -1353,6 +1359,7 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd,
if (!pud)
return -ENOMEM;
+ arm_smmu_flush_pgtable(smmu, pud, PAGE_SIZE);
pgd_populate(NULL, pgd, pud);
arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd));
@@ -1421,10 +1428,6 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
out_unlock:
spin_unlock(&smmu_domain->lock);
- /* Ensure new page tables are visible to the hardware walker */
- if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
- dsb();
-
return ret;
}
--
1.8.2.2
^ permalink raw reply related
* [PATCH 4/5] iommu/arm-smmu: set CBARn.BPSHCFG to NSH for s1-s2-bypass contexts
From: Will Deacon @ 2014-02-06 18:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710173-4343-1-git-send-email-will.deacon@arm.com>
Whilst trying to bring-up an SMMUv2 implementation with the table
walker plumbed into a coherent interconnect, I noticed that the memory
transactions targetting the CPU caches from the SMMU were marked as
outer-shareable instead of inner-shareable.
After a bunch of digging, it seems that we actually need to program
CBARn.BPSHCFG for s1-s2-bypass contexts to act as non-shareable in order
for the shareability configured in the corresponding TTBCR not to be
overridden with an outer-shareable attribute.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
drivers/iommu/arm-smmu.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 509f01f054d9..0ae4dd39197f 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -190,6 +190,9 @@
#define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2))
#define CBAR_VMID_SHIFT 0
#define CBAR_VMID_MASK 0xff
+#define CBAR_S1_BPSHCFG_SHIFT 8
+#define CBAR_S1_BPSHCFG_MASK 3
+#define CBAR_S1_BPSHCFG_NSH 3
#define CBAR_S1_MEMATTR_SHIFT 12
#define CBAR_S1_MEMATTR_MASK 0xf
#define CBAR_S1_MEMATTR_WB 0xf
@@ -671,11 +674,16 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
if (smmu->version == 1)
reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT;
- /* Use the weakest memory type, so it is overridden by the pte */
- if (stage1)
- reg |= (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
- else
+ /*
+ * Use the weakest shareability/memory types, so they are
+ * overridden by the ttbcr/pte.
+ */
+ if (stage1) {
+ reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
+ (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
+ } else {
reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT;
+ }
writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx));
if (smmu->version > 1) {
--
1.8.2.2
^ permalink raw reply related
* [PATCH 5/5] iommu/arm-smmu: fix compilation issue when !CONFIG_ARM_AMBA
From: Will Deacon @ 2014-02-06 18:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710173-4343-1-git-send-email-will.deacon@arm.com>
If !CONFIG_ARM_AMBA, we shouldn't try to register ourselves with the
amba_bustype.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
drivers/iommu/arm-smmu.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 0ae4dd39197f..6fe7922ecc1d 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -2004,8 +2004,10 @@ static int __init arm_smmu_init(void)
if (!iommu_present(&platform_bus_type))
bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
+#ifdef CONFIG_ARM_AMBA
if (!iommu_present(&amba_bustype))
bus_set_iommu(&amba_bustype, &arm_smmu_ops);
+#endif
return 0;
}
--
1.8.2.2
^ permalink raw reply related
* [PATCH] ARM: enable IRQs in user undefined instruction vector
From: Kevin Bracey @ 2014-02-06 18:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140206112039.GA31054@arm.com>
On 06/02/2014 13:20, Catalin Marinas wrote:
> On Tue, Feb 04, 2014 at 10:19:06PM +0200, Kevin Bracey wrote:
>> See http://comments.gmane.org/gmane.linux.ports.arm.omap/59256 for
>> an earlier report of the observed might_sleep() warning.
> There was a follow-up on this:
>
> http://thread.gmane.org/gmane.linux.ports.arm.kernel/263765
Thanks for that pointer - we failed to find that thread. And from it I
see I totally missed the iwmmxt path. :(
> __und_usr:
> usr_entry
> + enable_irq
> The problem is that you can be preempted here and parts of the kernel
> may not cope with this.
A very close analogue to this code is vector_swi. As far as I can see,
having interrupts+preemption enabled in this __und_usr section should be
as safe as it is there, so I'm pretty confident there shouldn't be a
general kernel issue. But...
> The reason I haven't pushed my patches to mainline is that I was worried
> about such preemption cases. We enter iwmmxt_task_enable for example
> with interrupts and preemption enabled, we disable preemption there but
> is it too late? I don't have a way to test these and even for VFP I'm
> not sure testing would guarantee it in all scenarios.
The only concern I can see - and it's a big one - is that of how a HW
coprocessor responds. If the coprocessor bounces an instruction, and we
switch context before reaching the support code, will the hardware and
its support code cope - both with switching to another context in that
state, and handling the original bounce in this context when we get back?
I know that because they're asynchronous, the FPA+VFP have always had to
cope with possible pre-emption in the window between them deciding they
need support and their next opportunity to bounce an instruction; but
what if they get pre-empted between a bounce being generated and the
support code processing it?
The VFP code did take pains to increment the pre-emption count before
enabling interrupts, but it's not obvious whether it requires no
pre-emption between the bounce and handler, or just no pre-emption
during the handler.
For the FPA, we only have FPA emulation, not FPA support code, so
nothing to worry about there.
What about the iwmmxt and the crunchbits? They are only lazy-enable
routines, to activate an inactive coprocessor. Which I think makes them
safe. If we schedule before reaching the handler, when this context is
returned to, the coprocessor must still be disabled in our context - the
handler can proceed to enable it. And there can't be any other context
state to worry about, assuming the lazy enable scheme works.
Personally, I've always wondered why ARM never implemented a CP15
register you could read to find out what instruction generated a SWI or
undefined instruction exception, to save all this hassle. It's always
seemed to me like an obvious addition, ever since the I+D caches were
split; why do I have to load my code into the data cache?
> So it needs more thinking. Please have a look at my patches, if we get
> to the conclusion there is no issue, I'll push them upstream.
>
I think if there's a problem, it will be in the VFP code - the others
seem straightforward. The interrupt enable has to be made safe - as
long as another core can age a page before the handler is reached, the
VFP support code will /have/ to be able to cope with pre-emption between
the fault and handler, if it doesn't already. We need a VFP expert to
figure it out properly.
We will stress test your posted patch for our failure case, which is
Android skipping VFP instructions thanks to the extra irqs_disabled()
patch in do_page_fault().
I think we should also include the fixup handler modification from my
patch - I think __und_usr having a fixup handler that skips the
instruction if do_page_fault fails is just asking for trouble, so it
should be aligned with vector_swi so it retries.
I share Alexey's Ignatov's concern that your patch ends up running the
support code with interrupts either on or off depending on whether you
came from user or supervisor mode, which feels a little odd. But then,
always enabling interrupts like the current code does, when they might
have been off in the SVC mode context, also seems wrong.
I did ponder for my version whether the __und_svc path should restore
original IRQ status before going to call_fpe, to make the handler entry
environment more uniform - IRQ status would always be as in original
context.
Maybe it's a fine detail, as we don't really expect to be handling any
of these instructions from the kernel anyway, but if we are going to the
trouble to send __und_svc to handlers rather than going straight to
__und_svc_fault...
Kevin
^ permalink raw reply
* [PATCH v2 0/9] Samsung PM consolidation part 1 (clocks)
From: Tomasz Figa @ 2014-02-06 18:16 UTC (permalink / raw)
To: linux-arm-kernel
This series reworks suspend/resume handling of Samsung clock drivers
to cover more SoC specific aspects that are beyond simple register
save and restore. The goal is to have all the suspend/resume code
that touches the clock controller in single place, which is the
clock driver.
On Exynos4210-based Trats, Exynos4412-based Trats2 and Exynos5250-based
Arndale boards (except suspend/resume, which is broken because of
unrelated reasons):
Tested-by: Tomasz Figa <t.figa@samsung.com>
Tomasz Figa (9):
clk: exynos4: Remove remnants of non-DT support
clk: samsung: Provide common helpers for register save/restore
clk: samsung: exynos4: Move suspend/resume handling to SoC driver
clk: samsung: exynos5250: Move suspend/resume handling to SoC driver
clk: samsung: exynos5420: Move suspend/resume handling to SoC driver
clk: samsung: s3c64xx: Move suspend/resume handling to SoC driver
clk: samsung: Drop old suspend/resume code
clk: samsung: exynos4: Add remaining suspend/resume handling
ARM: EXYNOS: pm: Drop legacy Exynos4 clock suspend/resume code
arch/arm/mach-exynos/pm.c | 148 +-----------------------------
drivers/clk/samsung/clk-exynos4.c | 172 +++++++++++++++++++++++++++++++----
drivers/clk/samsung/clk-exynos5250.c | 49 +++++++++-
drivers/clk/samsung/clk-exynos5420.c | 49 +++++++++-
drivers/clk/samsung/clk-exynos5440.c | 2 +-
drivers/clk/samsung/clk-s3c64xx.c | 79 +++++++++++++---
drivers/clk/samsung/clk.c | 71 ++++++---------
drivers/clk/samsung/clk.h | 14 ++-
8 files changed, 348 insertions(+), 236 deletions(-)
--
1.8.5.2
^ permalink raw reply
* [PATCH v2 1/9] clk: exynos4: Remove remnants of non-DT support
From: Tomasz Figa @ 2014-02-06 18:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710616-14226-1-git-send-email-t.figa@samsung.com>
This patch simplifies a bit clock initialization code by removing
remnants of non-DT clock initialization, such as reg_base and xom values
passed in function parameters.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/clk/samsung/clk-exynos4.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 010f071..12a9f28 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -908,12 +908,13 @@ static unsigned long exynos4_get_xom(void)
return xom;
}
-static void __init exynos4_clk_register_finpll(unsigned long xom)
+static void __init exynos4_clk_register_finpll(void)
{
struct samsung_fixed_rate_clock fclk;
struct clk *clk;
unsigned long finpll_f = 24000000;
char *parent_name;
+ unsigned int xom = exynos4_get_xom();
parent_name = xom & 1 ? "xusbxti" : "xxti";
clk = clk_get(NULL, parent_name);
@@ -1038,9 +1039,10 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
/* register exynos4 clocks */
static void __init exynos4_clk_init(struct device_node *np,
- enum exynos4_soc exynos4_soc,
- void __iomem *reg_base, unsigned long xom)
+ enum exynos4_soc exynos4_soc)
{
+ void __iomem *reg_base;
+
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
@@ -1058,7 +1060,7 @@ static void __init exynos4_clk_init(struct device_node *np,
ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
ext_clk_match);
- exynos4_clk_register_finpll(xom);
+ exynos4_clk_register_finpll();
if (exynos4_soc == EXYNOS4210) {
samsung_clk_register_mux(exynos4210_mux_early,
@@ -1136,12 +1138,12 @@ static void __init exynos4_clk_init(struct device_node *np,
static void __init exynos4210_clk_init(struct device_node *np)
{
- exynos4_clk_init(np, EXYNOS4210, NULL, exynos4_get_xom());
+ exynos4_clk_init(np, EXYNOS4210);
}
CLK_OF_DECLARE(exynos4210_clk, "samsung,exynos4210-clock", exynos4210_clk_init);
static void __init exynos4412_clk_init(struct device_node *np)
{
- exynos4_clk_init(np, EXYNOS4X12, NULL, exynos4_get_xom());
+ exynos4_clk_init(np, EXYNOS4X12);
}
CLK_OF_DECLARE(exynos4412_clk, "samsung,exynos4412-clock", exynos4412_clk_init);
--
1.8.5.2
^ permalink raw reply related
* [PATCH v2 2/9] clk: samsung: Provide common helpers for register save/restore
From: Tomasz Figa @ 2014-02-06 18:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710616-14226-1-git-send-email-t.figa@samsung.com>
As suspend/resume handlers are being moved to SoC specific code, due to
differencies in suspend/resume handling of particular SoCs, to minimize
code duplication this patch provides common register save/restore
helpers that save/restore given list of registers of clock controller.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/clk/samsung/clk.c | 32 ++++++++++++++++++++++++++++++++
drivers/clk/samsung/clk.h | 10 ++++++++++
2 files changed, 42 insertions(+)
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index f503f32..c0a716b 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -22,6 +22,38 @@ static struct clk_onecell_data clk_data;
#endif
#ifdef CONFIG_PM_SLEEP
+void samsung_clk_save(void __iomem *base,
+ struct samsung_clk_reg_dump *rd,
+ unsigned int num_regs)
+{
+ for (; num_regs > 0; --num_regs, ++rd)
+ rd->value = readl(base + rd->offset);
+}
+
+void samsung_clk_restore(void __iomem *base,
+ const struct samsung_clk_reg_dump *rd,
+ unsigned int num_regs)
+{
+ for (; num_regs > 0; --num_regs, ++rd)
+ writel(rd->value, base + rd->offset);
+}
+
+struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(unsigned long *rdump,
+ unsigned long nr_rdump)
+{
+ struct samsung_clk_reg_dump *rd;
+ unsigned int i;
+
+ rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL);
+ if (!rd)
+ return NULL;
+
+ for (i = 0; i < nr_rdump; ++i)
+ rd[i].offset = rdump[i];
+
+ return rd;
+}
+
static struct samsung_clk_reg_dump *reg_dump;
static unsigned long nr_reg_dump;
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 31b4174..ec8d46b 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -340,4 +340,14 @@ extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list,
extern unsigned long _get_rate(const char *clk_name);
+extern void samsung_clk_save(void __iomem *base,
+ struct samsung_clk_reg_dump *rd,
+ unsigned int num_regs);
+extern void samsung_clk_restore(void __iomem *base,
+ const struct samsung_clk_reg_dump *rd,
+ unsigned int num_regs);
+extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
+ unsigned long *rdump,
+ unsigned long nr_rdump);
+
#endif /* __SAMSUNG_CLK_H */
--
1.8.5.2
^ permalink raw reply related
* [PATCH v2 3/9] clk: samsung: exynos4: Move suspend/resume handling to SoC driver
From: Tomasz Figa @ 2014-02-06 18:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710616-14226-1-git-send-email-t.figa@samsung.com>
Since there are multiple differences in how suspend/resume of particular
Exynos SoCs must be handled, SoC driver is better place for
suspend/resume handlers and so this patch moves them.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/clk/samsung/clk-exynos4.c | 90 ++++++++++++++++++++++++++++++++++-----
1 file changed, 80 insertions(+), 10 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 12a9f28..325f292 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -16,6 +16,7 @@
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
#include "clk.h"
@@ -130,6 +131,16 @@ enum exynos4_plls {
nr_plls /* number of PLLs */
};
+static void __iomem *reg_base;
+static enum exynos4_soc exynos4_soc;
+
+/*
+ * Support for CMU save/restore across system suspends
+ */
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *exynos4_save_common;
+static struct samsung_clk_reg_dump *exynos4_save_soc;
+
/*
* list of controller registers to be saved and restored during a
* suspend/resume cycle.
@@ -227,6 +238,70 @@ static unsigned long exynos4_clk_regs[] __initdata = {
GATE_IP_CPU,
};
+static int exynos4_clk_suspend(void)
+{
+ samsung_clk_save(reg_base, exynos4_save_common,
+ ARRAY_SIZE(exynos4_clk_regs));
+
+ if (exynos4_soc == EXYNOS4210)
+ samsung_clk_save(reg_base, exynos4_save_soc,
+ ARRAY_SIZE(exynos4210_clk_save));
+ else
+ samsung_clk_save(reg_base, exynos4_save_soc,
+ ARRAY_SIZE(exynos4x12_clk_save));
+
+ return 0;
+}
+
+static void exynos4_clk_resume(void)
+{
+ samsung_clk_restore(reg_base, exynos4_save_common,
+ ARRAY_SIZE(exynos4_clk_regs));
+
+ if (exynos4_soc == EXYNOS4210)
+ samsung_clk_restore(reg_base, exynos4_save_soc,
+ ARRAY_SIZE(exynos4210_clk_save));
+ else
+ samsung_clk_restore(reg_base, exynos4_save_soc,
+ ARRAY_SIZE(exynos4x12_clk_save));
+}
+
+static struct syscore_ops exynos4_clk_syscore_ops = {
+ .suspend = exynos4_clk_suspend,
+ .resume = exynos4_clk_resume,
+};
+
+static void exynos4_clk_sleep_init(void)
+{
+ exynos4_save_common = samsung_clk_alloc_reg_dump(exynos4_clk_regs,
+ ARRAY_SIZE(exynos4_clk_regs));
+ if (!exynos4_save_common)
+ goto err_warn;
+
+ if (exynos4_soc == EXYNOS4210)
+ exynos4_save_soc = samsung_clk_alloc_reg_dump(
+ exynos4210_clk_save,
+ ARRAY_SIZE(exynos4210_clk_save));
+ else
+ exynos4_save_soc = samsung_clk_alloc_reg_dump(
+ exynos4x12_clk_save,
+ ARRAY_SIZE(exynos4x12_clk_save));
+ if (!exynos4_save_soc)
+ goto err_common;
+
+ register_syscore_ops(&exynos4_clk_syscore_ops);
+ return;
+
+err_common:
+ kfree(exynos4_save_common);
+err_warn:
+ pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
+ __func__);
+}
+#else
+static void exynos4_clk_sleep_init(void) {}
+#endif
+
/* list of all parent clock list */
PNAME(mout_apll_p) = { "fin_pll", "fout_apll", };
PNAME(mout_mpll_p) = { "fin_pll", "fout_mpll", };
@@ -1039,22 +1114,15 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
/* register exynos4 clocks */
static void __init exynos4_clk_init(struct device_node *np,
- enum exynos4_soc exynos4_soc)
+ enum exynos4_soc soc)
{
- void __iomem *reg_base;
+ exynos4_soc = soc;
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
- if (exynos4_soc == EXYNOS4210)
- samsung_clk_init(np, reg_base, CLK_NR_CLKS,
- exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs),
- exynos4210_clk_save, ARRAY_SIZE(exynos4210_clk_save));
- else
- samsung_clk_init(np, reg_base, CLK_NR_CLKS,
- exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs),
- exynos4x12_clk_save, ARRAY_SIZE(exynos4x12_clk_save));
+ samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0);
samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks,
ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
@@ -1127,6 +1195,8 @@ static void __init exynos4_clk_init(struct device_node *np,
samsung_clk_register_alias(exynos4_aliases,
ARRAY_SIZE(exynos4_aliases));
+ exynos4_clk_sleep_init();
+
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",
--
1.8.5.2
^ permalink raw reply related
* [PATCH v2 4/9] clk: samsung: exynos5250: Move suspend/resume handling to SoC driver
From: Tomasz Figa @ 2014-02-06 18:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710616-14226-1-git-send-email-t.figa@samsung.com>
Since there are multiple differences in how suspend/resume of particular
Exynos SoCs must be handled, SoC driver is better place for
suspend/resume handlers and so this patch moves them.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/clk/samsung/clk-exynos5250.c | 49 ++++++++++++++++++++++++++++++++----
drivers/clk/samsung/clk.c | 5 ++--
drivers/clk/samsung/clk.h | 4 +--
3 files changed, 49 insertions(+), 9 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index ff4beeb..b3cccf0 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -16,6 +16,7 @@
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
#include "clk.h"
@@ -85,6 +86,11 @@ enum exynos5250_plls {
nr_plls /* number of PLLs */
};
+static void __iomem *reg_base;
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *exynos5250_save;
+
/*
* list of controller registers to be saved and restored during a
* suspend/resume cycle.
@@ -137,6 +143,41 @@ static unsigned long exynos5250_clk_regs[] __initdata = {
GATE_IP_ACP,
};
+static int exynos5250_clk_suspend(void)
+{
+ samsung_clk_save(reg_base, exynos5250_save,
+ ARRAY_SIZE(exynos5250_clk_regs));
+
+ return 0;
+}
+
+static void exynos5250_clk_resume(void)
+{
+ samsung_clk_restore(reg_base, exynos5250_save,
+ ARRAY_SIZE(exynos5250_clk_regs));
+}
+
+static struct syscore_ops exynos5250_clk_syscore_ops = {
+ .suspend = exynos5250_clk_suspend,
+ .resume = exynos5250_clk_resume,
+};
+
+static void exynos5250_clk_sleep_init(void)
+{
+ exynos5250_save = samsung_clk_alloc_reg_dump(exynos5250_clk_regs,
+ ARRAY_SIZE(exynos5250_clk_regs));
+ if (!exynos5250_save) {
+ pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
+ __func__);
+ return;
+ }
+
+ register_syscore_ops(&exynos5250_clk_syscore_ops);
+}
+#else
+static void exynos5250_clk_sleep_init(void) {}
+#endif
+
/* list of all parent clock list */
PNAME(mout_apll_p) = { "fin_pll", "fout_apll", };
PNAME(mout_cpu_p) = { "mout_apll", "mout_mpll", };
@@ -645,8 +686,6 @@ static struct of_device_id ext_clk_match[] __initdata = {
/* register exynox5250 clocks */
static void __init exynos5250_clk_init(struct device_node *np)
{
- void __iomem *reg_base;
-
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
@@ -655,9 +694,7 @@ static void __init exynos5250_clk_init(struct device_node *np)
panic("%s: unable to determine soc\n", __func__);
}
- samsung_clk_init(np, reg_base, CLK_NR_CLKS,
- exynos5250_clk_regs, ARRAY_SIZE(exynos5250_clk_regs),
- NULL, 0);
+ samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0);
samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
ext_clk_match);
@@ -685,6 +722,8 @@ static void __init exynos5250_clk_init(struct device_node *np)
samsung_clk_register_gate(exynos5250_gate_clks,
ARRAY_SIZE(exynos5250_gate_clks));
+ exynos5250_clk_sleep_init();
+
pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
_get_rate("div_arm2"));
}
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index c0a716b..ec761e3 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -38,8 +38,9 @@ void samsung_clk_restore(void __iomem *base,
writel(rd->value, base + rd->offset);
}
-struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(unsigned long *rdump,
- unsigned long nr_rdump)
+struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
+ const unsigned long *rdump,
+ unsigned long nr_rdump)
{
struct samsung_clk_reg_dump *rd;
unsigned int i;
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index ec8d46b..93cb8a0 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -347,7 +347,7 @@ extern void samsung_clk_restore(void __iomem *base,
const struct samsung_clk_reg_dump *rd,
unsigned int num_regs);
extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
- unsigned long *rdump,
- unsigned long nr_rdump);
+ const unsigned long *rdump,
+ unsigned long nr_rdump);
#endif /* __SAMSUNG_CLK_H */
--
1.8.5.2
^ permalink raw reply related
* [PATCH v2 5/9] clk: samsung: exynos5420: Move suspend/resume handling to SoC driver
From: Tomasz Figa @ 2014-02-06 18:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710616-14226-1-git-send-email-t.figa@samsung.com>
Since there are multiple differences in how suspend/resume of particular
Exynos SoCs must be handled, SoC driver is better place for
suspend/resume handlers and so this patch moves them.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/clk/samsung/clk-exynos5420.c | 49 ++++++++++++++++++++++++++++++++----
1 file changed, 44 insertions(+), 5 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index ab4f2f7..8ce0780 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -16,6 +16,7 @@
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
#include "clk.h"
@@ -108,6 +109,11 @@ enum exynos5420_plls {
nr_plls /* number of PLLs */
};
+static void __iomem *reg_base;
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *exynos5420_save;
+
/*
* list of controller registers to be saved and restored during a
* suspend/resume cycle.
@@ -174,6 +180,41 @@ static unsigned long exynos5420_clk_regs[] __initdata = {
DIV_KFC0,
};
+static int exynos5420_clk_suspend(void)
+{
+ samsung_clk_save(reg_base, exynos5420_save,
+ ARRAY_SIZE(exynos5420_clk_regs));
+
+ return 0;
+}
+
+static void exynos5420_clk_resume(void)
+{
+ samsung_clk_restore(reg_base, exynos5420_save,
+ ARRAY_SIZE(exynos5420_clk_regs));
+}
+
+static struct syscore_ops exynos5420_clk_syscore_ops = {
+ .suspend = exynos5420_clk_suspend,
+ .resume = exynos5420_clk_resume,
+};
+
+static void exynos5420_clk_sleep_init(void)
+{
+ exynos5420_save = samsung_clk_alloc_reg_dump(exynos5420_clk_regs,
+ ARRAY_SIZE(exynos5420_clk_regs));
+ if (!exynos5420_save) {
+ pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
+ __func__);
+ return;
+ }
+
+ register_syscore_ops(&exynos5420_clk_syscore_ops);
+}
+#else
+static void exynos5420_clk_sleep_init(void) {}
+#endif
+
/* list of all parent clocks */
PNAME(mspll_cpu_p) = { "sclk_cpll", "sclk_dpll",
"sclk_mpll", "sclk_spll" };
@@ -737,8 +778,6 @@ static struct of_device_id ext_clk_match[] __initdata = {
/* register exynos5420 clocks */
static void __init exynos5420_clk_init(struct device_node *np)
{
- void __iomem *reg_base;
-
if (np) {
reg_base = of_iomap(np, 0);
if (!reg_base)
@@ -747,9 +786,7 @@ static void __init exynos5420_clk_init(struct device_node *np)
panic("%s: unable to determine soc\n", __func__);
}
- samsung_clk_init(np, reg_base, CLK_NR_CLKS,
- exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs),
- NULL, 0);
+ samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0);
samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
ext_clk_match);
@@ -765,5 +802,7 @@ static void __init exynos5420_clk_init(struct device_node *np)
ARRAY_SIZE(exynos5420_div_clks));
samsung_clk_register_gate(exynos5420_gate_clks,
ARRAY_SIZE(exynos5420_gate_clks));
+
+ exynos5420_clk_sleep_init();
}
CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init);
--
1.8.5.2
^ permalink raw reply related
* [PATCH v2 6/9] clk: samsung: s3c64xx: Move suspend/resume handling to SoC driver
From: Tomasz Figa @ 2014-02-06 18:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710616-14226-1-git-send-email-t.figa@samsung.com>
Since there are multiple differences in how suspend/resume of particular
Exynos SoCs must be handled, SoC driver is better place for
suspend/resume handlers and so this patch moves them.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/clk/samsung/clk-s3c64xx.c | 79 +++++++++++++++++++++++++++++++++------
1 file changed, 68 insertions(+), 11 deletions(-)
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index 8e27aee..d3fbfa5 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -13,6 +13,7 @@
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
#include <dt-bindings/clock/samsung,s3c64xx-clock.h>
@@ -61,6 +62,13 @@ enum s3c64xx_plls {
apll, mpll, epll,
};
+static void __iomem *reg_base;
+static bool is_s3c6400;
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *s3c64xx_save_common;
+static struct samsung_clk_reg_dump *s3c64xx_save_soc;
+
/*
* List of controller registers to be saved and restored during
* a suspend/resume cycle.
@@ -87,6 +95,60 @@ static unsigned long s3c6410_clk_regs[] __initdata = {
MEM0_GATE,
};
+static int s3c64xx_clk_suspend(void)
+{
+ samsung_clk_save(reg_base, s3c64xx_save_common,
+ ARRAY_SIZE(s3c64xx_clk_regs));
+
+ if (!is_s3c6400)
+ samsung_clk_save(reg_base, s3c64xx_save_soc,
+ ARRAY_SIZE(s3c6410_clk_regs));
+
+ return 0;
+}
+
+static void s3c64xx_clk_resume(void)
+{
+ samsung_clk_restore(reg_base, s3c64xx_save_common,
+ ARRAY_SIZE(s3c64xx_clk_regs));
+
+ if (!is_s3c6400)
+ samsung_clk_restore(reg_base, s3c64xx_save_soc,
+ ARRAY_SIZE(s3c6410_clk_regs));
+}
+
+static struct syscore_ops s3c64xx_clk_syscore_ops = {
+ .suspend = s3c64xx_clk_suspend,
+ .resume = s3c64xx_clk_resume,
+};
+
+static void s3c64xx_clk_sleep_init(void)
+{
+ s3c64xx_save_common = samsung_clk_alloc_reg_dump(s3c64xx_clk_regs,
+ ARRAY_SIZE(s3c64xx_clk_regs));
+ if (!s3c64xx_save_common)
+ goto err_warn;
+
+ if (!is_s3c6400) {
+ s3c64xx_save_soc = samsung_clk_alloc_reg_dump(s3c6410_clk_regs,
+ ARRAY_SIZE(s3c6410_clk_regs));
+ if (!s3c64xx_save_soc)
+ goto err_soc;
+ }
+
+ register_syscore_ops(&s3c64xx_clk_syscore_ops);
+ return;
+
+err_soc:
+ kfree(s3c64xx_save_common);
+err_warn:
+ pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
+ __func__);
+}
+#else
+static void s3c64xx_clk_sleep_init(void) {}
+#endif
+
/* List of parent clocks common for all S3C64xx SoCs. */
PNAME(spi_mmc_p) = { "mout_epll", "dout_mpll", "fin_pll", "clk27m" };
PNAME(uart_p) = { "mout_epll", "dout_mpll" };
@@ -391,11 +453,11 @@ static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f,
/* Register s3c64xx clocks. */
void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
- unsigned long xusbxti_f, bool is_s3c6400,
- void __iomem *reg_base)
+ unsigned long xusbxti_f, bool s3c6400,
+ void __iomem *base)
{
- unsigned long *soc_regs = NULL;
- unsigned long nr_soc_regs = 0;
+ reg_base = base;
+ is_s3c6400 = s3c6400;
if (np) {
reg_base = of_iomap(np, 0);
@@ -403,13 +465,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
panic("%s: failed to map registers\n", __func__);
}
- if (!is_s3c6400) {
- soc_regs = s3c6410_clk_regs;
- nr_soc_regs = ARRAY_SIZE(s3c6410_clk_regs);
- }
-
- samsung_clk_init(np, reg_base, NR_CLKS, s3c64xx_clk_regs,
- ARRAY_SIZE(s3c64xx_clk_regs), soc_regs, nr_soc_regs);
+ samsung_clk_init(np, reg_base, NR_CLKS, NULL, 0, NULL, 0);
/* Register external clocks. */
if (!np)
@@ -452,6 +508,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
samsung_clk_register_alias(s3c64xx_clock_aliases,
ARRAY_SIZE(s3c64xx_clock_aliases));
+ s3c64xx_clk_sleep_init();
pr_info("%s clocks: apll = %lu, mpll = %lu\n"
"\tepll = %lu, arm_clk = %lu\n",
--
1.8.5.2
^ permalink raw reply related
* [PATCH v2 7/9] clk: samsung: Drop old suspend/resume code
From: Tomasz Figa @ 2014-02-06 18:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710616-14226-1-git-send-email-t.figa@samsung.com>
Since all SoC drivers have been moved to local suspend/resume handling,
the old code can be safely dropped.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/clk/samsung/clk-exynos4.c | 2 +-
drivers/clk/samsung/clk-exynos5250.c | 2 +-
drivers/clk/samsung/clk-exynos5420.c | 2 +-
drivers/clk/samsung/clk-exynos5440.c | 2 +-
drivers/clk/samsung/clk-s3c64xx.c | 2 +-
drivers/clk/samsung/clk.c | 54 +-----------------------------------
drivers/clk/samsung/clk.h | 4 +--
7 files changed, 7 insertions(+), 61 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 325f292..b620a83 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -1122,7 +1122,7 @@ static void __init exynos4_clk_init(struct device_node *np,
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
- samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0);
+ samsung_clk_init(np, reg_base, CLK_NR_CLKS);
samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks,
ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index b3cccf0..e7ee442 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -694,7 +694,7 @@ static void __init exynos5250_clk_init(struct device_node *np)
panic("%s: unable to determine soc\n", __func__);
}
- samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0);
+ samsung_clk_init(np, reg_base, CLK_NR_CLKS);
samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
ext_clk_match);
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 8ce0780..60b2681 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -786,7 +786,7 @@ static void __init exynos5420_clk_init(struct device_node *np)
panic("%s: unable to determine soc\n", __func__);
}
- samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0);
+ samsung_clk_init(np, reg_base, CLK_NR_CLKS);
samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
ext_clk_match);
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
index cbc15b5..2bfad5a 100644
--- a/drivers/clk/samsung/clk-exynos5440.c
+++ b/drivers/clk/samsung/clk-exynos5440.c
@@ -101,7 +101,7 @@ static void __init exynos5440_clk_init(struct device_node *np)
return;
}
- samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0);
+ samsung_clk_init(np, reg_base, CLK_NR_CLKS);
samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index d3fbfa5..8bda658 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -465,7 +465,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
panic("%s: failed to map registers\n", __func__);
}
- samsung_clk_init(np, reg_base, NR_CLKS, NULL, 0, NULL, 0);
+ samsung_clk_init(np, reg_base, NR_CLKS);
/* Register external clocks. */
if (!np)
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index ec761e3..91bec3e 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -21,7 +21,6 @@ static void __iomem *reg_base;
static struct clk_onecell_data clk_data;
#endif
-#ifdef CONFIG_PM_SLEEP
void samsung_clk_save(void __iomem *base,
struct samsung_clk_reg_dump *rd,
unsigned int num_regs)
@@ -55,63 +54,12 @@ struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
return rd;
}
-static struct samsung_clk_reg_dump *reg_dump;
-static unsigned long nr_reg_dump;
-
-static int samsung_clk_suspend(void)
-{
- struct samsung_clk_reg_dump *rd = reg_dump;
- unsigned long i;
-
- for (i = 0; i < nr_reg_dump; i++, rd++)
- rd->value = __raw_readl(reg_base + rd->offset);
-
- return 0;
-}
-
-static void samsung_clk_resume(void)
-{
- struct samsung_clk_reg_dump *rd = reg_dump;
- unsigned long i;
-
- for (i = 0; i < nr_reg_dump; i++, rd++)
- __raw_writel(rd->value, reg_base + rd->offset);
-}
-
-static struct syscore_ops samsung_clk_syscore_ops = {
- .suspend = samsung_clk_suspend,
- .resume = samsung_clk_resume,
-};
-#endif /* CONFIG_PM_SLEEP */
-
/* setup the essentials required to support clock lookup using ccf */
void __init samsung_clk_init(struct device_node *np, void __iomem *base,
- unsigned long nr_clks, unsigned long *rdump,
- unsigned long nr_rdump, unsigned long *soc_rdump,
- unsigned long nr_soc_rdump)
+ unsigned long nr_clks)
{
reg_base = base;
-#ifdef CONFIG_PM_SLEEP
- if (rdump && nr_rdump) {
- unsigned int idx;
- reg_dump = kzalloc(sizeof(struct samsung_clk_reg_dump)
- * (nr_rdump + nr_soc_rdump), GFP_KERNEL);
- if (!reg_dump) {
- pr_err("%s: memory alloc for register dump failed\n",
- __func__);
- return;
- }
-
- for (idx = 0; idx < nr_rdump; idx++)
- reg_dump[idx].offset = rdump[idx];
- for (idx = 0; idx < nr_soc_rdump; idx++)
- reg_dump[nr_rdump + idx].offset = soc_rdump[idx];
- nr_reg_dump = nr_rdump + nr_soc_rdump;
- register_syscore_ops(&samsung_clk_syscore_ops);
- }
-#endif
-
clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
if (!clk_table)
panic("could not allocate clock lookup table\n");
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 93cb8a0..c7141ba 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -313,9 +313,7 @@ struct samsung_pll_clock {
_lock, _con, _rtable, _alias)
extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
- unsigned long nr_clks, unsigned long *rdump,
- unsigned long nr_rdump, unsigned long *soc_rdump,
- unsigned long nr_soc_rdump);
+ unsigned long nr_clks);
extern void __init samsung_clk_of_register_fixed_ext(
struct samsung_fixed_rate_clock *fixed_rate_clk,
unsigned int nr_fixed_rate_clk,
--
1.8.5.2
^ permalink raw reply related
* [PATCH v2 8/9] clk: samsung: exynos4: Add remaining suspend/resume handling
From: Tomasz Figa @ 2014-02-06 18:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710616-14226-1-git-send-email-t.figa@samsung.com>
As of now, part of Exynos4 clock suspend/resume handling is located
in mach-exynos/pm.c, which is not where code accessing CMU registers
should reside.
This patch implements all the necessary suspend/resume handling code
in Exynos4 clock driver to allow dropping that old code.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/clk/samsung/clk-exynos4.c | 76 ++++++++++++++++++++++++++++++++++-----
1 file changed, 68 insertions(+), 8 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index b620a83..b4f9672 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -140,6 +140,7 @@ static enum exynos4_soc exynos4_soc;
#ifdef CONFIG_PM_SLEEP
static struct samsung_clk_reg_dump *exynos4_save_common;
static struct samsung_clk_reg_dump *exynos4_save_soc;
+static struct samsung_clk_reg_dump *exynos4_save_pll;
/*
* list of controller registers to be saved and restored during a
@@ -165,6 +166,17 @@ static unsigned long exynos4x12_clk_save[] __initdata = {
E4X12_MPLL_CON0,
};
+static unsigned long exynos4_clk_pll_regs[] __initdata = {
+ EPLL_LOCK,
+ VPLL_LOCK,
+ EPLL_CON0,
+ EPLL_CON1,
+ EPLL_CON2,
+ VPLL_CON0,
+ VPLL_CON1,
+ VPLL_CON2,
+};
+
static unsigned long exynos4_clk_regs[] __initdata = {
SRC_LEFTBUS,
DIV_LEFTBUS,
@@ -172,12 +184,6 @@ static unsigned long exynos4_clk_regs[] __initdata = {
SRC_RIGHTBUS,
DIV_RIGHTBUS,
GATE_IP_RIGHTBUS,
- EPLL_CON0,
- EPLL_CON1,
- EPLL_CON2,
- VPLL_CON0,
- VPLL_CON1,
- VPLL_CON2,
SRC_TOP0,
SRC_TOP1,
SRC_CAM,
@@ -238,23 +244,70 @@ static unsigned long exynos4_clk_regs[] __initdata = {
GATE_IP_CPU,
};
+static const struct samsung_clk_reg_dump src_mask_suspend[] = {
+ { .offset = SRC_MASK_TOP, .value = 0x00000001, },
+ { .offset = SRC_MASK_CAM, .value = 0x11111111, },
+ { .offset = SRC_MASK_TV, .value = 0x00000111, },
+ { .offset = SRC_MASK_LCD0, .value = 0x00001111, },
+ { .offset = SRC_MASK_MAUDIO, .value = 0x00000001, },
+ { .offset = SRC_MASK_FSYS, .value = 0x01011111, },
+ { .offset = SRC_MASK_PERIL0, .value = 0x01111111, },
+ { .offset = SRC_MASK_PERIL1, .value = 0x01110111, },
+ { .offset = SRC_MASK_DMC, .value = 0x00010000, },
+};
+
+static const struct samsung_clk_reg_dump src_mask_suspend_e4210[] = {
+ { .offset = E4210_SRC_MASK_LCD1, .value = 0x00001111, },
+};
+
+#define PLL_ENABLED (1 << 31)
+#define PLL_LOCKED (1 << 29)
+
+static void exynos4_clk_wait_for_pll(u32 reg)
+{
+ u32 pll_con;
+
+ pll_con = readl(reg_base + reg);
+ if (!(pll_con & PLL_ENABLED))
+ return;
+
+ while (!(pll_con & PLL_LOCKED)) {
+ cpu_relax();
+ pll_con = readl(reg_base + reg);
+ }
+}
+
static int exynos4_clk_suspend(void)
{
samsung_clk_save(reg_base, exynos4_save_common,
ARRAY_SIZE(exynos4_clk_regs));
+ samsung_clk_save(reg_base, exynos4_save_pll,
+ ARRAY_SIZE(exynos4_clk_pll_regs));
- if (exynos4_soc == EXYNOS4210)
+ if (exynos4_soc == EXYNOS4210) {
samsung_clk_save(reg_base, exynos4_save_soc,
ARRAY_SIZE(exynos4210_clk_save));
- else
+ samsung_clk_restore(reg_base, src_mask_suspend_e4210,
+ ARRAY_SIZE(src_mask_suspend_e4210));
+ } else {
samsung_clk_save(reg_base, exynos4_save_soc,
ARRAY_SIZE(exynos4x12_clk_save));
+ }
+
+ samsung_clk_restore(reg_base, src_mask_suspend,
+ ARRAY_SIZE(src_mask_suspend));
return 0;
}
static void exynos4_clk_resume(void)
{
+ samsung_clk_restore(reg_base, exynos4_save_pll,
+ ARRAY_SIZE(exynos4_clk_pll_regs));
+
+ exynos4_clk_wait_for_pll(EPLL_CON0);
+ exynos4_clk_wait_for_pll(VPLL_CON0);
+
samsung_clk_restore(reg_base, exynos4_save_common,
ARRAY_SIZE(exynos4_clk_regs));
@@ -289,9 +342,16 @@ static void exynos4_clk_sleep_init(void)
if (!exynos4_save_soc)
goto err_common;
+ exynos4_save_pll = samsung_clk_alloc_reg_dump(exynos4_clk_pll_regs,
+ ARRAY_SIZE(exynos4_clk_pll_regs));
+ if (!exynos4_save_pll)
+ goto err_soc;
+
register_syscore_ops(&exynos4_clk_syscore_ops);
return;
+err_soc:
+ kfree(exynos4_save_soc);
err_common:
kfree(exynos4_save_common);
err_warn:
--
1.8.5.2
^ permalink raw reply related
* [PATCH v2 9/9] ARM: EXYNOS: pm: Drop legacy Exynos4 clock suspend/resume code
From: Tomasz Figa @ 2014-02-06 18:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391710616-14226-1-git-send-email-t.figa@samsung.com>
All the suspend/resume handling is already implemented in Exynos4 clock
driver, so this legacy code can be safely dropped.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/mach-exynos/pm.c | 148 +---------------------------------------------
1 file changed, 2 insertions(+), 146 deletions(-)
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index e00025b..ba18214 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -35,56 +35,6 @@
#include "common.h"
#include "regs-pmu.h"
-#define EXYNOS4_EPLL_LOCK (S5P_VA_CMU + 0x0C010)
-#define EXYNOS4_VPLL_LOCK (S5P_VA_CMU + 0x0C020)
-
-#define EXYNOS4_EPLL_CON0 (S5P_VA_CMU + 0x0C110)
-#define EXYNOS4_EPLL_CON1 (S5P_VA_CMU + 0x0C114)
-#define EXYNOS4_VPLL_CON0 (S5P_VA_CMU + 0x0C120)
-#define EXYNOS4_VPLL_CON1 (S5P_VA_CMU + 0x0C124)
-
-#define EXYNOS4_CLKSRC_MASK_TOP (S5P_VA_CMU + 0x0C310)
-#define EXYNOS4_CLKSRC_MASK_CAM (S5P_VA_CMU + 0x0C320)
-#define EXYNOS4_CLKSRC_MASK_TV (S5P_VA_CMU + 0x0C324)
-#define EXYNOS4_CLKSRC_MASK_LCD0 (S5P_VA_CMU + 0x0C334)
-#define EXYNOS4_CLKSRC_MASK_MAUDIO (S5P_VA_CMU + 0x0C33C)
-#define EXYNOS4_CLKSRC_MASK_FSYS (S5P_VA_CMU + 0x0C340)
-#define EXYNOS4_CLKSRC_MASK_PERIL0 (S5P_VA_CMU + 0x0C350)
-#define EXYNOS4_CLKSRC_MASK_PERIL1 (S5P_VA_CMU + 0x0C354)
-
-#define EXYNOS4_CLKSRC_MASK_DMC (S5P_VA_CMU + 0x10300)
-
-#define EXYNOS4_EPLLCON0_LOCKED_SHIFT (29)
-#define EXYNOS4_VPLLCON0_LOCKED_SHIFT (29)
-
-#define EXYNOS4210_CLKSRC_MASK_LCD1 (S5P_VA_CMU + 0x0C338)
-
-static const struct sleep_save exynos4_set_clksrc[] = {
- { .reg = EXYNOS4_CLKSRC_MASK_TOP , .val = 0x00000001, },
- { .reg = EXYNOS4_CLKSRC_MASK_CAM , .val = 0x11111111, },
- { .reg = EXYNOS4_CLKSRC_MASK_TV , .val = 0x00000111, },
- { .reg = EXYNOS4_CLKSRC_MASK_LCD0 , .val = 0x00001111, },
- { .reg = EXYNOS4_CLKSRC_MASK_MAUDIO , .val = 0x00000001, },
- { .reg = EXYNOS4_CLKSRC_MASK_FSYS , .val = 0x01011111, },
- { .reg = EXYNOS4_CLKSRC_MASK_PERIL0 , .val = 0x01111111, },
- { .reg = EXYNOS4_CLKSRC_MASK_PERIL1 , .val = 0x01110111, },
- { .reg = EXYNOS4_CLKSRC_MASK_DMC , .val = 0x00010000, },
-};
-
-static const struct sleep_save exynos4210_set_clksrc[] = {
- { .reg = EXYNOS4210_CLKSRC_MASK_LCD1 , .val = 0x00001111, },
-};
-
-static struct sleep_save exynos4_epll_save[] = {
- SAVE_ITEM(EXYNOS4_EPLL_CON0),
- SAVE_ITEM(EXYNOS4_EPLL_CON1),
-};
-
-static struct sleep_save exynos4_vpll_save[] = {
- SAVE_ITEM(EXYNOS4_VPLL_CON0),
- SAVE_ITEM(EXYNOS4_VPLL_CON1),
-};
-
static struct sleep_save exynos5_sys_save[] = {
SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
};
@@ -124,10 +74,7 @@ static void exynos_pm_prepare(void)
s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
- if (!soc_is_exynos5250()) {
- s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save));
- s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save));
- } else {
+ if (soc_is_exynos5250()) {
s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save));
/* Disable USE_RETENTION of JPEG_MEM_OPTION */
tmp = __raw_readl(EXYNOS5_JPEG_MEM_OPTION);
@@ -143,15 +90,6 @@ static void exynos_pm_prepare(void)
/* ensure at least INFORM0 has the resume address */
__raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
-
- /* Before enter central sequence mode, clock src register have to set */
-
- if (!soc_is_exynos5250())
- s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc));
-
- if (soc_is_exynos4210())
- s3c_pm_do_restore_core(exynos4210_set_clksrc, ARRAY_SIZE(exynos4210_set_clksrc));
-
}
static int exynos_pm_add(struct device *dev, struct subsys_interface *sif)
@@ -162,73 +100,6 @@ static int exynos_pm_add(struct device *dev, struct subsys_interface *sif)
return 0;
}
-static unsigned long pll_base_rate;
-
-static void exynos4_restore_pll(void)
-{
- unsigned long pll_con, locktime, lockcnt;
- unsigned long pll_in_rate;
- unsigned int p_div, epll_wait = 0, vpll_wait = 0;
-
- if (pll_base_rate == 0)
- return;
-
- pll_in_rate = pll_base_rate;
-
- /* EPLL */
- pll_con = exynos4_epll_save[0].val;
-
- if (pll_con & (1 << 31)) {
- pll_con &= (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT);
- p_div = (pll_con >> PLL46XX_PDIV_SHIFT);
-
- pll_in_rate /= 1000000;
-
- locktime = (3000 / pll_in_rate) * p_div;
- lockcnt = locktime * 10000 / (10000 / pll_in_rate);
-
- __raw_writel(lockcnt, EXYNOS4_EPLL_LOCK);
-
- s3c_pm_do_restore_core(exynos4_epll_save,
- ARRAY_SIZE(exynos4_epll_save));
- epll_wait = 1;
- }
-
- pll_in_rate = pll_base_rate;
-
- /* VPLL */
- pll_con = exynos4_vpll_save[0].val;
-
- if (pll_con & (1 << 31)) {
- pll_in_rate /= 1000000;
- /* 750us */
- locktime = 750;
- lockcnt = locktime * 10000 / (10000 / pll_in_rate);
-
- __raw_writel(lockcnt, EXYNOS4_VPLL_LOCK);
-
- s3c_pm_do_restore_core(exynos4_vpll_save,
- ARRAY_SIZE(exynos4_vpll_save));
- vpll_wait = 1;
- }
-
- /* Wait PLL locking */
-
- do {
- if (epll_wait) {
- pll_con = __raw_readl(EXYNOS4_EPLL_CON0);
- if (pll_con & (1 << EXYNOS4_EPLLCON0_LOCKED_SHIFT))
- epll_wait = 0;
- }
-
- if (vpll_wait) {
- pll_con = __raw_readl(EXYNOS4_VPLL_CON0);
- if (pll_con & (1 << EXYNOS4_VPLLCON0_LOCKED_SHIFT))
- vpll_wait = 0;
- }
- } while (epll_wait || vpll_wait);
-}
-
static struct subsys_interface exynos_pm_interface = {
.name = "exynos_pm",
.subsys = &exynos_subsys,
@@ -237,7 +108,6 @@ static struct subsys_interface exynos_pm_interface = {
static __init int exynos_pm_drvinit(void)
{
- struct clk *pll_base;
unsigned int tmp;
if (soc_is_exynos5440())
@@ -251,15 +121,6 @@ static __init int exynos_pm_drvinit(void)
tmp |= ((0xFF << 8) | (0x1F << 1));
__raw_writel(tmp, S5P_WAKEUP_MASK);
- if (!soc_is_exynos5250()) {
- pll_base = clk_get(NULL, "xtal");
-
- if (!IS_ERR(pll_base)) {
- pll_base_rate = clk_get_rate(pll_base);
- clk_put(pll_base);
- }
- }
-
return subsys_interface_register(&exynos_pm_interface);
}
arch_initcall(exynos_pm_drvinit);
@@ -343,13 +204,8 @@ static void exynos_pm_resume(void)
s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
- if (!soc_is_exynos5250()) {
- exynos4_restore_pll();
-
-#ifdef CONFIG_SMP
+ if (IS_ENABLED(CONFIG_SMP) && !soc_is_exynos5250())
scu_enable(S5P_VA_SCU);
-#endif
- }
early_wakeup:
--
1.8.5.2
^ 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