Skip to contentSkip to conversation

CPM1: implement GPIO LIB API

PATCH/RFC Jochen Friedrich 4 participants 5 messages Jan 17, 2008

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

---
arch/powerpc/platforms/8xx/Kconfig | 2 +
arch/powerpc/sysdev/commproc.c | 162 +++++++++++++++++++++++++++++++++++-

2 files changed, 163 insertions(+), 1 deletions(-)
arch/powerpc/platforms/8xx/Kconfig +0 -0
index 91fbe42..08e927c 100644
@@ -4,6 +4,8 @@ config FADS

config CPM1
bool
select CPM
+ select GENERIC_GPIO
+ select GPIO_LIB

choice
prompt "8xx Machine Type"

arch/powerpc/sysdev/commproc.c +0 -0
index 621bc6c..be78e65 100644
@@ -36,6 +36,7 @@

#include <asm/8xx_immap.h>
#include <asm/commproc.h>
#include <asm/io.h>
+#include <asm/gpio.h>
#include <asm/tlbflush.h>
#include <asm/rheap.h>
#include <asm/prom.h>
@@ -441,7 +442,7 @@ struct cpm_ioport16 {
};

struct cpm_ioport32 {
- __be32 dir, par, sor;
+ __be32 dir, par, sor, dat;
};

static void cpm1_set_pin32(int port, int pin, int flags)
@@ -648,3 +649,162 @@ int cpm1_clk_setup(enum cpm_clk_target target, int clock, int mode)

	return 0;
}

+
+/*
+ * GPIO LIB API implementation
+ */
+
+static int cpm1_gpio_get16(struct gpio_chip *gc, unsigned int gpio) +{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct cpm_ioport16 __iomem *iop = mm_gc->regs;
+ u16 pin_mask;
+
+ pin_mask = 1 << (15 - gpio);
+
+ return !!(in_be16(&iop->dat) & pin_mask);
+}
+
+static void cpm1_gpio_set16(struct gpio_chip *gc, unsigned int gpio, int value) +{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct cpm_ioport16 __iomem *iop = mm_gc->regs;
+ u16 pin_mask;
+
+ pin_mask = 1 << (15 - gpio);
+
+ if (value)
+ setbits16(&iop->dat, pin_mask);
+ else
+ clrbits16(&iop->dat, pin_mask);
+}
+
+static int cpm1_gpio_dir_out16(struct gpio_chip *gc, unsigned int gpio, int val) +{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct cpm_ioport16 __iomem *iop = mm_gc->regs;
+ u16 pin_mask;
+
+ pin_mask = 1 << (15 - gpio);
+
+ setbits16(&iop->dir, pin_mask);
+
+ cpm1_gpio_set16(gc, gpio, val);
+
+ return 0;
+}
+
+static int cpm1_gpio_dir_in16(struct gpio_chip *gc, unsigned int gpio) +{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct cpm_ioport16 __iomem *iop = mm_gc->regs;
+ u16 pin_mask;
+
+ pin_mask = 1 << (15 - gpio);
+
+ clrbits16(&iop->dir, pin_mask);
+
+ return 0;
+}
+
+static struct of_gpio_chip cpm1_gc16 = {
+ .gpio_cells = 1,
+ .xlate = of_gpio_simple_xlate,
+
+ .gc = {
+ .ngpio = 16,
+ .direction_input = cpm1_gpio_dir_in16,
+ .direction_output = cpm1_gpio_dir_out16,
+ .get = cpm1_gpio_get16,
+ .set = cpm1_gpio_set16,
+ },
+};
+
+int cpm1_gpiochip_add16(struct device_node *np)
+{
+ return of_mm_gpiochip_add(np, &cpm1_gc16);
+}
+
+static int cpm1_gpio_get32(struct gpio_chip *gc, unsigned int gpio) +{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct cpm_ioport32 __iomem *iop = mm_gc->regs;
+ u32 pin_mask;
+
+ pin_mask = 1 << (31 - gpio);
+
+ return !!(in_be32(&iop->dat) & pin_mask);
+}
+
+static void cpm1_gpio_set32(struct gpio_chip *gc, unsigned int gpio, int value) +{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct cpm_ioport32 __iomem *iop = mm_gc->regs;
+ u32 pin_mask;
+
+ pin_mask = 1 << (31 - gpio);
+
+ if (value)
+ setbits32(&iop->dat, pin_mask);
+ else
+ clrbits32(&iop->dat, pin_mask);
+}
+
+static int cpm1_gpio_dir_out32(struct gpio_chip *gc, unsigned int gpio, int val) +{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct cpm_ioport32 __iomem *iop = mm_gc->regs;
+ u32 pin_mask;
+
+ pin_mask = 1 << (31 - gpio);
+
+ setbits32(&iop->dir, pin_mask);
+
+ cpm1_gpio_set32(gc, gpio, val);
+
+ return 0;
+}
+
+static int cpm1_gpio_dir_in32(struct gpio_chip *gc, unsigned int gpio) +{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct cpm_ioport32 __iomem *iop = mm_gc->regs;
+ u32 pin_mask;
+
+ pin_mask = 1 << (31 - gpio);
+
+ clrbits32(&iop->dir, pin_mask);
+
+ return 0;
+}
+
+static struct of_gpio_chip cpm1_gc32 = {
+ .gpio_cells = 1,
+ .xlate = of_gpio_simple_xlate,
+
+ .gc = {
+ .ngpio = 32,
+ .direction_input = cpm1_gpio_dir_in32,
+ .direction_output = cpm1_gpio_dir_out32,
+ .get = cpm1_gpio_get32,
+ .set = cpm1_gpio_set32,
+ },
+};
+
+int cpm1_gpiochip_add32(struct device_node *np)
+{
+ return of_mm_gpiochip_add(np, &cpm1_gc32);
+}
+
+static int cpm_init_par_io(void)
+{
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank16")
+ cpm1_gpiochip_add16(np);
+
+ for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank32")
+ cpm1_gpiochip_add32(np);
+ return 0;
+}
+arch_initcall(cpm_init_par_io);

Signature · 1 line
1.5.3.8
#1 lore raw

Hi Jochen,

Thanks for the patch.

Quoted 6 lines · Jochen Friedrich

---
arch/powerpc/platforms/8xx/Kconfig | 2 +
arch/powerpc/sysdev/commproc.c | 162
+++++++++++++++++++++++++++++++++++-

2 files changed, 163 insertions(+), 1 deletions(-)

Something happened wrt long lines, your editor seem to wrap them. :-(

Quoted 5 lines
arch/powerpc/platforms/8xx/Kconfig +0 -0
index 91fbe42..08e927c 100644

[...]

Quoted 4 lines
arch/powerpc/sysdev/commproc.c +0 -0
index 621bc6c..be78e65 100644

[...]

arch/powerpc/sysdev/commproc.c

Quoted 4 lines
arch/powerpc/sysdev/commproc.c +4 -0
+int cpm1_gpiochip_add16(struct device_node *np)
+{
+	return of_mm_gpiochip_add(np, &cpm1_gc16);
+}

(1)

arch/powerpc/sysdev/commproc.c

Quoted 4 lines
arch/powerpc/sysdev/commproc.c +4 -0
+int cpm1_gpiochip_add32(struct device_node *np)
+{
+	return of_mm_gpiochip_add(np, &cpm1_gc32);
+}

(2)

arch/powerpc/sysdev/commproc.c

Quoted 12 lines
arch/powerpc/sysdev/commproc.c +12 -0
+static int cpm_init_par_io(void)
+{
+	struct device_node *np;
+
+	for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank16")
+		cpm1_gpiochip_add16(np);
+
+	for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank32")
+		cpm1_gpiochip_add32(np);
+	return 0;
+}
+arch_initcall(cpm_init_par_io);

I was unable to use arch_initcall() because lack of kmalloc() that early (needed for of_mm_gpiochip_add() and GPIO LIB in general). So, does it really work here?

Though, I tried arch_initcall() in the board file, and well... link order matters a lot, so arch_initcall could indeed work in the arch/powerpc/sysdev/. I should try that for QE. :-)

If it works, you'd better make (1) and (2) static, or just remove them completely, since there are no users outside of this file.

Thanks!

Signature · 4 lines
Anton Vorontsov
email: [email protected]
backup email: [email protected]
irc://irc.freenode.net/bd2
#2 lore raw
In reply to Jochen Friedrich

Hi Jochen,

comments below.

Quoted 2 lines · Jochen Friedrich

---

Need a more detailed change description.

Quoted 2 lines
 arch/powerpc/platforms/8xx/Kconfig |    2 +
 arch/powerpc/sysdev/commproc.c     |  162 +++++++++++++++++++++++++++++++++++-

Is this 8xx only? Can it live in arch/powerpc/platforms/8xx?

Quoted 14 lines
 2 files changed, 163 insertions(+), 1 deletions(-)
(quoted diff) +12 -0
+static struct of_gpio_chip cpm1_gc16 = {
+       .gpio_cells = 1,
+       .xlate = of_gpio_simple_xlate,
+
+       .gc = {
+               .ngpio = 16,
+               .direction_input = cpm1_gpio_dir_in16,
+               .direction_output = cpm1_gpio_dir_out16,
+               .get = cpm1_gpio_get16,
+               .set = cpm1_gpio_set16,
+       },
+};

<snip>

Review

Quoted 12 lines
(quoted diff) +12 -0
+static struct of_gpio_chip cpm1_gc32 = {
+       .gpio_cells = 1,
+       .xlate = of_gpio_simple_xlate,
+
+       .gc = {
+               .ngpio = 32,
+               .direction_input = cpm1_gpio_dir_in32,
+               .direction_output = cpm1_gpio_dir_out32,
+               .get = cpm1_gpio_get32,
+               .set = cpm1_gpio_set32,
+       },
+};

Nit: Your naming convention seems a little backwards. It took me a moment to figure out what your hooks lined up with. Can you make the '16' and '32' part of the prefix instead of appended on the end?

ie. use 'cpm1_gpio16_dir_in' instead of 'cpm1_gpio_dir_in16'

Review

Quoted 4 lines
(quoted diff) +4 -0
+int cpm1_gpiochip_add32(struct device_node *np)
+{
+       return of_mm_gpiochip_add(np, &cpm1_gc32);
+}

Can you just drop this function and roll it into cpm_init_par_io?

Review

Quoted 13 lines
(quoted diff) +13 -0
+
+static int cpm_init_par_io(void)
+{
+       struct device_node *np;
+
+       for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank16")
+               cpm1_gpiochip_add16(np);
+
+       for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank32")
+               cpm1_gpiochip_add32(np);
+       return 0;
+}
+arch_initcall(cpm_init_par_io);

Cheers,
g.

Signature · 2 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
#3 lore raw

Hi Grant,

Quoted 4 lines
Quoted 2 lines
 arch/powerpc/platforms/8xx/Kconfig |    2 +
 arch/powerpc/sysdev/commproc.c     |  162 +++++++++++++++++++++++++++++++++++-

Is this 8xx only? Can it live in arch/powerpc/platforms/8xx?

According to the freescale docs, the GPIO ports are part of the CPM1. So I've put the support into commproc.c (which maybe should be renamed to cpm1_common.c to match cpm2_common.c).

AFAIK, CPM1 is specific to 8xx.

Thanks,
Jochen

#4 lore raw
Quoted 11 lines · Jochen Friedrich

Hi Grant,

Quoted 4 lines
Quoted 2 lines
 arch/powerpc/platforms/8xx/Kconfig |    2 +
 arch/powerpc/sysdev/commproc.c     |  162 +++++++++++++++++++++++++++++++++++-

Is this 8xx only? Can it live in arch/powerpc/platforms/8xx?

According to the freescale docs, the GPIO ports are part of the CPM1. So I've put the support into commproc.c (which maybe should be renamed to cpm1_common.c to match cpm2_common.c).

AFAIK, CPM1 is specific to 8xx.

If we're going to rename, I'd change commproc.c to cpm1.c, and cpm2_common.c to cpm2.c.

-Scott