* [PATCH v3 00/22] PCI: Iterate pci host bridge instead of pci root bus
From: Yinghai Lu @ 2013-01-27 19:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAE9FiQXHG01NjnYNDbC-KEpbcvY-q4pBe97CxTOGS7W4vZQBYQ@mail.gmail.com>
Now we have pci_root_buses list, and there is lots of iteration with
list_of_each of it, that is not safe after we add pci root bus hotplug
support after booting stage.
Add pci_get_next_host_bridge and use bus_find_device in driver core to
iterate host bridge and the same time get root bus.
We replace searching root bus with searching host_bridge,
as host_bridge->bus is the root bus.
After those replacing, we even could kill pci_root_buses list.
based on pci/next
could get from
git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-for-each-host-bridge
-v2: updated after pci_root_bus_hotplug get into pci/next
-v3: update changelog and add cc for pci core change for arch guys.
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
Cc: Doug Thompson <dougthompson@xmission.com>
Cc: linux-edac at vger.kernel.org
Cc: x86 at kernel.org
Cc: David Airlie <airlied@linux.ie>
Cc: dri-devel at lists.freedesktop.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux at vger.kernel.org
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: linux-ia64 at vger.kernel.org
Cc: linux-altix at sgi.com
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: linux-alpha at vger.kernel.org
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-arm-kernel at lists.infradead.org
Cc: David Howells <dhowells@redhat.com>
Cc: Michal Simek <monstr@monstr.eu>
Cc: microblaze-uclinux at itee.uq.edu.au
Cc: Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
Cc: linux-am33-list at redhat.com
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev at lists.ozlabs.org
Yinghai Lu (22):
PCI: Rename pci_release_bus_bridge_dev to pci_release_host_bridge_dev
PCI: Add dummy bus_type for pci_host_bridge
PCI, libata: remove find_bridge in acpi_bus_type
PCI, ACPI: Update comments for find_bridge in acpi_bus_type
PCI: Add for_each_pci_host_bridge() and pci_get_next_host_bridge
PCI, hotplug: Kill pci_find_next_bus in sgi_hotplug
PCI: Kill pci_find_next_bus in pci_sysfs
PCI, edac: Kill pci_find_next_bus in edac
PCI, x86: Kill pci_find_next_bus in pcibios_scan_root
PCI, x86: Kill pci_root_buses in resources reservations
PCI, drm: Kill pci_root_buses in alpha hose setting
PCI: Kill pci_root_buses in setup-bus
PCI, sparc: Kill pci_find_next_bus
PCI, ia64: Kill pci_find_next_bus
PCI, alpha: Kill pci_root_buses
PCI, arm: Kill pci_root_buses
PCI, frv: Kill pci_root_buses in resources reservations
PCI, microblaze: Kill pci_root_buses in resources reservations
PCI, mn10300: Kill pci_root_buses in resources reservations
PCI, powerpc: Kill pci_root_buses in resources reservations
PCI: Kill pci_find_next_bus
PCI: Kill pci_root_buses
arch/alpha/kernel/pci.c | 6 +--
arch/arm/kernel/bios32.c | 9 ++---
arch/frv/mb93090-mb00/pci-frv.c | 37 +++++++++---------
arch/ia64/hp/common/sba_iommu.c | 7 ++--
arch/ia64/sn/kernel/io_common.c | 5 ++-
arch/microblaze/pci/pci-common.c | 10 ++---
arch/mn10300/unit-asb2305/pci-asb2305.c | 62 ++++++++++++++++---------------
arch/powerpc/kernel/pci-common.c | 13 +++----
arch/powerpc/kernel/pci_64.c | 8 ++--
arch/sparc/kernel/pci.c | 6 ++-
arch/x86/pci/common.c | 9 +++--
arch/x86/pci/i386.c | 20 +++++-----
drivers/ata/libata-acpi.c | 6 ---
drivers/edac/i7core_edac.c | 6 +--
drivers/gpu/drm/drm_fops.c | 10 +++--
drivers/pci/hotplug/sgi_hotplug.c | 6 ++-
drivers/pci/pci-driver.c | 11 +++++-
drivers/pci/pci-sysfs.c | 6 +--
drivers/pci/probe.c | 13 ++-----
drivers/pci/search.c | 61 +++++++++++++++---------------
drivers/pci/setup-bus.c | 24 ++++++------
include/acpi/acpi_bus.h | 2 +-
include/linux/pci.h | 18 +++++----
23 files changed, 187 insertions(+), 168 deletions(-)
--
1.7.10.4
^ permalink raw reply
* [PATCH v3 02/22] PCI: Add dummy bus_type for pci_host_bridge
From: Yinghai Lu @ 2013-01-27 19:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359314629-18651-1-git-send-email-yinghai@kernel.org>
Need to use it for looping registered host_bridge, and kill
pci_root_buses list.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
Cc: Doug Thompson <dougthompson@xmission.com>
Cc: linux-edac at vger.kernel.org
Cc: x86 at kernel.org
Cc: David Airlie <airlied@linux.ie>
Cc: dri-devel at lists.freedesktop.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux at vger.kernel.org
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: linux-ia64 at vger.kernel.org
Cc: linux-altix at sgi.com
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: linux-alpha at vger.kernel.org
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-arm-kernel at lists.infradead.org
Cc: David Howells <dhowells@redhat.com>
Cc: Michal Simek <monstr@monstr.eu>
Cc: microblaze-uclinux at itee.uq.edu.au
Cc: Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
Cc: linux-am33-list at redhat.com
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev at lists.ozlabs.org
---
drivers/pci/pci-driver.c | 11 ++++++++++-
drivers/pci/probe.c | 1 +
include/linux/pci.h | 2 ++
3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index acdcc3c..9fb004b 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -1278,11 +1278,20 @@ struct bus_type pci_bus_type = {
.pm = PCI_PM_OPS_PTR,
};
+struct bus_type pci_host_bridge_bus_type = {
+ .name = "pci_host_bridge",
+};
+
+static int __init pci_host_bridge_driver_init(void)
+{
+ return bus_register(&pci_host_bridge_bus_type);
+}
+postcore_initcall(pci_host_bridge_driver_init);
+
static int __init pci_driver_init(void)
{
return bus_register(&pci_bus_type);
}
-
postcore_initcall(pci_driver_init);
EXPORT_SYMBOL_GPL(pci_add_dynid);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ef50154..04ecf0d 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1692,6 +1692,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
goto err_out;
bridge->dev.parent = parent;
+ bridge->dev.bus = &pci_host_bridge_bus_type;
bridge->dev.release = pci_release_host_bridge_dev;
dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
error = pcibios_root_bridge_prepare(bridge);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 056d3d6..9da06ec 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -669,6 +669,7 @@ enum pcie_bus_config_types {
extern enum pcie_bus_config_types pcie_bus_config;
+extern struct bus_type pci_host_bridge_bus_type;
extern struct bus_type pci_bus_type;
/* Do NOT directly access these two variables, unless you are arch specific pci
@@ -740,6 +741,7 @@ void pci_stop_root_bus(struct pci_bus *bus);
void pci_remove_root_bus(struct pci_bus *bus);
void pci_setup_cardbus(struct pci_bus *bus);
extern void pci_sort_breadthfirst(void);
+#define dev_is_pci_host_bridge(d) ((d)->bus == &pci_host_bridge_bus_type)
#define dev_is_pci(d) ((d)->bus == &pci_bus_type)
#define dev_is_pf(d) ((dev_is_pci(d) ? to_pci_dev(d)->is_physfn : false))
#define dev_num_vf(d) ((dev_is_pci(d) ? pci_num_vf(to_pci_dev(d)) : 0))
--
1.7.10.4
^ permalink raw reply related
* [PATCH v3 05/22] PCI: Add for_each_pci_host_bridge() and pci_get_next_host_bridge
From: Yinghai Lu @ 2013-01-27 19:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359314629-18651-1-git-send-email-yinghai@kernel.org>
Now we have pci_root_buses list, and there is lots of iteration with
list_of_each of it, that is not safe after we add pci root bus hotplug
support after booting stage.
Also pci_find_next_bus is pretty misleading name, and it is only finding
next root bus instead of regular pci bus.
Add pci_get_next_host_bridge and use bus_find_device in driver core to
iterate host bridge and the same time get root bus.
In folllowing patches will replace searching root bus with searching host_bridge.
after using with that host-bridge, will need to call put device to release
reference if break early from the loop.
After those replacing, we even could kill pci_root_buses list.
-v2: fixes compiling error when CONFIG_PCI is not defined that Fengguang Wu found.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
Cc: Doug Thompson <dougthompson@xmission.com>
Cc: linux-edac at vger.kernel.org
Cc: x86 at kernel.org
Cc: David Airlie <airlied@linux.ie>
Cc: dri-devel at lists.freedesktop.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux at vger.kernel.org
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: linux-ia64 at vger.kernel.org
Cc: linux-altix at sgi.com
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: linux-alpha at vger.kernel.org
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-arm-kernel at lists.infradead.org
Cc: David Howells <dhowells@redhat.com>
Cc: Michal Simek <monstr@monstr.eu>
Cc: microblaze-uclinux at itee.uq.edu.au
Cc: Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
Cc: linux-am33-list at redhat.com
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev at lists.ozlabs.org
---
drivers/pci/search.c | 24 ++++++++++++++++++++++++
include/linux/pci.h | 9 +++++++++
2 files changed, 33 insertions(+)
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index d0627fa..db0c3a9 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -178,6 +178,30 @@ struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus,
}
EXPORT_SYMBOL(pci_get_domain_bus_and_slot);
+static int match_pci_host_bridge(struct device *dev, void *data)
+{
+ return 1;
+}
+
+struct pci_host_bridge *pci_get_next_host_bridge(struct pci_host_bridge *from)
+{
+ struct device *dev;
+ struct device *dev_start = NULL;
+ struct pci_host_bridge *bridge = NULL;
+
+ WARN_ON(in_interrupt());
+ if (from)
+ dev_start = &from->dev;
+ dev = bus_find_device(&pci_host_bridge_bus_type, dev_start, NULL,
+ match_pci_host_bridge);
+ if (dev)
+ bridge = to_pci_host_bridge(dev);
+ if (from)
+ put_device(&from->dev);
+ return bridge;
+}
+EXPORT_SYMBOL_GPL(pci_get_next_host_bridge);
+
static int match_pci_dev_by_id(struct device *dev, void *data)
{
struct pci_dev *pdev = to_pci_dev(dev);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 9da06ec..67879cb 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -375,6 +375,8 @@ struct pci_host_bridge {
};
#define to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
+#define for_each_pci_host_bridge(d) while ((d = pci_get_next_host_bridge(d)) != NULL)
+
void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
void (*release_fn)(struct pci_host_bridge *),
void *release_data);
@@ -763,6 +765,7 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
+struct pci_host_bridge *pci_get_next_host_bridge(struct pci_host_bridge *from);
struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
struct pci_dev *from);
struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
@@ -1418,6 +1421,12 @@ static inline int pci_domain_nr(struct pci_bus *bus)
static inline struct pci_dev *pci_dev_get(struct pci_dev *dev)
{ return NULL; }
+static inline struct pci_host_bridge *pci_get_next_host_bridge(
+ struct pci_host_bridge *host_bridge)
+{
+ return NULL;
+}
+
#define dev_is_pci(d) (false)
#define dev_is_pf(d) (false)
#define dev_num_vf(d) (0)
--
1.7.10.4
^ permalink raw reply related
* [PATCH v3 16/22] PCI, arm: Kill pci_root_buses
From: Yinghai Lu @ 2013-01-27 19:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359314629-18651-1-git-send-email-yinghai@kernel.org>
Replace that with hotplug-safe version iteration.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-arm-kernel at lists.infradead.org
---
arch/arm/kernel/bios32.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 9b72261..d0befe4 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -57,13 +57,10 @@ static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, in
void pcibios_report_status(u_int status_mask, int warn)
{
- struct list_head *l;
+ struct pci_host_bridge *host_bridge = NULL;
- list_for_each(l, &pci_root_buses) {
- struct pci_bus *bus = pci_bus_b(l);
-
- pcibios_bus_report_status(bus, status_mask, warn);
- }
+ for_each_pci_host_bridge(host_bridge)
+ pcibios_bus_report_status(host_bridge->bus, status_mask, warn);
}
/*
--
1.7.10.4
^ permalink raw reply related
* [PATCH v3 21/22] PCI: Kill pci_find_next_bus
From: Yinghai Lu @ 2013-01-27 19:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359314629-18651-1-git-send-email-yinghai@kernel.org>
No user now, remove it.
That name is misleading as it only for root buses.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
Cc: Doug Thompson <dougthompson@xmission.com>
Cc: linux-edac at vger.kernel.org
Cc: x86 at kernel.org
Cc: David Airlie <airlied@linux.ie>
Cc: dri-devel at lists.freedesktop.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux at vger.kernel.org
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: linux-ia64 at vger.kernel.org
Cc: linux-altix at sgi.com
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: linux-alpha at vger.kernel.org
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-arm-kernel at lists.infradead.org
Cc: David Howells <dhowells@redhat.com>
Cc: Michal Simek <monstr@monstr.eu>
Cc: microblaze-uclinux at itee.uq.edu.au
Cc: Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
Cc: linux-am33-list at redhat.com
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev at lists.ozlabs.org
---
drivers/pci/search.c | 37 +++++++------------------------------
include/linux/pci.h | 4 ----
2 files changed, 7 insertions(+), 34 deletions(-)
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index db0c3a9..329c533 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -79,44 +79,22 @@ static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
*/
struct pci_bus * pci_find_bus(int domain, int busnr)
{
- struct pci_bus *bus = NULL;
+ struct pci_host_bridge *host_bridge = NULL;
struct pci_bus *tmp_bus;
- while ((bus = pci_find_next_bus(bus)) != NULL) {
- if (pci_domain_nr(bus) != domain)
+ for_each_pci_host_bridge(host_bridge) {
+ if (pci_domain_nr(host_bridge->bus) != domain)
continue;
- tmp_bus = pci_do_find_bus(bus, busnr);
- if (tmp_bus)
+ tmp_bus = pci_do_find_bus(host_bridge->bus, busnr);
+ if (tmp_bus) {
+ put_device(&host_bridge->dev);
return tmp_bus;
+ }
}
return NULL;
}
/**
- * pci_find_next_bus - begin or continue searching for a PCI bus
- * @from: Previous PCI bus found, or %NULL for new search.
- *
- * Iterates through the list of known PCI busses. A new search is
- * initiated by passing %NULL as the @from argument. Otherwise if
- * @from is not %NULL, searches continue from next device on the
- * global list.
- */
-struct pci_bus *
-pci_find_next_bus(const struct pci_bus *from)
-{
- struct list_head *n;
- struct pci_bus *b = NULL;
-
- WARN_ON(in_interrupt());
- down_read(&pci_bus_sem);
- n = from ? from->node.next : pci_root_buses.next;
- if (n != &pci_root_buses)
- b = pci_bus_b(n);
- up_read(&pci_bus_sem);
- return b;
-}
-
-/**
* pci_get_slot - locate PCI device for a given PCI slot
* @bus: PCI bus on which desired PCI device resides
* @devfn: encodes number of PCI slot in which the desired PCI
@@ -356,7 +334,6 @@ EXPORT_SYMBOL(pci_dev_present);
/* For boot time work */
EXPORT_SYMBOL(pci_find_bus);
-EXPORT_SYMBOL(pci_find_next_bus);
/* For everyone */
EXPORT_SYMBOL(pci_get_device);
EXPORT_SYMBOL(pci_get_subsys);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 67879cb..bb07db2 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -763,7 +763,6 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap);
int pci_find_next_ext_capability(struct pci_dev *dev, int pos, int cap);
int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
-struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
struct pci_host_bridge *pci_get_next_host_bridge(struct pci_host_bridge *from);
struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
@@ -1404,9 +1403,6 @@ static inline int pci_block_cfg_access_in_atomic(struct pci_dev *dev)
static inline void pci_unblock_cfg_access(struct pci_dev *dev)
{ }
-static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
-{ return NULL; }
-
static inline struct pci_dev *pci_get_slot(struct pci_bus *bus,
unsigned int devfn)
{ return NULL; }
--
1.7.10.4
^ permalink raw reply related
* [PATCH v3 22/22] PCI: Kill pci_root_buses
From: Yinghai Lu @ 2013-01-27 19:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359314629-18651-1-git-send-email-yinghai@kernel.org>
No user now, remove it.
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
Cc: Doug Thompson <dougthompson@xmission.com>
Cc: linux-edac at vger.kernel.org
Cc: x86 at kernel.org
Cc: David Airlie <airlied@linux.ie>
Cc: dri-devel at lists.freedesktop.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux at vger.kernel.org
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: linux-ia64 at vger.kernel.org
Cc: linux-altix at sgi.com
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: linux-alpha at vger.kernel.org
Cc: Russell King <linux@arm.linux.org.uk>
Cc: linux-arm-kernel at lists.infradead.org
Cc: David Howells <dhowells@redhat.com>
Cc: Michal Simek <monstr@monstr.eu>
Cc: microblaze-uclinux at itee.uq.edu.au
Cc: Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
Cc: linux-am33-list at redhat.com
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev at lists.ozlabs.org
---
drivers/pci/probe.c | 8 --------
include/linux/pci.h | 3 ---
2 files changed, 11 deletions(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 04ecf0d..8420b9d 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -23,10 +23,6 @@ struct resource busn_resource = {
.flags = IORESOURCE_BUS,
};
-/* Ugh. Need to stop exporting this to modules. */
-LIST_HEAD(pci_root_buses);
-EXPORT_SYMBOL(pci_root_buses);
-
static LIST_HEAD(pci_domain_busn_res_list);
struct pci_domain_busn_res {
@@ -1746,10 +1742,6 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
dev_info(&b->dev, "root bus resource %pR%s\n", res, bus_addr);
}
- down_write(&pci_bus_sem);
- list_add_tail(&b->node, &pci_root_buses);
- up_write(&pci_bus_sem);
-
return b;
class_dev_reg_err:
diff --git a/include/linux/pci.h b/include/linux/pci.h
index bb07db2..b42721b 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -674,9 +674,6 @@ extern enum pcie_bus_config_types pcie_bus_config;
extern struct bus_type pci_host_bridge_bus_type;
extern struct bus_type pci_bus_type;
-/* Do NOT directly access these two variables, unless you are arch specific pci
- * code, or pci core code. */
-extern struct list_head pci_root_buses; /* list of all known PCI buses */
/* Some device drivers need know if pci is initiated */
extern int no_pci_devices(void);
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 0/9] ARM: S3C24XX: rework irq handling for a later dt usage
From: Heiko Stübner @ 2013-01-27 20:24 UTC (permalink / raw)
To: linux-arm-kernel
This v4 does not change any code part. The patches are merely rebased
to apply to the next/cleanup-s3c24xx branch as requested.
Heiko Stuebner (9):
ARM: S3C24XX: transform irq handling into a declarative form
ARM: S3C24XX: Move irq syscore-ops to irq-pm
ARM: S3C24XX: Modify s3c_irq_wake to use the hwirq property
ARM: S3C24XX: move s3c2416 irq init to common irq code
ARM: S3C24XX: modify s3c2416 irq init to initialize all irqs
ARM: S3C24XX: transform s3c2416 irqs into new structure
ARM: S3C24XX: move s3c2443 irq code to irq.c
ARM: S3C24XX: modify s3c2443 irq init to initialize all irqs
ARM: S3C24XX: transform s3c2443 subirqs into new structure
arch/arm/mach-s3c24xx/Makefile | 4 +-
arch/arm/mach-s3c24xx/common.h | 2 +
arch/arm/mach-s3c24xx/irq-pm.c | 41 +-
arch/arm/mach-s3c24xx/irq-s3c2416.c | 348 --------
arch/arm/mach-s3c24xx/irq-s3c2443.c | 281 -------
arch/arm/mach-s3c24xx/mach-smdk2416.c | 2 +-
arch/arm/mach-s3c24xx/mach-smdk2443.c | 2 +-
arch/arm/mach-s3c24xx/s3c2410.c | 4 +-
arch/arm/mach-s3c24xx/s3c2412.c | 4 +-
arch/arm/mach-s3c24xx/s3c2416.c | 4 +-
arch/arm/mach-s3c24xx/s3c2440.c | 4 +-
arch/arm/mach-s3c24xx/s3c2442.c | 4 +-
arch/arm/plat-s3c24xx/Kconfig | 1 +
arch/arm/plat-s3c24xx/irq.c | 1110 +++++++++++++++-----------
arch/arm/plat-samsung/include/plat/pm.h | 6 -
arch/arm/plat-samsung/include/plat/s3c2416.h | 1 +
arch/arm/plat-samsung/include/plat/s3c2443.h | 2 +
17 files changed, 688 insertions(+), 1132 deletions(-)
delete mode 100644 arch/arm/mach-s3c24xx/irq-s3c2416.c
delete mode 100644 arch/arm/mach-s3c24xx/irq-s3c2443.c
--
1.7.10.4
^ permalink raw reply
* [PATCH v4 1/9] ARM: S3C24XX: transform irq handling into a declarative form
From: Heiko Stübner @ 2013-01-27 20:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201301272124.18530.heiko@sntech.de>
The irqs available on the machine and even the bit settings in the
irq registers differ a lot through all the s3c24xx subarchitectures.
This results in each subarch having its own irq init which adds its
specific irqs to the base ones created in plat-s3c24xx/irq.c.
This of course makes a future move to devicetree hard to implement.
Therefore this patch transforms the base irq handling to a declarative
style, where the irq types as well as its parent/child relationship
gets read from a predefined datastructure, which later on can hopefully
be easily represented in devicetree too.
It should also be easy to include the subarch specific irqs here
in later patches, reducing code size and duplication.
It should not affect anything outside of the file, as the original
irq numbers and their handling are preserved (hopefully) correctly.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
changes since v2:
- redo the initialization, move parts of the upcoming dt init here
to enable both init variants to share the code
changes since v1:
- more generalized irq types, resulting in only types for
none, eint, edge and level being needed
- use chained_irq_enter/exit to simplify subirq handling
arch/arm/plat-s3c24xx/Kconfig | 1 +
arch/arm/plat-s3c24xx/irq.c | 930 ++++++++++++++++++++---------------------
2 files changed, 445 insertions(+), 486 deletions(-)
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
index eef3b6a..3bb5c8f 100644
--- a/arch/arm/plat-s3c24xx/Kconfig
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -9,6 +9,7 @@ config PLAT_S3C24XX
select ARCH_REQUIRE_GPIOLIB
select NO_IOPORT
select S3C_DEV_NAND
+ select IRQ_DOMAIN
help
Base platform code for any Samsung S3C24XX device
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
index fe57bbb..9e24ef5 100644
--- a/arch/arm/plat-s3c24xx/irq.c
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -1,7 +1,9 @@
-/* linux/arch/arm/plat-s3c24xx/irq.c
+/*
+ * S3C24XX IRQ handling
*
* Copyright (c) 2003-2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2012 Heiko Stuebner <heiko@sntech.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -12,175 +14,124 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/syscore_ops.h>
+#include <linux/irqdomain.h>
-#include <asm/irq.h>
#include <asm/mach/irq.h>
-#include <plat/regs-irqtype.h>
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
#include <plat/cpu.h>
+#include <plat/regs-irqtype.h>
#include <plat/pm.h>
#include <plat/irq.h>
-static void
-s3c_irq_mask(struct irq_data *data)
-{
- unsigned int irqno = data->irq - IRQ_EINT0;
- unsigned long mask;
-
- mask = __raw_readl(S3C2410_INTMSK);
- mask |= 1UL << irqno;
- __raw_writel(mask, S3C2410_INTMSK);
-}
-
-static inline void
-s3c_irq_ack(struct irq_data *data)
-{
- unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
-
- __raw_writel(bitval, S3C2410_SRCPND);
- __raw_writel(bitval, S3C2410_INTPND);
-}
-
-static inline void
-s3c_irq_maskack(struct irq_data *data)
-{
- unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
- unsigned long mask;
+#define S3C_IRQTYPE_NONE 0
+#define S3C_IRQTYPE_EINT 1
+#define S3C_IRQTYPE_EDGE 2
+#define S3C_IRQTYPE_LEVEL 3
- mask = __raw_readl(S3C2410_INTMSK);
- __raw_writel(mask|bitval, S3C2410_INTMSK);
+struct s3c_irq_data {
+ unsigned int type;
+ unsigned long parent_irq;
- __raw_writel(bitval, S3C2410_SRCPND);
- __raw_writel(bitval, S3C2410_INTPND);
-}
-
-
-static void
-s3c_irq_unmask(struct irq_data *data)
-{
- unsigned int irqno = data->irq;
- unsigned long mask;
-
- if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
- irqdbf2("s3c_irq_unmask %d\n", irqno);
-
- irqno -= IRQ_EINT0;
-
- mask = __raw_readl(S3C2410_INTMSK);
- mask &= ~(1UL << irqno);
- __raw_writel(mask, S3C2410_INTMSK);
-}
-
-struct irq_chip s3c_irq_level_chip = {
- .name = "s3c-level",
- .irq_ack = s3c_irq_maskack,
- .irq_mask = s3c_irq_mask,
- .irq_unmask = s3c_irq_unmask,
- .irq_set_wake = s3c_irq_wake
+ /* data gets filled during init */
+ struct s3c_irq_intc *intc;
+ unsigned long sub_bits;
+ struct s3c_irq_intc *sub_intc;
};
-struct irq_chip s3c_irq_chip = {
- .name = "s3c",
- .irq_ack = s3c_irq_ack,
- .irq_mask = s3c_irq_mask,
- .irq_unmask = s3c_irq_unmask,
- .irq_set_wake = s3c_irq_wake
+/*
+ * Sructure holding the controller data
+ * @reg_pending register holding pending irqs
+ * @reg_intpnd special register intpnd in main intc
+ * @reg_mask mask register
+ * @domain irq_domain of the controller
+ * @parent parent controller for ext and sub irqs
+ * @irqs irq-data, always s3c_irq_data[32]
+ */
+struct s3c_irq_intc {
+ void __iomem *reg_pending;
+ void __iomem *reg_intpnd;
+ void __iomem *reg_mask;
+ struct irq_domain *domain;
+ struct s3c_irq_intc *parent;
+ struct s3c_irq_data *irqs;
};
-static void
-s3c_irqext_mask(struct irq_data *data)
+static void s3c_irq_mask(struct irq_data *data)
{
- unsigned int irqno = data->irq - EXTINT_OFF;
+ struct s3c_irq_intc *intc = data->domain->host_data;
+ struct s3c_irq_intc *parent_intc = intc->parent;
+ struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq];
+ struct s3c_irq_data *parent_data;
unsigned long mask;
+ unsigned int irqno;
+
+ mask = __raw_readl(intc->reg_mask);
+ mask |= (1UL << data->hwirq);
+ __raw_writel(mask, intc->reg_mask);
+
+ if (parent_intc && irq_data->parent_irq) {
+ parent_data = &parent_intc->irqs[irq_data->parent_irq];
- mask = __raw_readl(S3C24XX_EINTMASK);
- mask |= ( 1UL << irqno);
- __raw_writel(mask, S3C24XX_EINTMASK);
+ /* check to see if we need to mask the parent IRQ */
+ if ((mask & parent_data->sub_bits) == parent_data->sub_bits) {
+ irqno = irq_find_mapping(parent_intc->domain,
+ irq_data->parent_irq);
+ s3c_irq_mask(irq_get_irq_data(irqno));
+ }
+ }
}
-static void
-s3c_irqext_ack(struct irq_data *data)
+static void s3c_irq_unmask(struct irq_data *data)
{
- unsigned long req;
- unsigned long bit;
+ struct s3c_irq_intc *intc = data->domain->host_data;
+ struct s3c_irq_intc *parent_intc = intc->parent;
+ struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq];
unsigned long mask;
+ unsigned int irqno;
- bit = 1UL << (data->irq - EXTINT_OFF);
-
- mask = __raw_readl(S3C24XX_EINTMASK);
-
- __raw_writel(bit, S3C24XX_EINTPEND);
-
- req = __raw_readl(S3C24XX_EINTPEND);
- req &= ~mask;
-
- /* not sure if we should be acking the parent irq... */
+ mask = __raw_readl(intc->reg_mask);
+ mask &= ~(1UL << data->hwirq);
+ __raw_writel(mask, intc->reg_mask);
- if (data->irq <= IRQ_EINT7) {
- if ((req & 0xf0) == 0)
- s3c_irq_ack(irq_get_irq_data(IRQ_EINT4t7));
- } else {
- if ((req >> 8) == 0)
- s3c_irq_ack(irq_get_irq_data(IRQ_EINT8t23));
+ if (parent_intc && irq_data->parent_irq) {
+ irqno = irq_find_mapping(parent_intc->domain,
+ irq_data->parent_irq);
+ s3c_irq_unmask(irq_get_irq_data(irqno));
}
}
-static void
-s3c_irqext_unmask(struct irq_data *data)
+static inline void s3c_irq_ack(struct irq_data *data)
{
- unsigned int irqno = data->irq - EXTINT_OFF;
- unsigned long mask;
+ struct s3c_irq_intc *intc = data->domain->host_data;
+ unsigned long bitval = 1UL << data->hwirq;
- mask = __raw_readl(S3C24XX_EINTMASK);
- mask &= ~(1UL << irqno);
- __raw_writel(mask, S3C24XX_EINTMASK);
+ __raw_writel(bitval, intc->reg_pending);
+ if (intc->reg_intpnd)
+ __raw_writel(bitval, intc->reg_intpnd);
}
-int
-s3c_irqext_type(struct irq_data *data, unsigned int type)
+static int s3c_irqext_type_set(void __iomem *gpcon_reg,
+ void __iomem *extint_reg,
+ unsigned long gpcon_offset,
+ unsigned long extint_offset,
+ unsigned int type)
{
- void __iomem *extint_reg;
- void __iomem *gpcon_reg;
- unsigned long gpcon_offset, extint_offset;
unsigned long newvalue = 0, value;
- if ((data->irq >= IRQ_EINT0) && (data->irq <= IRQ_EINT3)) {
- gpcon_reg = S3C2410_GPFCON;
- extint_reg = S3C24XX_EXTINT0;
- gpcon_offset = (data->irq - IRQ_EINT0) * 2;
- extint_offset = (data->irq - IRQ_EINT0) * 4;
- } else if ((data->irq >= IRQ_EINT4) && (data->irq <= IRQ_EINT7)) {
- gpcon_reg = S3C2410_GPFCON;
- extint_reg = S3C24XX_EXTINT0;
- gpcon_offset = (data->irq - (EXTINT_OFF)) * 2;
- extint_offset = (data->irq - (EXTINT_OFF)) * 4;
- } else if ((data->irq >= IRQ_EINT8) && (data->irq <= IRQ_EINT15)) {
- gpcon_reg = S3C2410_GPGCON;
- extint_reg = S3C24XX_EXTINT1;
- gpcon_offset = (data->irq - IRQ_EINT8) * 2;
- extint_offset = (data->irq - IRQ_EINT8) * 4;
- } else if ((data->irq >= IRQ_EINT16) && (data->irq <= IRQ_EINT23)) {
- gpcon_reg = S3C2410_GPGCON;
- extint_reg = S3C24XX_EXTINT2;
- gpcon_offset = (data->irq - IRQ_EINT8) * 2;
- extint_offset = (data->irq - IRQ_EINT16) * 4;
- } else {
- return -1;
- }
-
/* Set the GPIO to external interrupt mode */
value = __raw_readl(gpcon_reg);
value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
@@ -190,7 +141,7 @@ s3c_irqext_type(struct irq_data *data, unsigned int type)
switch (type)
{
case IRQ_TYPE_NONE:
- printk(KERN_WARNING "No edge setting!\n");
+ pr_warn("No edge setting!\n");
break;
case IRQ_TYPE_EDGE_RISING:
@@ -214,8 +165,8 @@ s3c_irqext_type(struct irq_data *data, unsigned int type)
break;
default:
- printk(KERN_ERR "No such irq type %d", type);
- return -1;
+ pr_err("No such irq type %d", type);
+ return -EINVAL;
}
value = __raw_readl(extint_reg);
@@ -225,265 +176,113 @@ s3c_irqext_type(struct irq_data *data, unsigned int type)
return 0;
}
-static struct irq_chip s3c_irqext_chip = {
- .name = "s3c-ext",
- .irq_mask = s3c_irqext_mask,
- .irq_unmask = s3c_irqext_unmask,
- .irq_ack = s3c_irqext_ack,
- .irq_set_type = s3c_irqext_type,
- .irq_set_wake = s3c_irqext_wake
-};
-
-static struct irq_chip s3c_irq_eint0t4 = {
- .name = "s3c-ext0",
- .irq_ack = s3c_irq_ack,
- .irq_mask = s3c_irq_mask,
- .irq_unmask = s3c_irq_unmask,
- .irq_set_wake = s3c_irq_wake,
- .irq_set_type = s3c_irqext_type,
-};
-
-/* mask values for the parent registers for each of the interrupt types */
-
-#define INTMSK_UART0 (1UL << (IRQ_UART0 - IRQ_EINT0))
-#define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0))
-#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0))
-#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
-
-
-/* UART0 */
-
-static void
-s3c_irq_uart0_mask(struct irq_data *data)
+/* FIXME: make static when it's out of plat-samsung/irq.h */
+int s3c_irqext_type(struct irq_data *data, unsigned int type)
{
- s3c_irqsub_mask(data->irq, INTMSK_UART0, 7);
-}
+ void __iomem *extint_reg;
+ void __iomem *gpcon_reg;
+ unsigned long gpcon_offset, extint_offset;
-static void
-s3c_irq_uart0_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_UART0);
-}
+ if ((data->hwirq >= 4) && (data->hwirq <= 7)) {
+ gpcon_reg = S3C2410_GPFCON;
+ extint_reg = S3C24XX_EXTINT0;
+ gpcon_offset = (data->hwirq) * 2;
+ extint_offset = (data->hwirq) * 4;
+ } else if ((data->hwirq >= 8) && (data->hwirq <= 15)) {
+ gpcon_reg = S3C2410_GPGCON;
+ extint_reg = S3C24XX_EXTINT1;
+ gpcon_offset = (data->hwirq - 8) * 2;
+ extint_offset = (data->hwirq - 8) * 4;
+ } else if ((data->hwirq >= 16) && (data->hwirq <= 23)) {
+ gpcon_reg = S3C2410_GPGCON;
+ extint_reg = S3C24XX_EXTINT2;
+ gpcon_offset = (data->hwirq - 8) * 2;
+ extint_offset = (data->hwirq - 16) * 4;
+ } else {
+ return -EINVAL;
+ }
-static void
-s3c_irq_uart0_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_UART0, 7);
+ return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
+ extint_offset, type);
}
-static struct irq_chip s3c_irq_uart0 = {
- .name = "s3c-uart0",
- .irq_mask = s3c_irq_uart0_mask,
- .irq_unmask = s3c_irq_uart0_unmask,
- .irq_ack = s3c_irq_uart0_ack,
-};
-
-/* UART1 */
-
-static void
-s3c_irq_uart1_mask(struct irq_data *data)
+static int s3c_irqext0_type(struct irq_data *data, unsigned int type)
{
- s3c_irqsub_mask(data->irq, INTMSK_UART1, 7 << 3);
-}
+ void __iomem *extint_reg;
+ void __iomem *gpcon_reg;
+ unsigned long gpcon_offset, extint_offset;
-static void
-s3c_irq_uart1_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_UART1);
-}
+ if ((data->hwirq >= 0) && (data->hwirq <= 3)) {
+ gpcon_reg = S3C2410_GPFCON;
+ extint_reg = S3C24XX_EXTINT0;
+ gpcon_offset = (data->hwirq) * 2;
+ extint_offset = (data->hwirq) * 4;
+ } else {
+ return -EINVAL;
+ }
-static void
-s3c_irq_uart1_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_UART1, 7 << 3);
+ return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset,
+ extint_offset, type);
}
-static struct irq_chip s3c_irq_uart1 = {
- .name = "s3c-uart1",
- .irq_mask = s3c_irq_uart1_mask,
- .irq_unmask = s3c_irq_uart1_unmask,
- .irq_ack = s3c_irq_uart1_ack,
+struct irq_chip s3c_irq_chip = {
+ .name = "s3c",
+ .irq_ack = s3c_irq_ack,
+ .irq_mask = s3c_irq_mask,
+ .irq_unmask = s3c_irq_unmask,
+ .irq_set_wake = s3c_irq_wake
};
-/* UART2 */
-
-static void
-s3c_irq_uart2_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_UART2, 7 << 6);
-}
-
-static void
-s3c_irq_uart2_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_UART2);
-}
-
-static void
-s3c_irq_uart2_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_UART2, 7 << 6);
-}
-
-static struct irq_chip s3c_irq_uart2 = {
- .name = "s3c-uart2",
- .irq_mask = s3c_irq_uart2_mask,
- .irq_unmask = s3c_irq_uart2_unmask,
- .irq_ack = s3c_irq_uart2_ack,
+struct irq_chip s3c_irq_level_chip = {
+ .name = "s3c-level",
+ .irq_mask = s3c_irq_mask,
+ .irq_unmask = s3c_irq_unmask,
+ .irq_ack = s3c_irq_ack,
};
-/* ADC and Touchscreen */
-
-static void
-s3c_irq_adc_mask(struct irq_data *d)
-{
- s3c_irqsub_mask(d->irq, INTMSK_ADCPARENT, 3 << 9);
-}
-
-static void
-s3c_irq_adc_unmask(struct irq_data *d)
-{
- s3c_irqsub_unmask(d->irq, INTMSK_ADCPARENT);
-}
-
-static void
-s3c_irq_adc_ack(struct irq_data *d)
-{
- s3c_irqsub_ack(d->irq, INTMSK_ADCPARENT, 3 << 9);
-}
-
-static struct irq_chip s3c_irq_adc = {
- .name = "s3c-adc",
- .irq_mask = s3c_irq_adc_mask,
- .irq_unmask = s3c_irq_adc_unmask,
- .irq_ack = s3c_irq_adc_ack,
+static struct irq_chip s3c_irqext_chip = {
+ .name = "s3c-ext",
+ .irq_mask = s3c_irq_mask,
+ .irq_unmask = s3c_irq_unmask,
+ .irq_ack = s3c_irq_ack,
+ .irq_set_type = s3c_irqext_type,
+ .irq_set_wake = s3c_irqext_wake
};
-/* irq demux for adc */
-static void s3c_irq_demux_adc(unsigned int irq,
- struct irq_desc *desc)
-{
- unsigned int subsrc, submsk;
- unsigned int offset = 9;
-
- /* read the current pending interrupts, and the mask
- * for what it is available */
-
- subsrc = __raw_readl(S3C2410_SUBSRCPND);
- submsk = __raw_readl(S3C2410_INTSUBMSK);
-
- subsrc &= ~submsk;
- subsrc >>= offset;
- subsrc &= 3;
-
- if (subsrc != 0) {
- if (subsrc & 1) {
- generic_handle_irq(IRQ_TC);
- }
- if (subsrc & 2) {
- generic_handle_irq(IRQ_ADC);
- }
- }
-}
-
-static void s3c_irq_demux_uart(unsigned int start)
-{
- unsigned int subsrc, submsk;
- unsigned int offset = start - IRQ_S3CUART_RX0;
-
- /* read the current pending interrupts, and the mask
- * for what it is available */
-
- subsrc = __raw_readl(S3C2410_SUBSRCPND);
- submsk = __raw_readl(S3C2410_INTSUBMSK);
-
- irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
- start, offset, subsrc, submsk);
-
- subsrc &= ~submsk;
- subsrc >>= offset;
- subsrc &= 7;
-
- if (subsrc != 0) {
- if (subsrc & 1)
- generic_handle_irq(start);
-
- if (subsrc & 2)
- generic_handle_irq(start+1);
-
- if (subsrc & 4)
- generic_handle_irq(start+2);
- }
-}
-
-/* uart demux entry points */
-
-static void
-s3c_irq_demux_uart0(unsigned int irq,
- struct irq_desc *desc)
-{
- irq = irq;
- s3c_irq_demux_uart(IRQ_S3CUART_RX0);
-}
-
-static void
-s3c_irq_demux_uart1(unsigned int irq,
- struct irq_desc *desc)
-{
- irq = irq;
- s3c_irq_demux_uart(IRQ_S3CUART_RX1);
-}
-
-static void
-s3c_irq_demux_uart2(unsigned int irq,
- struct irq_desc *desc)
-{
- irq = irq;
- s3c_irq_demux_uart(IRQ_S3CUART_RX2);
-}
+static struct irq_chip s3c_irq_eint0t4 = {
+ .name = "s3c-ext0",
+ .irq_ack = s3c_irq_ack,
+ .irq_mask = s3c_irq_mask,
+ .irq_unmask = s3c_irq_unmask,
+ .irq_set_wake = s3c_irq_wake,
+ .irq_set_type = s3c_irqext0_type,
+};
-static void
-s3c_irq_demux_extint8(unsigned int irq,
- struct irq_desc *desc)
+static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc)
{
- unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
- unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
-
- eintpnd &= ~eintmsk;
- eintpnd &= ~0xff; /* ignore lower irqs */
-
- /* we may as well handle all the pending IRQs here */
-
- while (eintpnd) {
- irq = __ffs(eintpnd);
- eintpnd &= ~(1<<irq);
-
- irq += (IRQ_EINT4 - 4);
- generic_handle_irq(irq);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct s3c_irq_intc *intc = desc->irq_data.domain->host_data;
+ struct s3c_irq_data *irq_data = &intc->irqs[desc->irq_data.hwirq];
+ struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
+ unsigned long src;
+ unsigned long msk;
+ unsigned int n;
+
+ chained_irq_enter(chip, desc);
+
+ src = __raw_readl(sub_intc->reg_pending);
+ msk = __raw_readl(sub_intc->reg_mask);
+
+ src &= ~msk;
+ src &= irq_data->sub_bits;
+
+ while (src) {
+ n = __ffs(src);
+ src &= ~(1 << n);
+ generic_handle_irq(irq_find_mapping(sub_intc->domain, n));
}
-}
-
-static void
-s3c_irq_demux_extint4t7(unsigned int irq,
- struct irq_desc *desc)
-{
- unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
- unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
-
- eintpnd &= ~eintmsk;
- eintpnd &= 0xff; /* only lower irqs */
-
- /* we may as well handle all the pending IRQs here */
-
- while (eintpnd) {
- irq = __ffs(eintpnd);
- eintpnd &= ~(1<<irq);
-
- irq += (IRQ_EINT4 - 4);
-
- generic_handle_irq(irq);
- }
+ chained_irq_exit(chip, desc);
}
#ifdef CONFIG_FIQ
@@ -519,155 +318,314 @@ int s3c24xx_set_fiq(unsigned int irq, bool on)
EXPORT_SYMBOL_GPL(s3c24xx_set_fiq);
#endif
-
-/* s3c24xx_init_irq
- *
- * Initialise S3C2410 IRQ system
-*/
-
-void __init s3c24xx_init_irq(void)
+static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
+ irq_hw_number_t hw)
{
- unsigned long pend;
- unsigned long last;
- int irqno;
- int i;
-
-#ifdef CONFIG_FIQ
- init_FIQ(FIQ_START);
-#endif
-
- irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
-
- /* first, clear all interrupts pending... */
+ struct s3c_irq_intc *intc = h->host_data;
+ struct s3c_irq_data *irq_data = &intc->irqs[hw];
+ struct s3c_irq_intc *parent_intc;
+ struct s3c_irq_data *parent_irq_data;
+ unsigned int irqno;
+
+ if (!intc) {
+ pr_err("irq-s3c24xx: no controller found for hwirq %lu\n", hw);
+ return -EINVAL;
+ }
- last = 0;
- for (i = 0; i < 4; i++) {
- pend = __raw_readl(S3C24XX_EINTPEND);
+ if (!irq_data) {
+ pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n", hw);
+ return -EINVAL;
+ }
- if (pend == 0 || pend == last)
- break;
+ /* attach controller pointer to irq_data */
+ irq_data->intc = intc;
- __raw_writel(pend, S3C24XX_EINTPEND);
- printk("irq: clearing pending ext status %08x\n", (int)pend);
- last = pend;
+ /* set handler and flags */
+ switch (irq_data->type) {
+ case S3C_IRQTYPE_NONE:
+ return 0;
+ case S3C_IRQTYPE_EINT:
+ if (irq_data->parent_irq)
+ irq_set_chip_and_handler(virq, &s3c_irqext_chip,
+ handle_edge_irq);
+ else
+ irq_set_chip_and_handler(virq, &s3c_irq_eint0t4,
+ handle_edge_irq);
+ break;
+ case S3C_IRQTYPE_EDGE:
+ if (irq_data->parent_irq)
+ irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
+ handle_edge_irq);
+ else
+ irq_set_chip_and_handler(virq, &s3c_irq_chip,
+ handle_edge_irq);
+ break;
+ case S3C_IRQTYPE_LEVEL:
+ if (irq_data->parent_irq)
+ irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
+ handle_level_irq);
+ else
+ irq_set_chip_and_handler(virq, &s3c_irq_chip,
+ handle_level_irq);
+ break;
+ default:
+ pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type);
+ return -EINVAL;
}
+ set_irq_flags(virq, IRQF_VALID);
+
+ if (irq_data->parent_irq) {
+ parent_intc = intc->parent;
+ if (!parent_intc) {
+ pr_err("irq-s3c24xx: no parent controller found for hwirq %lu\n",
+ hw);
+ goto err;
+ }
- last = 0;
- for (i = 0; i < 4; i++) {
- pend = __raw_readl(S3C2410_INTPND);
+ parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
+ if (!irq_data) {
+ pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n",
+ hw);
+ goto err;
+ }
- if (pend == 0 || pend == last)
- break;
+ parent_irq_data->sub_intc = intc;
+ parent_irq_data->sub_bits |= (1UL << hw);
- __raw_writel(pend, S3C2410_SRCPND);
- __raw_writel(pend, S3C2410_INTPND);
- printk("irq: clearing pending status %08x\n", (int)pend);
- last = pend;
+ /* attach the demuxer to the parent irq */
+ irqno = irq_find_mapping(parent_intc->domain,
+ irq_data->parent_irq);
+ if (!irqno) {
+ pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n",
+ irq_data->parent_irq);
+ goto err;
+ }
+ irq_set_chained_handler(irqno, s3c_irq_demux);
}
- last = 0;
- for (i = 0; i < 4; i++) {
- pend = __raw_readl(S3C2410_SUBSRCPND);
+ return 0;
- if (pend == 0 || pend == last)
- break;
+err:
+ set_irq_flags(virq, 0);
- printk("irq: clearing subpending status %08x\n", (int)pend);
- __raw_writel(pend, S3C2410_SUBSRCPND);
- last = pend;
- }
+ /* the only error can result from bad mapping data*/
+ return -EINVAL;
+}
- /* register the main interrupts */
+static struct irq_domain_ops s3c24xx_irq_ops = {
+ .map = s3c24xx_irq_map,
+ .xlate = irq_domain_xlate_twocell,
+};
- irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
+static void s3c24xx_clear_intc(struct s3c_irq_intc *intc)
+{
+ void __iomem *reg_source;
+ unsigned long pend;
+ unsigned long last;
+ int i;
- for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
- /* set all the s3c2410 internal irqs */
+ /* if intpnd is set, read the next pending irq from there */
+ reg_source = intc->reg_intpnd ? intc->reg_intpnd : intc->reg_pending;
- switch (irqno) {
- /* deal with the special IRQs (cascaded) */
+ last = 0;
+ for (i = 0; i < 4; i++) {
+ pend = __raw_readl(reg_source);
- case IRQ_EINT4t7:
- case IRQ_EINT8t23:
- case IRQ_UART0:
- case IRQ_UART1:
- case IRQ_UART2:
- case IRQ_ADCPARENT:
- irq_set_chip_and_handler(irqno, &s3c_irq_level_chip,
- handle_level_irq);
+ if (pend == 0 || pend == last)
break;
- case IRQ_RESERVED6:
- case IRQ_RESERVED24:
- /* no IRQ here */
- break;
+ __raw_writel(pend, intc->reg_pending);
+ if (intc->reg_intpnd)
+ __raw_writel(pend, intc->reg_intpnd);
- default:
- //irqdbf("registering irq %d (s3c irq)\n", irqno);
- irq_set_chip_and_handler(irqno, &s3c_irq_chip,
- handle_edge_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
+ pr_info("irq: clearing pending status %08x\n", (int)pend);
+ last = pend;
}
+}
- /* setup the cascade irq handlers */
-
- irq_set_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
- irq_set_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
+struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
+ struct s3c_irq_data *irq_data,
+ struct s3c_irq_intc *parent,
+ unsigned long address)
+{
+ struct s3c_irq_intc *intc;
+ void __iomem *base = (void *)0xf6000000; /* static mapping */
+ int irq_num;
+ int irq_start;
+ int irq_offset;
+ int ret;
+
+ intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
+ if (!intc)
+ return ERR_PTR(-ENOMEM);
+
+ intc->irqs = irq_data;
+
+ if (parent)
+ intc->parent = parent;
+
+ /* select the correct data for the controller.
+ * Need to hard code the irq num start and offset
+ * to preserve the static mapping for now
+ */
+ switch (address) {
+ case 0x4a000000:
+ pr_debug("irq: found main intc\n");
+ intc->reg_pending = base;
+ intc->reg_mask = base + 0x08;
+ intc->reg_intpnd = base + 0x10;
+ irq_num = 32;
+ irq_start = S3C2410_IRQ(0);
+ irq_offset = 0;
+ break;
+ case 0x4a000018:
+ pr_debug("irq: found subintc\n");
+ intc->reg_pending = base + 0x18;
+ intc->reg_mask = base + 0x1c;
+ irq_num = 29;
+ irq_start = S3C2410_IRQSUB(0);
+ irq_offset = 0;
+ break;
+ case 0x4a000040:
+ pr_debug("irq: found intc2\n");
+ intc->reg_pending = base + 0x40;
+ intc->reg_mask = base + 0x48;
+ intc->reg_intpnd = base + 0x50;
+ irq_num = 8;
+ irq_start = S3C2416_IRQ(0);
+ irq_offset = 0;
+ break;
+ case 0x560000a4:
+ pr_debug("irq: found eintc\n");
+ base = (void *)0xfd000000;
+
+ intc->reg_mask = base + 0xa4;
+ intc->reg_pending = base + 0x08;
+ irq_num = 20;
+ irq_start = S3C2410_IRQ(32);
+ irq_offset = 4;
+ break;
+ default:
+ pr_err("irq: unsupported controller address\n");
+ ret = -EINVAL;
+ goto err;
+ }
- irq_set_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
- irq_set_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
- irq_set_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
- irq_set_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
+ /* now that all the data is complete, init the irq-domain */
+ s3c24xx_clear_intc(intc);
+ intc->domain = irq_domain_add_legacy(np, irq_num, irq_start,
+ irq_offset, &s3c24xx_irq_ops,
+ intc);
+ if (!intc->domain) {
+ pr_err("irq: could not create irq-domain\n");
+ ret = -EINVAL;
+ goto err;
+ }
- /* external interrupts */
+ return intc;
- for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
- irqdbf("registering irq %d (ext int)\n", irqno);
- irq_set_chip_and_handler(irqno, &s3c_irq_eint0t4,
- handle_edge_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
+err:
+ kfree(intc);
+ return ERR_PTR(ret);
+}
- for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
- irqdbf("registering irq %d (extended s3c irq)\n", irqno);
- irq_set_chip_and_handler(irqno, &s3c_irqext_chip,
- handle_edge_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
+/* s3c24xx_init_irq
+ *
+ * Initialise S3C2410 IRQ system
+*/
- /* register the uart interrupts */
+static struct s3c_irq_data init_base[32] = {
+ { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+ { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+ { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+ { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+ { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+ { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+ { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
+ { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
+ { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+ { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+ { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+ { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+ { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
- irqdbf("s3c2410: registering external interrupts\n");
+static struct s3c_irq_data init_eint[32] = {
+ { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+ { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+ { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+ { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
+ { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
+};
- for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
- irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
- irq_set_chip_and_handler(irqno, &s3c_irq_uart0,
- handle_level_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
+static struct s3c_irq_data init_subint[32] = {
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+ { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+ { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+};
- for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
- irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
- irq_set_chip_and_handler(irqno, &s3c_irq_uart1,
- handle_level_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
+void __init s3c24xx_init_irq(void)
+{
+ struct s3c_irq_intc *main_intc;
- for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
- irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
- irq_set_chip_and_handler(irqno, &s3c_irq_uart2,
- handle_level_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
+#ifdef CONFIG_FIQ
+ init_FIQ(FIQ_START);
+#endif
- for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
- irqdbf("registering irq %d (s3c adc irq)\n", irqno);
- irq_set_chip_and_handler(irqno, &s3c_irq_adc, handle_edge_irq);
- set_irq_flags(irqno, IRQF_VALID);
+ main_intc = s3c24xx_init_intc(NULL, &init_base[0], NULL, 0x4a000000);
+ if (IS_ERR(main_intc)) {
+ pr_err("irq: could not create main interrupt controller\n");
+ return;
}
- irqdbf("s3c2410: registered interrupt handlers\n");
+ s3c24xx_init_intc(NULL, &init_subint[0], main_intc, 0x4a000018);
+ s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
}
struct syscore_ops s3c24xx_irq_syscore_ops = {
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 2/9] ARM: S3C24XX: Move irq syscore-ops to irq-pm
From: Heiko Stübner @ 2013-01-27 20:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201301272124.18530.heiko@sntech.de>
With this the definition of s3c24xx_irq_syscore_ops can also move to
common.h from plat/pm.h and the definitions of s3c24xx_irq_suspend
and s3c24xx_irq_resume are also not necessary anymore in plat/pm.h
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
arch/arm/mach-s3c24xx/common.h | 2 ++
arch/arm/mach-s3c24xx/irq-pm.c | 10 ++++++++--
arch/arm/mach-s3c24xx/s3c2410.c | 4 +++-
arch/arm/mach-s3c24xx/s3c2412.c | 4 +++-
arch/arm/mach-s3c24xx/s3c2416.c | 4 +++-
arch/arm/mach-s3c24xx/s3c2440.c | 4 +++-
arch/arm/mach-s3c24xx/s3c2442.c | 4 +++-
arch/arm/plat-s3c24xx/irq.c | 6 ------
arch/arm/plat-samsung/include/plat/pm.h | 6 ------
9 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h
index c2f596e..ed6276f 100644
--- a/arch/arm/mach-s3c24xx/common.h
+++ b/arch/arm/mach-s3c24xx/common.h
@@ -15,4 +15,6 @@
void s3c2410_restart(char mode, const char *cmd);
void s3c244x_restart(char mode, const char *cmd);
+extern struct syscore_ops s3c24xx_irq_syscore_ops;
+
#endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */
diff --git a/arch/arm/mach-s3c24xx/irq-pm.c b/arch/arm/mach-s3c24xx/irq-pm.c
index 0efb2e2..d48126d 100644
--- a/arch/arm/mach-s3c24xx/irq-pm.c
+++ b/arch/arm/mach-s3c24xx/irq-pm.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/syscore_ops.h>
#include <plat/cpu.h>
#include <plat/pm.h>
@@ -64,7 +65,7 @@ static unsigned long save_extint[3];
static unsigned long save_eintflt[4];
static unsigned long save_eintmask;
-int s3c24xx_irq_suspend(void)
+static int s3c24xx_irq_suspend(void)
{
unsigned int i;
@@ -80,7 +81,7 @@ int s3c24xx_irq_suspend(void)
return 0;
}
-void s3c24xx_irq_resume(void)
+static void s3c24xx_irq_resume(void)
{
unsigned int i;
@@ -93,3 +94,8 @@ void s3c24xx_irq_resume(void)
s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
__raw_writel(save_eintmask, S3C24XX_EINTMASK);
}
+
+struct syscore_ops s3c24xx_irq_syscore_ops = {
+ .suspend = s3c24xx_irq_suspend,
+ .resume = s3c24xx_irq_resume,
+};
diff --git a/arch/arm/mach-s3c24xx/s3c2410.c b/arch/arm/mach-s3c24xx/s3c2410.c
index a3c5cb0..9ebef95 100644
--- a/arch/arm/mach-s3c24xx/s3c2410.c
+++ b/arch/arm/mach-s3c24xx/s3c2410.c
@@ -49,6 +49,8 @@
#include <plat/gpio-cfg.h>
#include <plat/gpio-cfg-helpers.h>
+#include "common.h"
+
/* Initial IO mappings */
static struct map_desc s3c2410_iodesc[] __initdata = {
@@ -182,8 +184,8 @@ int __init s3c2410_init(void)
#ifdef CONFIG_PM
register_syscore_ops(&s3c2410_pm_syscore_ops);
-#endif
register_syscore_ops(&s3c24xx_irq_syscore_ops);
+#endif
return device_register(&s3c2410_dev);
}
diff --git a/arch/arm/mach-s3c24xx/s3c2412.c b/arch/arm/mach-s3c24xx/s3c2412.c
index c511a22..533b4a9 100644
--- a/arch/arm/mach-s3c24xx/s3c2412.c
+++ b/arch/arm/mach-s3c24xx/s3c2412.c
@@ -52,6 +52,8 @@
#define S3C2412_SWRST (S3C24XX_VA_CLKPWR + 0x30)
#define S3C2412_SWRST_RESET (0x533C2412)
+#include "common.h"
+
#ifndef CONFIG_CPU_S3C2412_ONLY
void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
@@ -245,8 +247,8 @@ int __init s3c2412_init(void)
#ifdef CONFIG_PM
register_syscore_ops(&s3c2412_pm_syscore_ops);
-#endif
register_syscore_ops(&s3c24xx_irq_syscore_ops);
+#endif
return device_register(&s3c2412_dev);
}
diff --git a/arch/arm/mach-s3c24xx/s3c2416.c b/arch/arm/mach-s3c24xx/s3c2416.c
index 77ee0b7..e30476d 100644
--- a/arch/arm/mach-s3c24xx/s3c2416.c
+++ b/arch/arm/mach-s3c24xx/s3c2416.c
@@ -63,6 +63,8 @@
#include <plat/rtc-core.h>
#include <plat/spi-core.h>
+#include "common.h"
+
static struct map_desc s3c2416_iodesc[] __initdata = {
IODESC_ENT(WATCHDOG),
IODESC_ENT(CLKPWR),
@@ -105,9 +107,9 @@ int __init s3c2416_init(void)
#ifdef CONFIG_PM
register_syscore_ops(&s3c2416_pm_syscore_ops);
-#endif
register_syscore_ops(&s3c24xx_irq_syscore_ops);
register_syscore_ops(&s3c2416_irq_syscore_ops);
+#endif
return device_register(&s3c2416_dev);
}
diff --git a/arch/arm/mach-s3c24xx/s3c2440.c b/arch/arm/mach-s3c24xx/s3c2440.c
index 2b3dddb..559e394 100644
--- a/arch/arm/mach-s3c24xx/s3c2440.c
+++ b/arch/arm/mach-s3c24xx/s3c2440.c
@@ -40,6 +40,8 @@
#include <plat/gpio-cfg.h>
#include <plat/gpio-cfg-helpers.h>
+#include "common.h"
+
static struct device s3c2440_dev = {
.bus = &s3c2440_subsys,
};
@@ -57,9 +59,9 @@ int __init s3c2440_init(void)
#ifdef CONFIG_PM
register_syscore_ops(&s3c2410_pm_syscore_ops);
+ register_syscore_ops(&s3c24xx_irq_syscore_ops);
#endif
register_syscore_ops(&s3c244x_pm_syscore_ops);
- register_syscore_ops(&s3c24xx_irq_syscore_ops);
/* register our system device for everything else */
diff --git a/arch/arm/mach-s3c24xx/s3c2442.c b/arch/arm/mach-s3c24xx/s3c2442.c
index 22cb7c9..f732826 100644
--- a/arch/arm/mach-s3c24xx/s3c2442.c
+++ b/arch/arm/mach-s3c24xx/s3c2442.c
@@ -51,6 +51,8 @@
#include <plat/gpio-cfg.h>
#include <plat/gpio-cfg-helpers.h>
+#include "common.h"
+
/* S3C2442 extended clock support */
static unsigned long s3c2442_camif_upll_round(struct clk *clk,
@@ -172,9 +174,9 @@ int __init s3c2442_init(void)
#ifdef CONFIG_PM
register_syscore_ops(&s3c2410_pm_syscore_ops);
+ register_syscore_ops(&s3c24xx_irq_syscore_ops);
#endif
register_syscore_ops(&s3c244x_pm_syscore_ops);
- register_syscore_ops(&s3c24xx_irq_syscore_ops);
return device_register(&s3c2442_dev);
}
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
index 9e24ef5..adb4358 100644
--- a/arch/arm/plat-s3c24xx/irq.c
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -24,7 +24,6 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/device.h>
-#include <linux/syscore_ops.h>
#include <linux/irqdomain.h>
#include <asm/mach/irq.h>
@@ -627,8 +626,3 @@ void __init s3c24xx_init_irq(void)
s3c24xx_init_intc(NULL, &init_subint[0], main_intc, 0x4a000018);
s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
}
-
-struct syscore_ops s3c24xx_irq_syscore_ops = {
- .suspend = s3c24xx_irq_suspend,
- .resume = s3c24xx_irq_resume,
-};
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h
index 887a0c9..f6fcade 100644
--- a/arch/arm/plat-samsung/include/plat/pm.h
+++ b/arch/arm/plat-samsung/include/plat/pm.h
@@ -109,17 +109,11 @@ extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count);
#ifdef CONFIG_PM
extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
extern int s3c_irqext_wake(struct irq_data *data, unsigned int state);
-extern int s3c24xx_irq_suspend(void);
-extern void s3c24xx_irq_resume(void);
#else
#define s3c_irq_wake NULL
#define s3c_irqext_wake NULL
-#define s3c24xx_irq_suspend NULL
-#define s3c24xx_irq_resume NULL
#endif
-extern struct syscore_ops s3c24xx_irq_syscore_ops;
-
/* PM debug functions */
#ifdef CONFIG_SAMSUNG_PM_DEBUG
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 3/9] ARM: S3C24XX: Modify s3c_irq_wake to use the hwirq property
From: Heiko Stübner @ 2013-01-27 20:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201301272124.18530.heiko@sntech.de>
This gets rid of the use of static irq mappings there.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
arch/arm/mach-s3c24xx/irq-pm.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-s3c24xx/irq-pm.c b/arch/arm/mach-s3c24xx/irq-pm.c
index d48126d..640ec91 100644
--- a/arch/arm/mach-s3c24xx/irq-pm.c
+++ b/arch/arm/mach-s3c24xx/irq-pm.c
@@ -30,18 +30,18 @@
* set bit to 1 in allow bitfield to enable the wakeup settings on it
*/
-unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
+unsigned long s3c_irqwake_intallow = 1L << 30 | 0xfL;
unsigned long s3c_irqwake_eintallow = 0x0000fff0L;
int s3c_irq_wake(struct irq_data *data, unsigned int state)
{
- unsigned long irqbit = 1 << (data->irq - IRQ_EINT0);
+ unsigned long irqbit = 1 << data->hwirq;
if (!(s3c_irqwake_intallow & irqbit))
return -ENOENT;
- printk(KERN_INFO "wake %s for irq %d\n",
- state ? "enabled" : "disabled", data->irq);
+ pr_info("wake %s for hwirq %lu\n",
+ state ? "enabled" : "disabled", data->hwirq);
if (!state)
s3c_irqwake_intmask |= irqbit;
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 4/9] ARM: S3C24XX: move s3c2416 irq init to common irq code
From: Heiko Stübner @ 2013-01-27 20:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201301272124.18530.heiko@sntech.de>
This is needed to further clean up the irq init.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
arch/arm/mach-s3c24xx/Makefile | 2 +-
arch/arm/mach-s3c24xx/irq-pm.c | 23 +++
arch/arm/mach-s3c24xx/irq-s3c2416.c | 348 -----------------------------------
arch/arm/plat-s3c24xx/irq.c | 286 ++++++++++++++++++++++++++++
4 files changed, 310 insertions(+), 349 deletions(-)
delete mode 100644 arch/arm/mach-s3c24xx/irq-s3c2416.c
diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile
index 08b87cd..68d134f 100644
--- a/arch/arm/mach-s3c24xx/Makefile
+++ b/arch/arm/mach-s3c24xx/Makefile
@@ -28,7 +28,7 @@ obj-$(CONFIG_S3C2412_DMA) += dma-s3c2412.o
obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o
obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o
-obj-$(CONFIG_CPU_S3C2416) += s3c2416.o irq-s3c2416.o clock-s3c2416.o
+obj-$(CONFIG_CPU_S3C2416) += s3c2416.o clock-s3c2416.o
obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o
obj-$(CONFIG_CPU_S3C2440) += s3c2440.o irq-s3c2440.o clock-s3c2440.o
diff --git a/arch/arm/mach-s3c24xx/irq-pm.c b/arch/arm/mach-s3c24xx/irq-pm.c
index 640ec91..e119959 100644
--- a/arch/arm/mach-s3c24xx/irq-pm.c
+++ b/arch/arm/mach-s3c24xx/irq-pm.c
@@ -99,3 +99,26 @@ struct syscore_ops s3c24xx_irq_syscore_ops = {
.suspend = s3c24xx_irq_suspend,
.resume = s3c24xx_irq_resume,
};
+
+#ifdef CONFIG_CPU_S3C2416
+static struct sleep_save s3c2416_irq_save[] = {
+ SAVE_ITEM(S3C2416_INTMSK2),
+};
+
+static int s3c2416_irq_suspend(void)
+{
+ s3c_pm_do_save(s3c2416_irq_save, ARRAY_SIZE(s3c2416_irq_save));
+
+ return 0;
+}
+
+static void s3c2416_irq_resume(void)
+{
+ s3c_pm_do_restore(s3c2416_irq_save, ARRAY_SIZE(s3c2416_irq_save));
+}
+
+struct syscore_ops s3c2416_irq_syscore_ops = {
+ .suspend = s3c2416_irq_suspend,
+ .resume = s3c2416_irq_resume,
+};
+#endif
diff --git a/arch/arm/mach-s3c24xx/irq-s3c2416.c b/arch/arm/mach-s3c24xx/irq-s3c2416.c
deleted file mode 100644
index ff141b0..0000000
--- a/arch/arm/mach-s3c24xx/irq-s3c2416.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/* linux/arch/arm/mach-s3c2416/irq.c
- *
- * Copyright (c) 2009 Yauhen Kharuzhy <jekhor@gmail.com>,
- * as part of OpenInkpot project
- * Copyright (c) 2009 Promwad Innovation Company
- * Yauhen Kharuzhy <yauhen.kharuzhy@promwad.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/pm.h>
-#include <plat/irq.h>
-
-#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
-
-static inline void s3c2416_irq_demux(unsigned int irq, unsigned int len)
-{
- unsigned int subsrc, submsk;
- unsigned int end;
-
- /* read the current pending interrupts, and the mask
- * for what it is available */
-
- subsrc = __raw_readl(S3C2410_SUBSRCPND);
- submsk = __raw_readl(S3C2410_INTSUBMSK);
-
- subsrc &= ~submsk;
- subsrc >>= (irq - S3C2410_IRQSUB(0));
- subsrc &= (1 << len)-1;
-
- end = len + irq;
-
- for (; irq < end && subsrc; irq++) {
- if (subsrc & 1)
- generic_handle_irq(irq);
-
- subsrc >>= 1;
- }
-}
-
-/* WDT/AC97 sub interrupts */
-
-static void s3c2416_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc)
-{
- s3c2416_irq_demux(IRQ_S3C2443_WDT, 4);
-}
-
-#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0))
-#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97)
-
-static void s3c2416_irq_wdtac97_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
-}
-
-static void s3c2416_irq_wdtac97_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97);
-}
-
-static void s3c2416_irq_wdtac97_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
-}
-
-static struct irq_chip s3c2416_irq_wdtac97 = {
- .irq_mask = s3c2416_irq_wdtac97_mask,
- .irq_unmask = s3c2416_irq_wdtac97_unmask,
- .irq_ack = s3c2416_irq_wdtac97_ack,
-};
-
-/* LCD sub interrupts */
-
-static void s3c2416_irq_demux_lcd(unsigned int irq, struct irq_desc *desc)
-{
- s3c2416_irq_demux(IRQ_S3C2443_LCD1, 4);
-}
-
-#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0))
-#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4)
-
-static void s3c2416_irq_lcd_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD);
-}
-
-static void s3c2416_irq_lcd_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_LCD);
-}
-
-static void s3c2416_irq_lcd_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD);
-}
-
-static struct irq_chip s3c2416_irq_lcd = {
- .irq_mask = s3c2416_irq_lcd_mask,
- .irq_unmask = s3c2416_irq_lcd_unmask,
- .irq_ack = s3c2416_irq_lcd_ack,
-};
-
-/* DMA sub interrupts */
-
-static void s3c2416_irq_demux_dma(unsigned int irq, struct irq_desc *desc)
-{
- s3c2416_irq_demux(IRQ_S3C2443_DMA0, 6);
-}
-
-#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0))
-#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5)
-
-
-static void s3c2416_irq_dma_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA);
-}
-
-static void s3c2416_irq_dma_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_DMA);
-}
-
-static void s3c2416_irq_dma_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA);
-}
-
-static struct irq_chip s3c2416_irq_dma = {
- .irq_mask = s3c2416_irq_dma_mask,
- .irq_unmask = s3c2416_irq_dma_unmask,
- .irq_ack = s3c2416_irq_dma_ack,
-};
-
-/* UART3 sub interrupts */
-
-static void s3c2416_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
-{
- s3c2416_irq_demux(IRQ_S3C2443_RX3, 3);
-}
-
-#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
-#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
-
-static void s3c2416_irq_uart3_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3);
-}
-
-static void s3c2416_irq_uart3_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_UART3);
-}
-
-static void s3c2416_irq_uart3_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3);
-}
-
-static struct irq_chip s3c2416_irq_uart3 = {
- .irq_mask = s3c2416_irq_uart3_mask,
- .irq_unmask = s3c2416_irq_uart3_unmask,
- .irq_ack = s3c2416_irq_uart3_ack,
-};
-
-/* second interrupt register */
-
-static inline void s3c2416_irq_ack_second(struct irq_data *data)
-{
- unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D);
-
- __raw_writel(bitval, S3C2416_SRCPND2);
- __raw_writel(bitval, S3C2416_INTPND2);
-}
-
-static void s3c2416_irq_mask_second(struct irq_data *data)
-{
- unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D);
- unsigned long mask;
-
- mask = __raw_readl(S3C2416_INTMSK2);
- mask |= bitval;
- __raw_writel(mask, S3C2416_INTMSK2);
-}
-
-static void s3c2416_irq_unmask_second(struct irq_data *data)
-{
- unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D);
- unsigned long mask;
-
- mask = __raw_readl(S3C2416_INTMSK2);
- mask &= ~bitval;
- __raw_writel(mask, S3C2416_INTMSK2);
-}
-
-struct irq_chip s3c2416_irq_second = {
- .irq_ack = s3c2416_irq_ack_second,
- .irq_mask = s3c2416_irq_mask_second,
- .irq_unmask = s3c2416_irq_unmask_second,
-};
-
-
-/* IRQ initialisation code */
-
-static int s3c2416_add_sub(unsigned int base,
- void (*demux)(unsigned int,
- struct irq_desc *),
- struct irq_chip *chip,
- unsigned int start, unsigned int end)
-{
- unsigned int irqno;
-
- irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq);
- irq_set_chained_handler(base, demux);
-
- for (irqno = start; irqno <= end; irqno++) {
- irq_set_chip_and_handler(irqno, chip, handle_level_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
-
- return 0;
-}
-
-static void s3c2416_irq_add_second(void)
-{
- unsigned long pend;
- unsigned long last;
- int irqno;
- int i;
-
- /* first, clear all interrupts pending... */
- last = 0;
- for (i = 0; i < 4; i++) {
- pend = __raw_readl(S3C2416_INTPND2);
-
- if (pend == 0 || pend == last)
- break;
-
- __raw_writel(pend, S3C2416_SRCPND2);
- __raw_writel(pend, S3C2416_INTPND2);
- printk(KERN_INFO "irq: clearing pending status %08x\n",
- (int)pend);
- last = pend;
- }
-
- for (irqno = IRQ_S3C2416_2D; irqno <= IRQ_S3C2416_I2S1; irqno++) {
- switch (irqno) {
- case IRQ_S3C2416_RESERVED2:
- case IRQ_S3C2416_RESERVED3:
- /* no IRQ here */
- break;
- default:
- irq_set_chip_and_handler(irqno, &s3c2416_irq_second,
- handle_edge_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
- }
-}
-
-static int s3c2416_irq_add(struct device *dev,
- struct subsys_interface *sif)
-{
- printk(KERN_INFO "S3C2416: IRQ Support\n");
-
- s3c2416_add_sub(IRQ_LCD, s3c2416_irq_demux_lcd, &s3c2416_irq_lcd,
- IRQ_S3C2443_LCD2, IRQ_S3C2443_LCD4);
-
- s3c2416_add_sub(IRQ_S3C2443_DMA, s3c2416_irq_demux_dma,
- &s3c2416_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5);
-
- s3c2416_add_sub(IRQ_S3C2443_UART3, s3c2416_irq_demux_uart3,
- &s3c2416_irq_uart3,
- IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3);
-
- s3c2416_add_sub(IRQ_WDT, s3c2416_irq_demux_wdtac97,
- &s3c2416_irq_wdtac97,
- IRQ_S3C2443_WDT, IRQ_S3C2443_AC97);
-
- s3c2416_irq_add_second();
-
- return 0;
-}
-
-static struct subsys_interface s3c2416_irq_interface = {
- .name = "s3c2416_irq",
- .subsys = &s3c2416_subsys,
- .add_dev = s3c2416_irq_add,
-};
-
-static int __init s3c2416_irq_init(void)
-{
- return subsys_interface_register(&s3c2416_irq_interface);
-}
-
-arch_initcall(s3c2416_irq_init);
-
-#ifdef CONFIG_PM
-static struct sleep_save irq_save[] = {
- SAVE_ITEM(S3C2416_INTMSK2),
-};
-
-int s3c2416_irq_suspend(void)
-{
- s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
-
- return 0;
-}
-
-void s3c2416_irq_resume(void)
-{
- s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
-}
-
-struct syscore_ops s3c2416_irq_syscore_ops = {
- .suspend = s3c2416_irq_suspend,
- .resume = s3c2416_irq_resume,
-};
-#endif
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
index adb4358..131f747 100644
--- a/arch/arm/plat-s3c24xx/irq.c
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -626,3 +626,289 @@ void __init s3c24xx_init_irq(void)
s3c24xx_init_intc(NULL, &init_subint[0], main_intc, 0x4a000018);
s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
}
+
+#ifdef CONFIG_CPU_S3C2416
+#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
+
+static inline void s3c2416_irq_demux(unsigned int irq, unsigned int len)
+{
+ unsigned int subsrc, submsk;
+ unsigned int end;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+ subsrc = __raw_readl(S3C2410_SUBSRCPND);
+ submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+ subsrc &= ~submsk;
+ subsrc >>= (irq - S3C2410_IRQSUB(0));
+ subsrc &= (1 << len)-1;
+
+ end = len + irq;
+
+ for (; irq < end && subsrc; irq++) {
+ if (subsrc & 1)
+ generic_handle_irq(irq);
+
+ subsrc >>= 1;
+ }
+}
+
+/* WDT/AC97 sub interrupts */
+
+static void s3c2416_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2416_irq_demux(IRQ_S3C2443_WDT, 4);
+}
+
+#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0))
+#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97)
+
+static void s3c2416_irq_wdtac97_mask(struct irq_data *data)
+{
+ s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+}
+
+static void s3c2416_irq_wdtac97_unmask(struct irq_data *data)
+{
+ s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97);
+}
+
+static void s3c2416_irq_wdtac97_ack(struct irq_data *data)
+{
+ s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+}
+
+static struct irq_chip s3c2416_irq_wdtac97 = {
+ .irq_mask = s3c2416_irq_wdtac97_mask,
+ .irq_unmask = s3c2416_irq_wdtac97_unmask,
+ .irq_ack = s3c2416_irq_wdtac97_ack,
+};
+
+/* LCD sub interrupts */
+
+static void s3c2416_irq_demux_lcd(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2416_irq_demux(IRQ_S3C2443_LCD1, 4);
+}
+
+#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0))
+#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4)
+
+static void s3c2416_irq_lcd_mask(struct irq_data *data)
+{
+ s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD);
+}
+
+static void s3c2416_irq_lcd_unmask(struct irq_data *data)
+{
+ s3c_irqsub_unmask(data->irq, INTMSK_LCD);
+}
+
+static void s3c2416_irq_lcd_ack(struct irq_data *data)
+{
+ s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD);
+}
+
+static struct irq_chip s3c2416_irq_lcd = {
+ .irq_mask = s3c2416_irq_lcd_mask,
+ .irq_unmask = s3c2416_irq_lcd_unmask,
+ .irq_ack = s3c2416_irq_lcd_ack,
+};
+
+/* DMA sub interrupts */
+
+static void s3c2416_irq_demux_dma(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2416_irq_demux(IRQ_S3C2443_DMA0, 6);
+}
+
+#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0))
+#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5)
+
+
+static void s3c2416_irq_dma_mask(struct irq_data *data)
+{
+ s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA);
+}
+
+static void s3c2416_irq_dma_unmask(struct irq_data *data)
+{
+ s3c_irqsub_unmask(data->irq, INTMSK_DMA);
+}
+
+static void s3c2416_irq_dma_ack(struct irq_data *data)
+{
+ s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA);
+}
+
+static struct irq_chip s3c2416_irq_dma = {
+ .irq_mask = s3c2416_irq_dma_mask,
+ .irq_unmask = s3c2416_irq_dma_unmask,
+ .irq_ack = s3c2416_irq_dma_ack,
+};
+
+/* UART3 sub interrupts */
+
+static void s3c2416_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2416_irq_demux(IRQ_S3C2443_RX3, 3);
+}
+
+#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
+#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
+
+static void s3c2416_irq_uart3_mask(struct irq_data *data)
+{
+ s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3);
+}
+
+static void s3c2416_irq_uart3_unmask(struct irq_data *data)
+{
+ s3c_irqsub_unmask(data->irq, INTMSK_UART3);
+}
+
+static void s3c2416_irq_uart3_ack(struct irq_data *data)
+{
+ s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3);
+}
+
+static struct irq_chip s3c2416_irq_uart3 = {
+ .irq_mask = s3c2416_irq_uart3_mask,
+ .irq_unmask = s3c2416_irq_uart3_unmask,
+ .irq_ack = s3c2416_irq_uart3_ack,
+};
+
+/* second interrupt register */
+
+static inline void s3c2416_irq_ack_second(struct irq_data *data)
+{
+ unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D);
+
+ __raw_writel(bitval, S3C2416_SRCPND2);
+ __raw_writel(bitval, S3C2416_INTPND2);
+}
+
+static void s3c2416_irq_mask_second(struct irq_data *data)
+{
+ unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D);
+ unsigned long mask;
+
+ mask = __raw_readl(S3C2416_INTMSK2);
+ mask |= bitval;
+ __raw_writel(mask, S3C2416_INTMSK2);
+}
+
+static void s3c2416_irq_unmask_second(struct irq_data *data)
+{
+ unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D);
+ unsigned long mask;
+
+ mask = __raw_readl(S3C2416_INTMSK2);
+ mask &= ~bitval;
+ __raw_writel(mask, S3C2416_INTMSK2);
+}
+
+static struct irq_chip s3c2416_irq_second = {
+ .irq_ack = s3c2416_irq_ack_second,
+ .irq_mask = s3c2416_irq_mask_second,
+ .irq_unmask = s3c2416_irq_unmask_second,
+};
+
+
+/* IRQ initialisation code */
+
+static int s3c2416_add_sub(unsigned int base,
+ void (*demux)(unsigned int,
+ struct irq_desc *),
+ struct irq_chip *chip,
+ unsigned int start, unsigned int end)
+{
+ unsigned int irqno;
+
+ irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq);
+ irq_set_chained_handler(base, demux);
+
+ for (irqno = start; irqno <= end; irqno++) {
+ irq_set_chip_and_handler(irqno, chip, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ return 0;
+}
+
+static void s3c2416_irq_add_second(void)
+{
+ unsigned long pend;
+ unsigned long last;
+ int irqno;
+ int i;
+
+ /* first, clear all interrupts pending... */
+ last = 0;
+ for (i = 0; i < 4; i++) {
+ pend = __raw_readl(S3C2416_INTPND2);
+
+ if (pend == 0 || pend == last)
+ break;
+
+ __raw_writel(pend, S3C2416_SRCPND2);
+ __raw_writel(pend, S3C2416_INTPND2);
+ printk(KERN_INFO "irq: clearing pending status %08x\n",
+ (int)pend);
+ last = pend;
+ }
+
+ for (irqno = IRQ_S3C2416_2D; irqno <= IRQ_S3C2416_I2S1; irqno++) {
+ switch (irqno) {
+ case IRQ_S3C2416_RESERVED2:
+ case IRQ_S3C2416_RESERVED3:
+ /* no IRQ here */
+ break;
+ default:
+ irq_set_chip_and_handler(irqno, &s3c2416_irq_second,
+ handle_edge_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+ }
+}
+
+static int s3c2416_irq_add(struct device *dev,
+ struct subsys_interface *sif)
+{
+ printk(KERN_INFO "S3C2416: IRQ Support\n");
+
+ s3c2416_add_sub(IRQ_LCD, s3c2416_irq_demux_lcd, &s3c2416_irq_lcd,
+ IRQ_S3C2443_LCD2, IRQ_S3C2443_LCD4);
+
+ s3c2416_add_sub(IRQ_S3C2443_DMA, s3c2416_irq_demux_dma,
+ &s3c2416_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5);
+
+ s3c2416_add_sub(IRQ_S3C2443_UART3, s3c2416_irq_demux_uart3,
+ &s3c2416_irq_uart3,
+ IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3);
+
+ s3c2416_add_sub(IRQ_WDT, s3c2416_irq_demux_wdtac97,
+ &s3c2416_irq_wdtac97,
+ IRQ_S3C2443_WDT, IRQ_S3C2443_AC97);
+
+ s3c2416_irq_add_second();
+
+ return 0;
+}
+
+static struct subsys_interface s3c2416_irq_interface = {
+ .name = "s3c2416_irq",
+ .subsys = &s3c2416_subsys,
+ .add_dev = s3c2416_irq_add,
+};
+
+static int __init s3c2416_irq_init(void)
+{
+ return subsys_interface_register(&s3c2416_irq_interface);
+}
+
+arch_initcall(s3c2416_irq_init);
+
+#endif
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 5/9] ARM: S3C24XX: modify s3c2416 irq init to initialize all irqs
From: Heiko Stübner @ 2013-01-27 20:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201301272124.18530.heiko@sntech.de>
Previously the irq init used s3c24xx_init_irq and an additional
arch_initcall to add the cpu specific irqs.
To be able to simplyfy the irq init later, create a new function
s3c416_init_irq, which then calls s3c24xx_init_irq but also adds
the cpu specific irqs.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
arch/arm/mach-s3c24xx/mach-smdk2416.c | 2 +-
arch/arm/plat-s3c24xx/irq.c | 22 ++++------------------
arch/arm/plat-samsung/include/plat/s3c2416.h | 1 +
3 files changed, 6 insertions(+), 19 deletions(-)
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c
index 7de4120..2abb66f 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2416.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c
@@ -250,7 +250,7 @@ MACHINE_START(SMDK2416, "SMDK2416")
/* Maintainer: Yauhen Kharuzhy <jekhor@gmail.com> */
.atag_offset = 0x100,
- .init_irq = s3c24xx_init_irq,
+ .init_irq = s3c2416_init_irq,
.map_io = smdk2416_map_io,
.init_machine = smdk2416_machine_init,
.timer = &s3c24xx_timer,
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
index 131f747..3763b91 100644
--- a/arch/arm/plat-s3c24xx/irq.c
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -874,10 +874,11 @@ static void s3c2416_irq_add_second(void)
}
}
-static int s3c2416_irq_add(struct device *dev,
- struct subsys_interface *sif)
+void __init s3c2416_init_irq(void)
{
- printk(KERN_INFO "S3C2416: IRQ Support\n");
+ pr_info("S3C2416: IRQ Support\n");
+
+ s3c24xx_init_irq();
s3c2416_add_sub(IRQ_LCD, s3c2416_irq_demux_lcd, &s3c2416_irq_lcd,
IRQ_S3C2443_LCD2, IRQ_S3C2443_LCD4);
@@ -894,21 +895,6 @@ static int s3c2416_irq_add(struct device *dev,
IRQ_S3C2443_WDT, IRQ_S3C2443_AC97);
s3c2416_irq_add_second();
-
- return 0;
}
-static struct subsys_interface s3c2416_irq_interface = {
- .name = "s3c2416_irq",
- .subsys = &s3c2416_subsys,
- .add_dev = s3c2416_irq_add,
-};
-
-static int __init s3c2416_irq_init(void)
-{
- return subsys_interface_register(&s3c2416_irq_interface);
-}
-
-arch_initcall(s3c2416_irq_init);
-
#endif
diff --git a/arch/arm/plat-samsung/include/plat/s3c2416.h b/arch/arm/plat-samsung/include/plat/s3c2416.h
index 7178e33..f27399a 100644
--- a/arch/arm/plat-samsung/include/plat/s3c2416.h
+++ b/arch/arm/plat-samsung/include/plat/s3c2416.h
@@ -25,6 +25,7 @@ extern int s3c2416_baseclk_add(void);
extern void s3c2416_restart(char mode, const char *cmd);
+extern void s3c2416_init_irq(void);
extern struct syscore_ops s3c2416_irq_syscore_ops;
#else
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 6/9] ARM: S3C24XX: transform s3c2416 irqs into new structure
From: Heiko Stübner @ 2013-01-27 20:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201301272124.18530.heiko@sntech.de>
Share the common irq code by simply defining a correct mapping declaration
for the s3c2416.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
arch/arm/plat-s3c24xx/irq.c | 342 +++++++++++--------------------------------
1 file changed, 87 insertions(+), 255 deletions(-)
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
index 3763b91..c6d0d57 100644
--- a/arch/arm/plat-s3c24xx/irq.c
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -352,7 +352,8 @@ static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
handle_edge_irq);
break;
case S3C_IRQTYPE_EDGE:
- if (irq_data->parent_irq)
+ if (irq_data->parent_irq ||
+ intc->reg_pending == S3C2416_SRCPND2)
irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
handle_edge_irq);
else
@@ -628,273 +629,104 @@ void __init s3c24xx_init_irq(void)
}
#ifdef CONFIG_CPU_S3C2416
-#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
-
-static inline void s3c2416_irq_demux(unsigned int irq, unsigned int len)
-{
- unsigned int subsrc, submsk;
- unsigned int end;
-
- /* read the current pending interrupts, and the mask
- * for what it is available */
-
- subsrc = __raw_readl(S3C2410_SUBSRCPND);
- submsk = __raw_readl(S3C2410_INTSUBMSK);
-
- subsrc &= ~submsk;
- subsrc >>= (irq - S3C2410_IRQSUB(0));
- subsrc &= (1 << len)-1;
-
- end = len + irq;
-
- for (; irq < end && subsrc; irq++) {
- if (subsrc & 1)
- generic_handle_irq(irq);
-
- subsrc >>= 1;
- }
-}
-
-/* WDT/AC97 sub interrupts */
-
-static void s3c2416_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc)
-{
- s3c2416_irq_demux(IRQ_S3C2443_WDT, 4);
-}
-
-#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0))
-#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97)
-
-static void s3c2416_irq_wdtac97_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
-}
-
-static void s3c2416_irq_wdtac97_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97);
-}
-
-static void s3c2416_irq_wdtac97_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
-}
-
-static struct irq_chip s3c2416_irq_wdtac97 = {
- .irq_mask = s3c2416_irq_wdtac97_mask,
- .irq_unmask = s3c2416_irq_wdtac97_unmask,
- .irq_ack = s3c2416_irq_wdtac97_ack,
-};
-
-/* LCD sub interrupts */
-
-static void s3c2416_irq_demux_lcd(unsigned int irq, struct irq_desc *desc)
-{
- s3c2416_irq_demux(IRQ_S3C2443_LCD1, 4);
-}
-
-#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0))
-#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4)
-
-static void s3c2416_irq_lcd_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD);
-}
-
-static void s3c2416_irq_lcd_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_LCD);
-}
-
-static void s3c2416_irq_lcd_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD);
-}
-
-static struct irq_chip s3c2416_irq_lcd = {
- .irq_mask = s3c2416_irq_lcd_mask,
- .irq_unmask = s3c2416_irq_lcd_unmask,
- .irq_ack = s3c2416_irq_lcd_ack,
-};
-
-/* DMA sub interrupts */
-
-static void s3c2416_irq_demux_dma(unsigned int irq, struct irq_desc *desc)
-{
- s3c2416_irq_demux(IRQ_S3C2443_DMA0, 6);
-}
-
-#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0))
-#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5)
-
-
-static void s3c2416_irq_dma_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA);
-}
-
-static void s3c2416_irq_dma_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_DMA);
-}
-
-static void s3c2416_irq_dma_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA);
-}
-
-static struct irq_chip s3c2416_irq_dma = {
- .irq_mask = s3c2416_irq_dma_mask,
- .irq_unmask = s3c2416_irq_dma_unmask,
- .irq_ack = s3c2416_irq_dma_ack,
+static struct s3c_irq_data init_s3c2416base[32] = {
+ { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+ { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+ { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+ { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+ { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+ { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
+ { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+ { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* NAND */
+ { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+ { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+ { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+ { .type = S3C_IRQTYPE_NONE, },
+ { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
};
-/* UART3 sub interrupts */
-
-static void s3c2416_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
-{
- s3c2416_irq_demux(IRQ_S3C2443_RX3, 3);
-}
-
-#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
-#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
-
-static void s3c2416_irq_uart3_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3);
-}
-
-static void s3c2416_irq_uart3_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_UART3);
-}
-
-static void s3c2416_irq_uart3_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3);
-}
-
-static struct irq_chip s3c2416_irq_uart3 = {
- .irq_mask = s3c2416_irq_uart3_mask,
- .irq_unmask = s3c2416_irq_uart3_unmask,
- .irq_ack = s3c2416_irq_uart3_ack,
+static struct s3c_irq_data init_s3c2416subint[32] = {
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+ { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+ { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+ { .type = S3C_IRQTYPE_NONE }, /* reserved */
+ { .type = S3C_IRQTYPE_NONE }, /* reserved */
+ { .type = S3C_IRQTYPE_NONE }, /* reserved */
+ { .type = S3C_IRQTYPE_NONE }, /* reserved */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
};
-/* second interrupt register */
-
-static inline void s3c2416_irq_ack_second(struct irq_data *data)
-{
- unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D);
-
- __raw_writel(bitval, S3C2416_SRCPND2);
- __raw_writel(bitval, S3C2416_INTPND2);
-}
-
-static void s3c2416_irq_mask_second(struct irq_data *data)
-{
- unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D);
- unsigned long mask;
-
- mask = __raw_readl(S3C2416_INTMSK2);
- mask |= bitval;
- __raw_writel(mask, S3C2416_INTMSK2);
-}
-
-static void s3c2416_irq_unmask_second(struct irq_data *data)
-{
- unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D);
- unsigned long mask;
-
- mask = __raw_readl(S3C2416_INTMSK2);
- mask &= ~bitval;
- __raw_writel(mask, S3C2416_INTMSK2);
-}
-
-static struct irq_chip s3c2416_irq_second = {
- .irq_ack = s3c2416_irq_ack_second,
- .irq_mask = s3c2416_irq_mask_second,
- .irq_unmask = s3c2416_irq_unmask_second,
+static struct s3c_irq_data init_s3c2416_second[32] = {
+ { .type = S3C_IRQTYPE_EDGE }, /* 2D */
+ { .type = S3C_IRQTYPE_EDGE }, /* IIC1 */
+ { .type = S3C_IRQTYPE_NONE }, /* reserved */
+ { .type = S3C_IRQTYPE_NONE }, /* reserved */
+ { .type = S3C_IRQTYPE_EDGE }, /* PCM0 */
+ { .type = S3C_IRQTYPE_EDGE }, /* PCM1 */
+ { .type = S3C_IRQTYPE_EDGE }, /* I2S0 */
+ { .type = S3C_IRQTYPE_EDGE }, /* I2S1 */
};
-
-/* IRQ initialisation code */
-
-static int s3c2416_add_sub(unsigned int base,
- void (*demux)(unsigned int,
- struct irq_desc *),
- struct irq_chip *chip,
- unsigned int start, unsigned int end)
-{
- unsigned int irqno;
-
- irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq);
- irq_set_chained_handler(base, demux);
-
- for (irqno = start; irqno <= end; irqno++) {
- irq_set_chip_and_handler(irqno, chip, handle_level_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
-
- return 0;
-}
-
-static void s3c2416_irq_add_second(void)
-{
- unsigned long pend;
- unsigned long last;
- int irqno;
- int i;
-
- /* first, clear all interrupts pending... */
- last = 0;
- for (i = 0; i < 4; i++) {
- pend = __raw_readl(S3C2416_INTPND2);
-
- if (pend == 0 || pend == last)
- break;
-
- __raw_writel(pend, S3C2416_SRCPND2);
- __raw_writel(pend, S3C2416_INTPND2);
- printk(KERN_INFO "irq: clearing pending status %08x\n",
- (int)pend);
- last = pend;
- }
-
- for (irqno = IRQ_S3C2416_2D; irqno <= IRQ_S3C2416_I2S1; irqno++) {
- switch (irqno) {
- case IRQ_S3C2416_RESERVED2:
- case IRQ_S3C2416_RESERVED3:
- /* no IRQ here */
- break;
- default:
- irq_set_chip_and_handler(irqno, &s3c2416_irq_second,
- handle_edge_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
- }
-}
-
void __init s3c2416_init_irq(void)
{
- pr_info("S3C2416: IRQ Support\n");
-
- s3c24xx_init_irq();
+ struct s3c_irq_intc *main_intc;
- s3c2416_add_sub(IRQ_LCD, s3c2416_irq_demux_lcd, &s3c2416_irq_lcd,
- IRQ_S3C2443_LCD2, IRQ_S3C2443_LCD4);
+ pr_info("S3C2416: IRQ Support\n");
- s3c2416_add_sub(IRQ_S3C2443_DMA, s3c2416_irq_demux_dma,
- &s3c2416_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5);
+#ifdef CONFIG_FIQ
+ init_FIQ(FIQ_START);
+#endif
- s3c2416_add_sub(IRQ_S3C2443_UART3, s3c2416_irq_demux_uart3,
- &s3c2416_irq_uart3,
- IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3);
+ main_intc = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL, 0x4a000000);
+ if (IS_ERR(main_intc)) {
+ pr_err("irq: could not create main interrupt controller\n");
+ return;
+ }
- s3c2416_add_sub(IRQ_WDT, s3c2416_irq_demux_wdtac97,
- &s3c2416_irq_wdtac97,
- IRQ_S3C2443_WDT, IRQ_S3C2443_AC97);
+ s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
+ s3c24xx_init_intc(NULL, &init_s3c2416subint[0], main_intc, 0x4a000018);
- s3c2416_irq_add_second();
+ s3c24xx_init_intc(NULL, &init_s3c2416_second[0], NULL, 0x4a000040);
}
#endif
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 7/9] ARM: S3C24XX: move s3c2443 irq code to irq.c
From: Heiko Stübner @ 2013-01-27 20:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201301272124.18530.heiko@sntech.de>
Prequisite for further optimizations.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
arch/arm/mach-s3c24xx/Makefile | 2 +-
arch/arm/mach-s3c24xx/irq-s3c2443.c | 281 -----------------------------------
arch/arm/plat-s3c24xx/irq.c | 243 ++++++++++++++++++++++++++++++
3 files changed, 244 insertions(+), 282 deletions(-)
delete mode 100644 arch/arm/mach-s3c24xx/irq-s3c2443.c
diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile
index 68d134f..1d67582 100644
--- a/arch/arm/mach-s3c24xx/Makefile
+++ b/arch/arm/mach-s3c24xx/Makefile
@@ -39,7 +39,7 @@ obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o
obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o
obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o
-obj-$(CONFIG_CPU_S3C2443) += s3c2443.o irq-s3c2443.o clock-s3c2443.o
+obj-$(CONFIG_CPU_S3C2443) += s3c2443.o clock-s3c2443.o
# PM
diff --git a/arch/arm/mach-s3c24xx/irq-s3c2443.c b/arch/arm/mach-s3c24xx/irq-s3c2443.c
deleted file mode 100644
index 5e69109..0000000
--- a/arch/arm/mach-s3c24xx/irq-s3c2443.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/* linux/arch/arm/mach-s3c2443/irq.c
- *
- * Copyright (c) 2007 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/pm.h>
-#include <plat/irq.h>
-
-#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
-
-static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len)
-{
- unsigned int subsrc, submsk;
- unsigned int end;
-
- /* read the current pending interrupts, and the mask
- * for what it is available */
-
- subsrc = __raw_readl(S3C2410_SUBSRCPND);
- submsk = __raw_readl(S3C2410_INTSUBMSK);
-
- subsrc &= ~submsk;
- subsrc >>= (irq - S3C2410_IRQSUB(0));
- subsrc &= (1 << len)-1;
-
- end = len + irq;
-
- for (; irq < end && subsrc; irq++) {
- if (subsrc & 1)
- generic_handle_irq(irq);
-
- subsrc >>= 1;
- }
-}
-
-/* WDT/AC97 sub interrupts */
-
-static void s3c2443_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc)
-{
- s3c2443_irq_demux(IRQ_S3C2443_WDT, 4);
-}
-
-#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0))
-#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97)
-
-static void s3c2443_irq_wdtac97_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
-}
-
-static void s3c2443_irq_wdtac97_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97);
-}
-
-static void s3c2443_irq_wdtac97_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
-}
-
-static struct irq_chip s3c2443_irq_wdtac97 = {
- .irq_mask = s3c2443_irq_wdtac97_mask,
- .irq_unmask = s3c2443_irq_wdtac97_unmask,
- .irq_ack = s3c2443_irq_wdtac97_ack,
-};
-
-/* LCD sub interrupts */
-
-static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc)
-{
- s3c2443_irq_demux(IRQ_S3C2443_LCD1, 4);
-}
-
-#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0))
-#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4)
-
-static void s3c2443_irq_lcd_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD);
-}
-
-static void s3c2443_irq_lcd_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_LCD);
-}
-
-static void s3c2443_irq_lcd_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD);
-}
-
-static struct irq_chip s3c2443_irq_lcd = {
- .irq_mask = s3c2443_irq_lcd_mask,
- .irq_unmask = s3c2443_irq_lcd_unmask,
- .irq_ack = s3c2443_irq_lcd_ack,
-};
-
-/* DMA sub interrupts */
-
-static void s3c2443_irq_demux_dma(unsigned int irq, struct irq_desc *desc)
-{
- s3c2443_irq_demux(IRQ_S3C2443_DMA0, 6);
-}
-
-#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0))
-#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5)
-
-static void s3c2443_irq_dma_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA);
-}
-
-static void s3c2443_irq_dma_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_DMA);
-}
-
-static void s3c2443_irq_dma_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA);
-}
-
-static struct irq_chip s3c2443_irq_dma = {
- .irq_mask = s3c2443_irq_dma_mask,
- .irq_unmask = s3c2443_irq_dma_unmask,
- .irq_ack = s3c2443_irq_dma_ack,
-};
-
-/* UART3 sub interrupts */
-
-static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
-{
- s3c2443_irq_demux(IRQ_S3C2443_RX3, 3);
-}
-
-#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
-#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
-
-static void s3c2443_irq_uart3_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3);
-}
-
-static void s3c2443_irq_uart3_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_UART3);
-}
-
-static void s3c2443_irq_uart3_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3);
-}
-
-static struct irq_chip s3c2443_irq_uart3 = {
- .irq_mask = s3c2443_irq_uart3_mask,
- .irq_unmask = s3c2443_irq_uart3_unmask,
- .irq_ack = s3c2443_irq_uart3_ack,
-};
-
-/* CAM sub interrupts */
-
-static void s3c2443_irq_demux_cam(unsigned int irq, struct irq_desc *desc)
-{
- s3c2443_irq_demux(IRQ_S3C2440_CAM_C, 4);
-}
-
-#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
-#define SUBMSK_CAM INTMSK(IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P)
-
-static void s3c2443_irq_cam_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_CAM, SUBMSK_CAM);
-}
-
-static void s3c2443_irq_cam_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_CAM);
-}
-
-static void s3c2443_irq_cam_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_CAM, SUBMSK_CAM);
-}
-
-static struct irq_chip s3c2443_irq_cam = {
- .irq_mask = s3c2443_irq_cam_mask,
- .irq_unmask = s3c2443_irq_cam_unmask,
- .irq_ack = s3c2443_irq_cam_ack,
-};
-
-/* IRQ initialisation code */
-
-static int s3c2443_add_sub(unsigned int base,
- void (*demux)(unsigned int,
- struct irq_desc *),
- struct irq_chip *chip,
- unsigned int start, unsigned int end)
-{
- unsigned int irqno;
-
- irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq);
- irq_set_chained_handler(base, demux);
-
- for (irqno = start; irqno <= end; irqno++) {
- irq_set_chip_and_handler(irqno, chip, handle_level_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
-
- return 0;
-}
-
-static int s3c2443_irq_add(struct device *dev,
- struct subsys_interface *sif)
-{
- printk("S3C2443: IRQ Support\n");
-
- s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam,
- IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P);
-
- s3c2443_add_sub(IRQ_LCD, s3c2443_irq_demux_lcd, &s3c2443_irq_lcd,
- IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4);
-
- s3c2443_add_sub(IRQ_S3C2443_DMA, s3c2443_irq_demux_dma,
- &s3c2443_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5);
-
- s3c2443_add_sub(IRQ_S3C2443_UART3, s3c2443_irq_demux_uart3,
- &s3c2443_irq_uart3,
- IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3);
-
- s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97,
- &s3c2443_irq_wdtac97,
- IRQ_S3C2443_WDT, IRQ_S3C2443_AC97);
-
- return 0;
-}
-
-static struct subsys_interface s3c2443_irq_interface = {
- .name = "s3c2443_irq",
- .subsys = &s3c2443_subsys,
- .add_dev = s3c2443_irq_add,
-};
-
-static int __init s3c2443_irq_init(void)
-{
- return subsys_interface_register(&s3c2443_irq_interface);
-}
-
-arch_initcall(s3c2443_irq_init);
-
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
index c6d0d57..0a051eb 100644
--- a/arch/arm/plat-s3c24xx/irq.c
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -730,3 +730,246 @@ void __init s3c2416_init_irq(void)
}
#endif
+
+#ifdef CONFIG_CPU_S3C2443
+#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
+
+static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len)
+{
+ unsigned int subsrc, submsk;
+ unsigned int end;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+ subsrc = __raw_readl(S3C2410_SUBSRCPND);
+ submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+ subsrc &= ~submsk;
+ subsrc >>= (irq - S3C2410_IRQSUB(0));
+ subsrc &= (1 << len)-1;
+
+ end = len + irq;
+
+ for (; irq < end && subsrc; irq++) {
+ if (subsrc & 1)
+ generic_handle_irq(irq);
+
+ subsrc >>= 1;
+ }
+}
+
+/* WDT/AC97 sub interrupts */
+
+static void s3c2443_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2443_irq_demux(IRQ_S3C2443_WDT, 4);
+}
+
+#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0))
+#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97)
+
+static void s3c2443_irq_wdtac97_mask(struct irq_data *data)
+{
+ s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+}
+
+static void s3c2443_irq_wdtac97_unmask(struct irq_data *data)
+{
+ s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97);
+}
+
+static void s3c2443_irq_wdtac97_ack(struct irq_data *data)
+{
+ s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
+}
+
+static struct irq_chip s3c2443_irq_wdtac97 = {
+ .irq_mask = s3c2443_irq_wdtac97_mask,
+ .irq_unmask = s3c2443_irq_wdtac97_unmask,
+ .irq_ack = s3c2443_irq_wdtac97_ack,
+};
+
+/* LCD sub interrupts */
+
+static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2443_irq_demux(IRQ_S3C2443_LCD1, 4);
+}
+
+#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0))
+#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4)
+
+static void s3c2443_irq_lcd_mask(struct irq_data *data)
+{
+ s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD);
+}
+
+static void s3c2443_irq_lcd_unmask(struct irq_data *data)
+{
+ s3c_irqsub_unmask(data->irq, INTMSK_LCD);
+}
+
+static void s3c2443_irq_lcd_ack(struct irq_data *data)
+{
+ s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD);
+}
+
+static struct irq_chip s3c2443_irq_lcd = {
+ .irq_mask = s3c2443_irq_lcd_mask,
+ .irq_unmask = s3c2443_irq_lcd_unmask,
+ .irq_ack = s3c2443_irq_lcd_ack,
+};
+
+/* DMA sub interrupts */
+
+static void s3c2443_irq_demux_dma(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2443_irq_demux(IRQ_S3C2443_DMA0, 6);
+}
+
+#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0))
+#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5)
+
+static void s3c2443_irq_dma_mask(struct irq_data *data)
+{
+ s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA);
+}
+
+static void s3c2443_irq_dma_unmask(struct irq_data *data)
+{
+ s3c_irqsub_unmask(data->irq, INTMSK_DMA);
+}
+
+static void s3c2443_irq_dma_ack(struct irq_data *data)
+{
+ s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA);
+}
+
+static struct irq_chip s3c2443_irq_dma = {
+ .irq_mask = s3c2443_irq_dma_mask,
+ .irq_unmask = s3c2443_irq_dma_unmask,
+ .irq_ack = s3c2443_irq_dma_ack,
+};
+
+/* UART3 sub interrupts */
+
+static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2443_irq_demux(IRQ_S3C2443_RX3, 3);
+}
+
+#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
+#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
+
+static void s3c2443_irq_uart3_mask(struct irq_data *data)
+{
+ s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3);
+}
+
+static void s3c2443_irq_uart3_unmask(struct irq_data *data)
+{
+ s3c_irqsub_unmask(data->irq, INTMSK_UART3);
+}
+
+static void s3c2443_irq_uart3_ack(struct irq_data *data)
+{
+ s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3);
+}
+
+static struct irq_chip s3c2443_irq_uart3 = {
+ .irq_mask = s3c2443_irq_uart3_mask,
+ .irq_unmask = s3c2443_irq_uart3_unmask,
+ .irq_ack = s3c2443_irq_uart3_ack,
+};
+
+/* CAM sub interrupts */
+
+static void s3c2443_irq_demux_cam(unsigned int irq, struct irq_desc *desc)
+{
+ s3c2443_irq_demux(IRQ_S3C2440_CAM_C, 4);
+}
+
+#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
+#define SUBMSK_CAM INTMSK(IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P)
+
+static void s3c2443_irq_cam_mask(struct irq_data *data)
+{
+ s3c_irqsub_mask(data->irq, INTMSK_CAM, SUBMSK_CAM);
+}
+
+static void s3c2443_irq_cam_unmask(struct irq_data *data)
+{
+ s3c_irqsub_unmask(data->irq, INTMSK_CAM);
+}
+
+static void s3c2443_irq_cam_ack(struct irq_data *data)
+{
+ s3c_irqsub_maskack(data->irq, INTMSK_CAM, SUBMSK_CAM);
+}
+
+static struct irq_chip s3c2443_irq_cam = {
+ .irq_mask = s3c2443_irq_cam_mask,
+ .irq_unmask = s3c2443_irq_cam_unmask,
+ .irq_ack = s3c2443_irq_cam_ack,
+};
+
+/* IRQ initialisation code */
+
+static int s3c2443_add_sub(unsigned int base,
+ void (*demux)(unsigned int,
+ struct irq_desc *),
+ struct irq_chip *chip,
+ unsigned int start, unsigned int end)
+{
+ unsigned int irqno;
+
+ irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq);
+ irq_set_chained_handler(base, demux);
+
+ for (irqno = start; irqno <= end; irqno++) {
+ irq_set_chip_and_handler(irqno, chip, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ return 0;
+}
+
+static int s3c2443_irq_add(struct device *dev,
+ struct subsys_interface *sif)
+{
+ printk("S3C2443: IRQ Support\n");
+
+ s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam,
+ IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P);
+
+ s3c2443_add_sub(IRQ_LCD, s3c2443_irq_demux_lcd, &s3c2443_irq_lcd,
+ IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4);
+
+ s3c2443_add_sub(IRQ_S3C2443_DMA, s3c2443_irq_demux_dma,
+ &s3c2443_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5);
+
+ s3c2443_add_sub(IRQ_S3C2443_UART3, s3c2443_irq_demux_uart3,
+ &s3c2443_irq_uart3,
+ IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3);
+
+ s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97,
+ &s3c2443_irq_wdtac97,
+ IRQ_S3C2443_WDT, IRQ_S3C2443_AC97);
+
+ return 0;
+}
+
+static struct subsys_interface s3c2443_irq_interface = {
+ .name = "s3c2443_irq",
+ .subsys = &s3c2443_subsys,
+ .add_dev = s3c2443_irq_add,
+};
+
+static int __init s3c2443_irq_init(void)
+{
+ return subsys_interface_register(&s3c2443_irq_interface);
+}
+
+arch_initcall(s3c2443_irq_init);
+#endif
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 8/9] ARM: S3C24XX: modify s3c2443 irq init to initialize all irqs
From: Heiko Stübner @ 2013-01-27 20:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201301272124.18530.heiko@sntech.de>
Previously the irq init used s3c24xx_init_irq and an additional
arch_initcall to add the cpu specific irqs.
To be able to simplyfy the irq init later, create a new function
s3c2443_init_irq, which then calls s3c24xx_init_irq but also adds
the cpu specific irqs.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
arch/arm/mach-s3c24xx/mach-smdk2443.c | 2 +-
arch/arm/plat-s3c24xx/irq.c | 22 ++++------------------
arch/arm/plat-samsung/include/plat/s3c2443.h | 2 ++
3 files changed, 7 insertions(+), 19 deletions(-)
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2443.c b/arch/arm/mach-s3c24xx/mach-smdk2443.c
index c6d1a03..8b65a54 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2443.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2443.c
@@ -140,7 +140,7 @@ MACHINE_START(SMDK2443, "SMDK2443")
/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
.atag_offset = 0x100,
- .init_irq = s3c24xx_init_irq,
+ .init_irq = s3c2443_init_irq,
.map_io = smdk2443_map_io,
.init_machine = smdk2443_machine_init,
.timer = &s3c24xx_timer,
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
index 0a051eb..4cf3c13 100644
--- a/arch/arm/plat-s3c24xx/irq.c
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -935,10 +935,11 @@ static int s3c2443_add_sub(unsigned int base,
return 0;
}
-static int s3c2443_irq_add(struct device *dev,
- struct subsys_interface *sif)
+void __init s3c2443_init_irq(void)
{
- printk("S3C2443: IRQ Support\n");
+ pr_info("S3C2443: IRQ Support\n");
+
+ s3c24xx_init_irq();
s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam,
IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P);
@@ -956,20 +957,5 @@ static int s3c2443_irq_add(struct device *dev,
s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97,
&s3c2443_irq_wdtac97,
IRQ_S3C2443_WDT, IRQ_S3C2443_AC97);
-
- return 0;
}
-
-static struct subsys_interface s3c2443_irq_interface = {
- .name = "s3c2443_irq",
- .subsys = &s3c2443_subsys,
- .add_dev = s3c2443_irq_add,
-};
-
-static int __init s3c2443_irq_init(void)
-{
- return subsys_interface_register(&s3c2443_irq_interface);
-}
-
-arch_initcall(s3c2443_irq_init);
#endif
diff --git a/arch/arm/plat-samsung/include/plat/s3c2443.h b/arch/arm/plat-samsung/include/plat/s3c2443.h
index a5b794f..71b88ec 100644
--- a/arch/arm/plat-samsung/include/plat/s3c2443.h
+++ b/arch/arm/plat-samsung/include/plat/s3c2443.h
@@ -25,6 +25,8 @@ extern void s3c2443_init_clocks(int xtal);
extern int s3c2443_baseclk_add(void);
extern void s3c2443_restart(char mode, const char *cmd);
+
+extern void s3c2443_init_irq(void);
#else
#define s3c2443_init_clocks NULL
#define s3c2443_init_uarts NULL
--
1.7.10.4
^ permalink raw reply related
* [PATCH v4 9/9] ARM: S3C24XX: transform s3c2443 subirqs into new structure
From: Heiko Stübner @ 2013-01-27 20:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201301272124.18530.heiko@sntech.de>
Share the common irq code by simply defining a correct mapping declaration
for the s3c2443.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
arch/arm/plat-s3c24xx/irq.c | 289 +++++++++++--------------------------------
1 file changed, 75 insertions(+), 214 deletions(-)
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
index 4cf3c13..969426b 100644
--- a/arch/arm/plat-s3c24xx/irq.c
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -732,230 +732,91 @@ void __init s3c2416_init_irq(void)
#endif
#ifdef CONFIG_CPU_S3C2443
-#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
-
-static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len)
-{
- unsigned int subsrc, submsk;
- unsigned int end;
-
- /* read the current pending interrupts, and the mask
- * for what it is available */
-
- subsrc = __raw_readl(S3C2410_SUBSRCPND);
- submsk = __raw_readl(S3C2410_INTSUBMSK);
-
- subsrc &= ~submsk;
- subsrc >>= (irq - S3C2410_IRQSUB(0));
- subsrc &= (1 << len)-1;
-
- end = len + irq;
-
- for (; irq < end && subsrc; irq++) {
- if (subsrc & 1)
- generic_handle_irq(irq);
-
- subsrc >>= 1;
- }
-}
-
-/* WDT/AC97 sub interrupts */
-
-static void s3c2443_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc)
-{
- s3c2443_irq_demux(IRQ_S3C2443_WDT, 4);
-}
-
-#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0))
-#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97)
-
-static void s3c2443_irq_wdtac97_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
-}
-
-static void s3c2443_irq_wdtac97_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97);
-}
-
-static void s3c2443_irq_wdtac97_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
-}
-
-static struct irq_chip s3c2443_irq_wdtac97 = {
- .irq_mask = s3c2443_irq_wdtac97_mask,
- .irq_unmask = s3c2443_irq_wdtac97_unmask,
- .irq_ack = s3c2443_irq_wdtac97_ack,
-};
-
-/* LCD sub interrupts */
-
-static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc)
-{
- s3c2443_irq_demux(IRQ_S3C2443_LCD1, 4);
-}
-
-#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0))
-#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4)
-
-static void s3c2443_irq_lcd_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD);
-}
-
-static void s3c2443_irq_lcd_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_LCD);
-}
-
-static void s3c2443_irq_lcd_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD);
-}
-
-static struct irq_chip s3c2443_irq_lcd = {
- .irq_mask = s3c2443_irq_lcd_mask,
- .irq_unmask = s3c2443_irq_lcd_unmask,
- .irq_ack = s3c2443_irq_lcd_ack,
-};
-
-/* DMA sub interrupts */
-
-static void s3c2443_irq_demux_dma(unsigned int irq, struct irq_desc *desc)
-{
- s3c2443_irq_demux(IRQ_S3C2443_DMA0, 6);
-}
-
-#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0))
-#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5)
-
-static void s3c2443_irq_dma_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA);
-}
-
-static void s3c2443_irq_dma_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_DMA);
-}
-
-static void s3c2443_irq_dma_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA);
-}
-
-static struct irq_chip s3c2443_irq_dma = {
- .irq_mask = s3c2443_irq_dma_mask,
- .irq_unmask = s3c2443_irq_dma_unmask,
- .irq_ack = s3c2443_irq_dma_ack,
-};
-
-/* UART3 sub interrupts */
-
-static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
-{
- s3c2443_irq_demux(IRQ_S3C2443_RX3, 3);
-}
-
-#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
-#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
-
-static void s3c2443_irq_uart3_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3);
-}
-
-static void s3c2443_irq_uart3_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_UART3);
-}
-
-static void s3c2443_irq_uart3_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3);
-}
-
-static struct irq_chip s3c2443_irq_uart3 = {
- .irq_mask = s3c2443_irq_uart3_mask,
- .irq_unmask = s3c2443_irq_uart3_unmask,
- .irq_ack = s3c2443_irq_uart3_ack,
+static struct s3c_irq_data init_s3c2443base[32] = {
+ { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+ { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+ { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+ { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
+ { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* CFON */
+ { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* NAND */
+ { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+ { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+ { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+ { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+ { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
};
-/* CAM sub interrupts */
-static void s3c2443_irq_demux_cam(unsigned int irq, struct irq_desc *desc)
-{
- s3c2443_irq_demux(IRQ_S3C2440_CAM_C, 4);
-}
-
-#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
-#define SUBMSK_CAM INTMSK(IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P)
-
-static void s3c2443_irq_cam_mask(struct irq_data *data)
-{
- s3c_irqsub_mask(data->irq, INTMSK_CAM, SUBMSK_CAM);
-}
-
-static void s3c2443_irq_cam_unmask(struct irq_data *data)
-{
- s3c_irqsub_unmask(data->irq, INTMSK_CAM);
-}
-
-static void s3c2443_irq_cam_ack(struct irq_data *data)
-{
- s3c_irqsub_maskack(data->irq, INTMSK_CAM, SUBMSK_CAM);
-}
-
-static struct irq_chip s3c2443_irq_cam = {
- .irq_mask = s3c2443_irq_cam_mask,
- .irq_unmask = s3c2443_irq_cam_unmask,
- .irq_ack = s3c2443_irq_cam_ack,
+static struct s3c_irq_data init_s3c2443subint[32] = {
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+ { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+ { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
+ { .type = S3C_IRQTYPE_NONE }, /* reserved */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD1 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
+ { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
};
-/* IRQ initialisation code */
-
-static int s3c2443_add_sub(unsigned int base,
- void (*demux)(unsigned int,
- struct irq_desc *),
- struct irq_chip *chip,
- unsigned int start, unsigned int end)
-{
- unsigned int irqno;
-
- irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq);
- irq_set_chained_handler(base, demux);
-
- for (irqno = start; irqno <= end; irqno++) {
- irq_set_chip_and_handler(irqno, chip, handle_level_irq);
- set_irq_flags(irqno, IRQF_VALID);
- }
-
- return 0;
-}
-
void __init s3c2443_init_irq(void)
{
- pr_info("S3C2443: IRQ Support\n");
-
- s3c24xx_init_irq();
-
- s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam,
- IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P);
+ struct s3c_irq_intc *main_intc;
- s3c2443_add_sub(IRQ_LCD, s3c2443_irq_demux_lcd, &s3c2443_irq_lcd,
- IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4);
+ pr_info("S3C2443: IRQ Support\n");
- s3c2443_add_sub(IRQ_S3C2443_DMA, s3c2443_irq_demux_dma,
- &s3c2443_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5);
+#ifdef CONFIG_FIQ
+ init_FIQ(FIQ_START);
+#endif
- s3c2443_add_sub(IRQ_S3C2443_UART3, s3c2443_irq_demux_uart3,
- &s3c2443_irq_uart3,
- IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3);
+ main_intc = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL, 0x4a000000);
+ if (IS_ERR(main_intc)) {
+ pr_err("irq: could not create main interrupt controller\n");
+ return;
+ }
- s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97,
- &s3c2443_irq_wdtac97,
- IRQ_S3C2443_WDT, IRQ_S3C2443_AC97);
+ s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
+ s3c24xx_init_intc(NULL, &init_s3c2443subint[0], main_intc, 0x4a000018);
}
#endif
--
1.7.10.4
^ permalink raw reply related
* [PATCHv3] ARM: sunxi: gpio: Add Allwinner SoCs GPIO drivers
From: Emilio López @ 2013-01-27 22:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359192670-22543-1-git-send-email-maxime.ripard@free-electrons.com>
Hello Maxime,
El 26/01/13 06:31, Maxime Ripard escribi?:
> The IP responsible for the muxing on the Allwinner SoCs are also
> handling the GPIOs on the system. This patch adds the needed driver that
> relies on the pinctrl driver for most of its operations.
>
> The number of pins available for GPIOs operations are already declared
> in the pinctrl driver, we only need to probe a generic driver to handle
> the banks available for each SoC.
>
> This driver has been tested on a A13-Olinuxino.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
> Changes from v2:
> - Removed the call to kzalloc to build the pin name
>
> drivers/pinctrl/pinctrl-sunxi.c | 134 ++++++++++++++++++++++++++++++++++++++-
> drivers/pinctrl/pinctrl-sunxi.h | 25 +++++++-
> 2 files changed, 156 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
> index 6f02e34..4ed0e7e 100644
> --- a/drivers/pinctrl/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/pinctrl-sunxi.c
> @@ -11,6 +11,7 @@
> */
>
> #include <linux/io.h>
> +#include <linux/gpio.h>
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/of_address.h>
> @@ -609,11 +610,53 @@ static int sunxi_pmx_enable(struct pinctrl_dev *pctldev,
> return 0;
> }
>
> +static int
> +sunxi_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
> + struct pinctrl_gpio_range *range,
> + unsigned offset,
> + bool input)
> +{
> + struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
> + struct sunxi_desc_function *desc;
> + char pin_name[SUNXI_PIN_NAME_MAX_LEN];
> + char *func;
> + u8 bank, pin;
> + int ret;
> +
> + bank = (offset) / PINS_PER_BANK;
> + pin = (offset) % PINS_PER_BANK;
> +
> + ret = sprintf(pin_name, "P%c%d", 'A' + bank, pin);
> + if (!ret)
> + goto error;
> +
> + if (input)
> + func = "gpio_in";
> + else
> + func = "gpio_out";
> +
> + desc = sunxi_pinctrl_desc_find_function_by_name(pctl,
> + pin_name,
> + func);
> + if (!desc) {
> + ret = -EINVAL;
> + goto error;
> + }
> +
> + sunxi_pmx_set(pctldev, offset, desc->muxval);
> +
> + ret = 0;
> +
> +error:
> + return ret;
> +}
> +
> static struct pinmux_ops sunxi_pmx_ops = {
> .get_functions_count = sunxi_pmx_get_funcs_cnt,
> .get_function_name = sunxi_pmx_get_func_name,
> .get_function_groups = sunxi_pmx_get_func_groups,
> .enable = sunxi_pmx_enable,
> + .gpio_set_direction = sunxi_pmx_gpio_set_direction,
> };
>
> static struct pinctrl_desc sunxi_pctrl_desc = {
> @@ -622,6 +665,60 @@ static struct pinctrl_desc sunxi_pctrl_desc = {
> .pmxops = &sunxi_pmx_ops,
> };
>
> +static int sunxi_pinctrl_gpio_request(struct gpio_chip *chip, unsigned offset)
> +{
> + return pinctrl_request_gpio(chip->base + offset);
> +}
> +
> +static void sunxi_pinctrl_gpio_free(struct gpio_chip *chip, unsigned offset)
> +{
> + pinctrl_free_gpio(chip->base + offset);
> +}
> +
> +static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip,
> + unsigned offset)
> +{
> + return pinctrl_gpio_direction_input(chip->base + offset);
> +}
> +
> +static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset)
> +{
> + struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
> +
> + u32 reg = sunxi_data_reg(offset);
> + u8 index = sunxi_data_offset(offset);
> + u32 val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK;
> +
> + return val;
> +}
> +
> +static int sunxi_pinctrl_gpio_direction_output(struct gpio_chip *chip,
> + unsigned offset, int value)
> +{
> + return pinctrl_gpio_direction_output(chip->base + offset);
> +}
> +
> +static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip,
> + unsigned offset, int value)
> +{
> + struct sunxi_pinctrl *pctl = dev_get_drvdata(chip->dev);
> + u32 reg = sunxi_data_reg(offset);
> + u8 index = sunxi_data_offset(offset);
> +
> + writel((value & DATA_PINS_MASK) << index, pctl->membase + reg);
> +}
> +
> +static struct gpio_chip sunxi_pinctrl_gpio_chip __devinitconst = {
__devinitconst got dropped on commit 54b956b9, "Remove __dev* markings
from init.h".
Thanks for the patches, I will be trying them on my A10 board soon.
--
Emilio
^ permalink raw reply
* [PATCH v2 0/3] Kirkwoode cpufreq driver
From: Rafael J. Wysocki @ 2013-01-27 22:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130126230459.GU1758@titan.lakedaemon.net>
On Saturday, January 26, 2013 06:04:59 PM Jason Cooper wrote:
> On Sat, Jan 26, 2013 at 10:52:42PM +0100, Rafael J. Wysocki wrote:
> > On Saturday, January 26, 2013 04:43:56 PM Andrew Lunn wrote:
> > > This patchset adds a cpufreq driver for Marvell Kirkwood SoCs.
> > >
> > > The changes to kirkwood_defconfig enable it and set the default
> > > governor to ondemand.
> > >
> > > Changes since v1:
> > >
> > > tabify Kconfig.arm entry
> > > Sort order of include files
> > > Remove some unnecassary include files
> > > Reformat multiline comment to be coding style conform.
> > >
> > > Andrew Lunn (3):
> > > cpufreq: kirkwood: Add a cpufreq driver for Marvell Kirkwood SoCs
> > > arm: kirkwood: Instantiate cpufreq driver
> > > arm: kirkwood: Enable cpufreq and ondemand on kirkwood_defconfig
> >
> > If you want me to take this, it'll need some ACKs from the clk people
> > and arm-soc maintainers at least.
>
> In the past, we've sent the driver changes (patch #1) through the
> appropriate driver maintainer's tree, and the subsequent patches (2 & 3)
> through arm-soc with a listed dependency on the driver maintainer's
> tree/branch. We've found that causes the fewest conflicts/headaches
> that way.
>
> If you're Ok with that, just let me know which tree and branch you pull
> it in to.
Yes, that would be fine by me. In the future, though, please say in the
comment part of the changelog (i.e. between the sign-off tag and the actual
patch) who's the target maintainer of the patch.
When patch [1/3] is ready, it will be applied to the pm-cpufreq branch of the
linux-pm.git tree (that branch doesn't contain any new material at the
moment, because I'm having issues with one of the candidate commits and
I'm debugging them).
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply
* [PATCH 02/26] mfd: ab8500-sysctrl: If a charger is present, reboot instead
From: Samuel Ortiz @ 2013-01-27 23:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358254566-12419-3-git-send-email-lee.jones@linaro.org>
Hi Lee,
On Tue, Jan 15, 2013 at 12:55:42PM +0000, Lee Jones wrote:
> From: Jonas Aaberg <jonas.aberg@stericsson.com>
>
> If a changer is attached on power off, reboot the system
s/changer/charger/
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply
* [PATCH 05/26] mfd: ab8500-gpadc: Change to mdelay for greater resolution
From: Samuel Ortiz @ 2013-01-27 23:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358254566-12419-6-git-send-email-lee.jones@linaro.org>
Hi Lee, Jonas,
On Tue, Jan 15, 2013 at 12:55:45PM +0000, Lee Jones wrote:
> From: Jonas Aaberg <jonas.aberg@stericsson.com>
>
> The resolution of msleep is related to HZ, so with HZ set to
> 100 any msleep of less than 10ms will become ~10ms.
usleep_range would be more appropriate, sleeping should be preferred over
spinning.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply
* [PATCH 06/26] mfd: ab8500-sysctrl: Provide configuration for SysClkReqRfClkBuf registers
From: Samuel Ortiz @ 2013-01-27 23:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358254566-12419-7-git-send-email-lee.jones@linaro.org>
Hi Lee, Kennet,
On Tue, Jan 15, 2013 at 12:55:46PM +0000, Lee Jones wrote:
> From: Kennet Wallden <kennet.wallden@stericsson.com>
>
> Add the possibility to pass configuration settings for
> SysCl1kReqRfClkBuf to SysClk8ReqRfClkBuf via platform data.
>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> Signed-off-by: Kennet Wallden <kennet.wallden@stericsson.com>
> Reviewed-by: Karl-Johan PERNTZ <karl-johan.perntz@stericsson.com>
> Reviewed-by: Bengt JONSSON <bengt.g.jonsson@stericsson.com>
> ---
> drivers/mfd/ab8500-sysctrl.c | 25 +++++++++++++++++++++++++
> include/linux/mfd/abx500/ab8500-sysctrl.h | 5 +++++
> include/linux/mfd/abx500/ab8500.h | 2 ++
> 3 files changed, 32 insertions(+)
>
> diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
> index cf58f69..19a024e 100644
> --- a/drivers/mfd/ab8500-sysctrl.c
> +++ b/drivers/mfd/ab8500-sysctrl.c
> @@ -113,11 +113,36 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)
> static int __devinit ab8500_sysctrl_probe(struct platform_device *pdev)
> {
> struct ab8500_platform_data *plat;
> + struct ab8500_sysctrl_platform_data *pdata;
>
> sysctrl_dev = &pdev->dev;
> plat = dev_get_platdata(pdev->dev.parent);
> if (plat->pm_power_off)
> pm_power_off = ab8500_power_off;
> +
> + pdata = plat->sysctrl;
> +
> + if (pdata) {
> + int ret;
> + int i;
> + int j;
Cosmetic
int i, j, ret;
> + for (i = AB8500_SYSCLKREQ1RFCLKBUF;
> + i <= AB8500_SYSCLKREQ8RFCLKBUF; i++) {
> + j = i - AB8500_SYSCLKREQ1RFCLKBUF;
> + ret = ab8500_sysctrl_write(i, 0xff,
> + pdata->initial_req_buf_config[j]);
> + dev_dbg(&pdev->dev,
> + "Setting SysClkReq%dRfClkBuf 0x%X\n",
> + j + 1,
> + pdata->initial_req_buf_config[j]);
> + if (ret < 0) {
> + dev_err(&pdev->dev,
> + "unable to set sysClkReq%dRfClkBuf: "
> + "%d\n", j + 1, ret);
> + }
> + }
> + }
> +
> return 0;
> }
>
> diff --git a/include/linux/mfd/abx500/ab8500-sysctrl.h b/include/linux/mfd/abx500/ab8500-sysctrl.h
> index 10eb509..ebf12e7 100644
> --- a/include/linux/mfd/abx500/ab8500-sysctrl.h
> +++ b/include/linux/mfd/abx500/ab8500-sysctrl.h
> @@ -37,6 +37,11 @@ static inline int ab8500_sysctrl_clear(u16 reg, u8 bits)
> return ab8500_sysctrl_write(reg, bits, 0);
> }
>
> +/* Configuration data for SysClkReq1RfClkBuf - SysClkReq8RfClkBuf */
> +struct ab8500_sysctrl_platform_data {
> + u8 initial_req_buf_config[8];
> +};
> +
> /* Registers */
> #define AB8500_TURNONSTATUS 0x100
> #define AB8500_RESETSTATUS 0x101
> diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h
> index 96840c4..3f4e6d1 100644
> --- a/include/linux/mfd/abx500/ab8500.h
> +++ b/include/linux/mfd/abx500/ab8500.h
> @@ -270,6 +270,7 @@ struct regulator_reg_init;
> struct regulator_init_data;
> struct ab8500_gpio_platform_data;
> struct ab8500_codec_platform_data;
> +struct ab8500_sysctrl_platform_data;
>
> /**
> * struct ab8500_platform_data - AB8500 platform data
> @@ -291,6 +292,7 @@ struct ab8500_platform_data {
> struct regulator_init_data *regulator;
> struct ab8500_gpio_platform_data *gpio;
> struct ab8500_codec_platform_data *codec;
> + struct ab8500_sysctrl_platform_data *sysctrl;
> };
>
> extern int __devinit ab8500_init(struct ab8500 *ab8500,
> --
> 1.7.9.5
>
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply
* [PATCH 09/26] mfd: ab8500-debugfs: Provide a means for a user subscribe to IRQs
From: Samuel Ortiz @ 2013-01-27 23:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358254566-12419-10-git-send-email-lee.jones@linaro.org>
Hi Lee,
On Tue, Jan 15, 2013 at 12:55:49PM +0000, Lee Jones wrote:
> Allow users to subscribe to and view IRQ events live from debugfs.
I seem to remember that I got a similar patch some time ago for the same
purpose and my answer was: Please use a UIO driver for this. There already is
such driver, it's uio_pdrv_genirq. What your debugfs registration entry could
do is adding a platform device for the specific interrupt number. This would
avoid the irq handler registration and the sysfs entry creation, both things I
believe are not very elegant and open coded. It also gives you an IRQ count
implementation.
Ideally, the UIO framework could be improved to support IRQ ranges (through
IRQ domains) instead of the current single interrupt number.
Have you considered going through that path ?
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply
* [PATCH 10/26] mfd: ab8500-debugfs: Wake-up device on debugfs IRQ
From: Samuel Ortiz @ 2013-01-27 23:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358254566-12419-11-git-send-email-lee.jones@linaro.org>
Hi Lee,
On Tue, Jan 15, 2013 at 12:55:50PM +0000, Lee Jones wrote:
> Ensure the device wakes up if the debugfs IRQ fires if we're
> in suspend mode.
>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
> drivers/mfd/ab8500-debugfs.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
Please squash this one with the previous one.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply
* [PATCH 13/26] mfd: ab8500-debugfs: Formated access AB8500 registers from debugfs entry
From: Samuel Ortiz @ 2013-01-27 23:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358254566-12419-14-git-send-email-lee.jones@linaro.org>
Hi Lee,
On Tue, Jan 15, 2013 at 12:55:53PM +0000, Lee Jones wrote:
> +static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg,
> + struct device *dev)
> +{
> + uint write, val = 0;
> + struct hwreg_cfg loc = {
> + .bank = 0, /* default: invalid phys addr */
> + .addr = 0, /* default: invalid phys addr */
> + .fmt = 0, /* default: 32bit access, hex output */
> + .mask = 0xFFFFFFFF, /* default: no mask */
> + .shift = 0, /* default: no bit shift */
> + };
> +
> + /* read or write ? */
> + if (!strncmp(b, "read ", 5)) {
> + write = 0;
> + b += 5;
> + } else if (!strncmp(b, "write ", 6)) {
> + write = 1;
> + b += 6;
> + } else
> + return -EINVAL;
> +
> + /* OPTIONS -l|-w|-b -s -m -o */
> + while ((*b == ' ') || (*b == '-')) {
> + if (*(b-1) != ' ') {
> + b++;
> + continue;
> + }
> + if ((!strncmp(b, "-d ", 3)) ||
> + (!strncmp(b, "-dec ", 5))) {
> + b += (*(b+2) == ' ') ? 3 : 5;
> + loc.fmt |= (1<<0);
> + } else if ((!strncmp(b, "-h ", 3)) ||
> + (!strncmp(b, "-hex ", 5))) {
> + b += (*(b+2) == ' ') ? 3 : 5;
> + loc.fmt &= ~(1<<0);
> + } else if ((!strncmp(b, "-m ", 3)) ||
> + (!strncmp(b, "-mask ", 6))) {
> + b += (*(b+2) == ' ') ? 3 : 6;
> + if (strval_len(b) == 0)
> + return -EINVAL;
> + loc.mask = simple_strtoul(b, &b, 0);
> + } else if ((!strncmp(b, "-s ", 3)) ||
> + (!strncmp(b, "-shift ", 7))) {
> + b += (*(b+2) == ' ') ? 3 : 7;
> + if (strval_len(b) == 0)
> + return -EINVAL;
> + loc.shift = simple_strtol(b, &b, 0);
> + } else {
> + return -EINVAL;
> + }
> + }
> + /* get arg BANK and ADDRESS */
> + if (strval_len(b) == 0)
> + return -EINVAL;
> + loc.bank = simple_strtoul(b, &b, 0);
> + while (*b == ' ')
> + b++;
> + if (strval_len(b) == 0)
> + return -EINVAL;
> + loc.addr = simple_strtoul(b, &b, 0);
> +
> + if (write) {
> + while (*b == ' ')
> + b++;
> + if (strval_len(b) == 0)
> + return -EINVAL;
> + val = simple_strtoul(b, &b, 0);
> + }
> +
> + /* args are ok, update target cfg (mainly for read) */
> + *cfg = loc;
> +
> +#if ABB_HWREG_DEBUG
> + pr_warn("HWREG request: %s, %s, addr=0x%08X, mask=0x%X, shift=%d
> + value=0x%X\n", (write) ? "write" : "read",
> + REG_FMT_DEC(cfg) ? "decimal" : "hexa",
> + cfg->addr, cfg->mask, cfg->shift, val);
> +#endif
> +
> + if (write) {
if (!write)
return 0;
for a more readable code.
> + u8 regvalue;
> + int ret = abx500_get_register_interruptible(dev,
> + (u8)cfg->bank, (u8)cfg->addr, ®value);
> + if (ret < 0) {
> + dev_err(dev, "abx500_get_reg fail %d, %d\n",
> + ret, __LINE__);
> + return -EINVAL;
> + }
> +
> + if (cfg->shift >= 0) {
> + regvalue &= ~(cfg->mask << (cfg->shift));
> + val = (val & cfg->mask) << (cfg->shift);
> + } else {
> + regvalue &= ~(cfg->mask >> (-cfg->shift));
> + val = (val & cfg->mask) >> (-cfg->shift);
> + }
> + val = val | regvalue;
> +
> + ret = abx500_set_register_interruptible(dev,
> + (u8)cfg->bank, (u8)cfg->addr, (u8)val);
> + if (ret < 0) {
> + pr_err("abx500_set_reg failed %d, %d", ret, __LINE__);
> + return -EINVAL;
> + }
> +
> + }
> + return 0;
> +}
I think this is a pretty big routine, that could be split into a command
parsing part and the actual register write one.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply
* [PATCH 14/26] mfd: ab8500-debugfs: Fix introduced compiler time warnings
From: Samuel Ortiz @ 2013-01-27 23:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358254566-12419-15-git-send-email-lee.jones@linaro.org>
Hi Lee,
On Tue, Jan 15, 2013 at 12:55:54PM +0000, Lee Jones wrote:
> From: Philippe Langlais <philippe.langlais@stericsson.com>
>
> Some simple fixes regarding pre-processor usage.
>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> Signed-off-by: Philippe Langlais <philippe.langlais@linaro.org>
> ---
> drivers/mfd/ab8500-debugfs.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
Here again, please squash this one with the previous one.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox