From: tony@atomide.com (Tony Lindgren)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 05/10] ARM: OMAP2+: Fix support for multiple devices on a GPMC chip select
Date: Wed, 29 Oct 2014 17:29:03 -0700 [thread overview]
Message-ID: <1414628948-30702-6-git-send-email-tony@atomide.com> (raw)
In-Reply-To: <1414628948-30702-1-git-send-email-tony@atomide.com>
There are cases where we have multiple device instances
connected to a single GPMC chip select. For example, there
are four UARTs on the Zoom debug boards that all share a
single chip select and a GPIO interrupt.
We do have support for this already in theory, but it's broken
because we're bailing out if the chip select is already taken.
To be able to provide checks on the chip select usage, let's
add new struct gpmc_cs_data so we can start using already
registered device names for checks.
Later on we probably want to start using struct gpmc_cs_data
as a wrapper for all the GPMC chipselect related data.
Cc: Roger Quadros <rogerq@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
arch/arm/mach-omap2/gpmc.c | 61 +++++++++++++++++++++++++++++++++++++---------
1 file changed, 49 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 5fa3755..2c5f348 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -118,6 +118,15 @@
*/
#define GPMC_NR_IRQ 2
+struct gpmc_cs_data {
+ const char *name;
+
+#define GPMC_CS_RESERVED (1 << 0)
+ u32 flags;
+
+ struct resource mem;
+};
+
struct gpmc_client_irq {
unsigned irq;
u32 bitmask;
@@ -155,10 +164,9 @@ static struct irq_chip gpmc_irq_chip;
static int gpmc_irq_start;
static struct resource gpmc_mem_root;
-static struct resource gpmc_cs_mem[GPMC_CS_NUM];
+static struct gpmc_cs_data gpmc_cs[GPMC_CS_NUM];
static DEFINE_SPINLOCK(gpmc_mem_lock);
/* Define chip-selects as reserved by default until probe completes */
-static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1);
static unsigned int gpmc_cs_num = GPMC_CS_NUM;
static unsigned int gpmc_nr_waitpins;
static struct device *gpmc_dev;
@@ -460,13 +468,30 @@ static int gpmc_cs_mem_enabled(int cs)
static void gpmc_cs_set_reserved(int cs, int reserved)
{
- gpmc_cs_map &= ~(1 << cs);
- gpmc_cs_map |= (reserved ? 1 : 0) << cs;
+ struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+
+ gpmc->flags |= GPMC_CS_RESERVED;
}
static bool gpmc_cs_reserved(int cs)
{
- return gpmc_cs_map & (1 << cs);
+ struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+
+ return gpmc->flags & GPMC_CS_RESERVED;
+}
+
+static void gpmc_cs_set_name(int cs, const char *name)
+{
+ struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+
+ gpmc->name = name;
+}
+
+const char *gpmc_cs_get_name(int cs)
+{
+ struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+
+ return gpmc->name;
}
static unsigned long gpmc_mem_align(unsigned long size)
@@ -485,7 +510,8 @@ static unsigned long gpmc_mem_align(unsigned long size)
static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
{
- struct resource *res = &gpmc_cs_mem[cs];
+ struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+ struct resource *res = &gpmc->mem;
int r;
size = gpmc_mem_align(size);
@@ -500,7 +526,8 @@ static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
static int gpmc_cs_delete_mem(int cs)
{
- struct resource *res = &gpmc_cs_mem[cs];
+ struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+ struct resource *res = &gpmc->mem;
int r;
spin_lock(&gpmc_mem_lock);
@@ -557,7 +584,8 @@ static int gpmc_cs_remap(int cs, u32 base)
int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
{
- struct resource *res = &gpmc_cs_mem[cs];
+ struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+ struct resource *res = &gpmc->mem;
int r = -1;
if (cs > gpmc_cs_num) {
@@ -597,7 +625,8 @@ EXPORT_SYMBOL(gpmc_cs_request);
void gpmc_cs_free(int cs)
{
- struct resource *res = &gpmc_cs_mem[cs];
+ struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+ struct resource *res = &gpmc->mem;
spin_lock(&gpmc_mem_lock);
if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) {
@@ -1511,6 +1540,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
struct gpmc_timings gpmc_t;
struct resource res;
unsigned long base;
+ const char *name;
int ret, cs;
if (of_property_read_u32(child, "reg", &cs) < 0) {
@@ -1525,11 +1555,21 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
return -ENODEV;
}
+ /*
+ * Check if we have multiple instances of the same device
+ * on a single chip select. If so, use the already initialized
+ * timings.
+ */
+ name = gpmc_cs_get_name(cs);
+ if (name && child->name && of_node_cmp(child->name, name) == 0)
+ goto no_timings;
+
ret = gpmc_cs_request(cs, resource_size(&res), &base);
if (ret < 0) {
dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
return ret;
}
+ gpmc_cs_set_name(cs, child->name);
/*
* For some GPMC devices we still need to rely on the bootloader
@@ -1708,9 +1748,6 @@ static int gpmc_probe(struct platform_device *pdev)
if (gpmc_setup_irq() < 0)
dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
- /* Now the GPMC is initialised, unreserve the chip-selects */
- gpmc_cs_map = 0;
-
if (!pdev->dev.of_node) {
gpmc_cs_num = GPMC_CS_NUM;
gpmc_nr_waitpins = GPMC_NR_WAITPINS;
--
2.1.1
next prev parent reply other threads:[~2014-10-30 0:29 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-30 0:28 [PATCH 00/10] omap gpmc and board clean-up for v3.19 merge window Tony Lindgren
2014-10-30 0:28 ` [PATCH 01/10] ARM: dts: Fix bootloader version dependencies by muxing n900 smc91x pins Tony Lindgren
2014-10-30 11:59 ` Roger Quadros
2014-10-30 15:49 ` Tony Lindgren
2014-11-03 9:30 ` Roger Quadros
2014-10-30 0:29 ` [PATCH 02/10] ARM: dts: Fix wrong GPMC size mappings for omaps Tony Lindgren
2014-10-30 12:05 ` Roger Quadros
2014-10-30 0:29 ` [PATCH 03/10] ARM: dts: Add smc91x GPMC configuration for 2430sdp Tony Lindgren
2014-10-30 0:29 ` [PATCH 04/10] ARM: dts: Add GPMC timings for omap zoom serial port Tony Lindgren
2014-10-30 12:21 ` Roger Quadros
2014-10-30 0:29 ` Tony Lindgren [this message]
2014-10-30 12:26 ` [PATCH 05/10] ARM: OMAP2+: Fix support for multiple devices on a GPMC chip select Roger Quadros
2014-10-30 0:29 ` [PATCH 06/10] ARM: OMAP2+: Show bootloader GPMC timings to allow configuring the .dts file Tony Lindgren
2014-10-30 14:19 ` Roger Quadros
2014-10-30 14:45 ` Tony Lindgren
2014-10-30 15:04 ` Roger Quadros
2014-10-30 16:30 ` Tony Lindgren
2014-10-31 9:24 ` Roger Quadros
2014-11-04 13:40 ` Roger Quadros
2014-11-04 15:49 ` Tony Lindgren
2014-10-30 14:26 ` Roger Quadros
2014-10-30 0:29 ` [PATCH 07/10] ARM: OMAP2+: Require proper GPMC timings for devices Tony Lindgren
2014-10-30 14:27 ` Roger Quadros
2014-10-30 0:29 ` [PATCH 08/10] ARM: OMAP2+: Drop legacy code for gpmc-smc91x.c Tony Lindgren
2014-10-30 14:28 ` Roger Quadros
2014-10-30 0:29 ` [PATCH 09/10] ARM: OMAP2+: Drop board file for ti8168evm Tony Lindgren
2014-10-30 0:29 ` [PATCH 10/10] ARM: omap2plus: Drop board file for 3430sdp Tony Lindgren
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1414628948-30702-6-git-send-email-tony@atomide.com \
--to=tony@atomide.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).