* Re: [RFC/PATCH 2/2] powerpc: irqtrace support to 64-bit powerpc
From: Benjamin Herrenschmidt @ 2007-10-15 9:25 UTC (permalink / raw)
To: Johannes Berg; +Cc: linuxppc-dev
In-Reply-To: <1192437681.3349.12.camel@johannes.berg>
>
> > --- linux-work.orig/include/asm-powerpc/irqflags.h 2007-10-15 17:10:12.000000000 +1000
> > +++ linux-work/include/asm-powerpc/irqflags.h 2007-10-15 17:11:09.000000000 +1000
>
> > /*
> > - * Do the CPU's IRQ-state tracing from assembly code. We call a
> > - * C function, so save all the C-clobbered registers:
> > + * Most of the CPU's IRQ-state tracing is done from assembly code; we
> > + * have to call a C function so call a wrapper that saves all the
> > + * C-clobbered registers.
> > */
>
> That comment is now wrong, it should probably be removed.
Ah yes, it's stale, I'll get rid of it. Thanks.
Ben.
^ permalink raw reply
* [PATCH 1/5] Update ibm_newemac to use dcr_host_t.base
From: Michael Ellerman @ 2007-10-15 9:34 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, jgarzik
Now that dcr_host_t contains the base address, we can use that in the
ibm_newemac code, rather than storing it separately.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
drivers/net/ibm_newemac/mal.c | 9 +++++----
drivers/net/ibm_newemac/mal.h | 5 ++---
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
index 5885411..748a869 100644
--- a/drivers/net/ibm_newemac/mal.c
+++ b/drivers/net/ibm_newemac/mal.c
@@ -461,6 +461,7 @@ static int __devinit mal_probe(struct of_device *ofdev,
struct mal_instance *mal;
int err = 0, i, bd_size;
int index = mal_count++;
+ unsigned int dcr_base;
const u32 *prop;
u32 cfg;
@@ -497,14 +498,14 @@ static int __devinit mal_probe(struct of_device *ofdev,
}
mal->num_rx_chans = prop[0];
- mal->dcr_base = dcr_resource_start(ofdev->node, 0);
- if (mal->dcr_base == 0) {
+ dcr_base = dcr_resource_start(ofdev->node, 0);
+ if (dcr_base == 0) {
printk(KERN_ERR
"mal%d: can't find DCR resource!\n", index);
err = -ENODEV;
goto fail;
}
- mal->dcr_host = dcr_map(ofdev->node, mal->dcr_base, 0x100);
+ mal->dcr_host = dcr_map(ofdev->node, dcr_base, 0x100);
if (!DCR_MAP_OK(mal->dcr_host)) {
printk(KERN_ERR
"mal%d: failed to map DCRs !\n", index);
@@ -626,7 +627,7 @@ static int __devinit mal_probe(struct of_device *ofdev,
fail2:
dma_free_coherent(&ofdev->dev, bd_size, mal->bd_virt, mal->bd_dma);
fail_unmap:
- dcr_unmap(mal->dcr_host, mal->dcr_base, 0x100);
+ dcr_unmap(mal->dcr_host, dcr_base, 0x100);
fail:
kfree(mal);
diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h
index cb1a16d..6daa98e 100644
--- a/drivers/net/ibm_newemac/mal.h
+++ b/drivers/net/ibm_newemac/mal.h
@@ -185,7 +185,6 @@ struct mal_commac {
struct mal_instance {
int version;
- int dcr_base;
dcr_host_t dcr_host;
int num_tx_chans; /* Number of TX channels */
@@ -213,12 +212,12 @@ struct mal_instance {
static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg)
{
- return dcr_read(mal->dcr_host, mal->dcr_base + reg);
+ return dcr_read(mal->dcr_host, mal->dcr_host.base + reg);
}
static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val)
{
- dcr_write(mal->dcr_host, mal->dcr_base + reg, val);
+ dcr_write(mal->dcr_host, mal->dcr_host.base + reg, val);
}
/* Register MAL devices */
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 2/5] Use dcr_host_t.base in ibm_emac_mal
From: Michael Ellerman @ 2007-10-15 9:34 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, jgarzik
In-Reply-To: <33ee227bae85a8d7ccde69a717cff47000888354.1192440801.git.michael@ellerman.id.au>
This requires us to do a sort-of fake dcr_map(), so that base is set
properly. This will be fixed/removed when the device-tree-aware emac driver
is merged.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
drivers/net/ibm_emac/ibm_emac_mal.c | 5 ++++-
drivers/net/ibm_emac/ibm_emac_mal.h | 5 ++---
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.c b/drivers/net/ibm_emac/ibm_emac_mal.c
index 4e49e8c..dcd8826 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.c
+++ b/drivers/net/ibm_emac/ibm_emac_mal.c
@@ -413,7 +413,10 @@ static int __init mal_probe(struct ocp_device *ocpdev)
ocpdev->def->index);
return -ENOMEM;
}
- mal->dcrbase = maldata->dcr_base;
+
+ /* XXX This only works for native dcr for now */
+ mal->dcrhost = dcr_map(NULL, maldata->dcr_base, 0);
+
mal->def = ocpdev->def;
INIT_LIST_HEAD(&mal->poll_list);
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.h b/drivers/net/ibm_emac/ibm_emac_mal.h
index 8f54d62..aa76d3f 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.h
+++ b/drivers/net/ibm_emac/ibm_emac_mal.h
@@ -191,7 +191,6 @@ struct mal_commac {
};
struct ibm_ocp_mal {
- int dcrbase;
dcr_host_t dcrhost;
struct list_head poll_list;
@@ -209,12 +208,12 @@ struct ibm_ocp_mal {
static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg)
{
- return dcr_read(mal->dcrhost, mal->dcrbase + reg);
+ return dcr_read(mal->dcrhost, mal->dcrhost.base + reg);
}
static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val)
{
- dcr_write(mal->dcrhost, mal->dcrbase + reg, val);
+ dcr_write(mal->dcrhost, mal->dcrhost.base + reg, val);
}
/* Register MAL devices */
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 3/5] Add dcr_host_t.base in dcr_read()/dcr_write()
From: Michael Ellerman @ 2007-10-15 9:34 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, jgarzik
In-Reply-To: <33ee227bae85a8d7ccde69a717cff47000888354.1192440801.git.michael@ellerman.id.au>
Now that all users of dcr_read()/dcr_write() add the dcr_host_t.base, we
can save them the trouble and do it in dcr_read()/dcr_write().
As some background to why we just went through all this jiggery-pokery,
benh sayeth:
Initially the goal of the dcr_read/dcr_write routines was to operate like
mfdcr/mtdcr which take absolute DCR numbers. The reason is that on 4xx
hardware, indirect DCR access is a pain (goes through a table of
instructions) and it's useful to have the compiler resolve an absolute DCR
inline.
We decided that wasn't worth the API bastardisation since most places
where absolute DCR values are used are low level 4xx-only code which may
as well continue using mfdcr/mtdcr, while the new API is designed for
device "instances" that can exist on 4xx and Axon type platforms and may
be located at variable DCR offsets.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/axon_msi.c | 4 ++--
arch/powerpc/sysdev/mpic.c | 4 ++--
drivers/net/ibm_emac/ibm_emac_mal.h | 4 ++--
drivers/net/ibm_newemac/mal.h | 4 ++--
include/asm-powerpc/dcr-mmio.h | 4 ++--
include/asm-powerpc/dcr-native.h | 4 ++--
6 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 1245b2f..aca1500 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -77,12 +77,12 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
{
pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
- dcr_write(msic->dcr_host, msic->dcr_host.base + dcr_n, val);
+ dcr_write(msic->dcr_host, dcr_n, val);
}
static u32 msic_dcr_read(struct axon_msic *msic, unsigned int dcr_n)
{
- return dcr_read(msic->dcr_host, msic->dcr_host.base + dcr_n);
+ return dcr_read(msic->dcr_host, dcr_n);
}
static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 893e654..e479388 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -156,7 +156,7 @@ static inline u32 _mpic_read(enum mpic_reg_type type,
switch(type) {
#ifdef CONFIG_PPC_DCR
case mpic_access_dcr:
- return dcr_read(rb->dhost, rb->dhost.base + reg);
+ return dcr_read(rb->dhost, reg);
#endif
case mpic_access_mmio_be:
return in_be32(rb->base + (reg >> 2));
@@ -173,7 +173,7 @@ static inline void _mpic_write(enum mpic_reg_type type,
switch(type) {
#ifdef CONFIG_PPC_DCR
case mpic_access_dcr:
- return dcr_write(rb->dhost, rb->dhost.base + reg, value);
+ return dcr_write(rb->dhost, reg, value);
#endif
case mpic_access_mmio_be:
return out_be32(rb->base + (reg >> 2), value);
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.h b/drivers/net/ibm_emac/ibm_emac_mal.h
index aa76d3f..b8adbe6 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.h
+++ b/drivers/net/ibm_emac/ibm_emac_mal.h
@@ -208,12 +208,12 @@ struct ibm_ocp_mal {
static inline u32 get_mal_dcrn(struct ibm_ocp_mal *mal, int reg)
{
- return dcr_read(mal->dcrhost, mal->dcrhost.base + reg);
+ return dcr_read(mal->dcrhost, reg);
}
static inline void set_mal_dcrn(struct ibm_ocp_mal *mal, int reg, u32 val)
{
- dcr_write(mal->dcrhost, mal->dcrhost.base + reg, val);
+ dcr_write(mal->dcrhost, reg, val);
}
/* Register MAL devices */
diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h
index 6daa98e..784edb8 100644
--- a/drivers/net/ibm_newemac/mal.h
+++ b/drivers/net/ibm_newemac/mal.h
@@ -212,12 +212,12 @@ struct mal_instance {
static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg)
{
- return dcr_read(mal->dcr_host, mal->dcr_host.base + reg);
+ return dcr_read(mal->dcr_host, reg);
}
static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val)
{
- dcr_write(mal->dcr_host, mal->dcr_host.base + reg, val);
+ dcr_write(mal->dcr_host, reg, val);
}
/* Register MAL devices */
diff --git a/include/asm-powerpc/dcr-mmio.h b/include/asm-powerpc/dcr-mmio.h
index 6b82c3b..a7d9eaf 100644
--- a/include/asm-powerpc/dcr-mmio.h
+++ b/include/asm-powerpc/dcr-mmio.h
@@ -37,12 +37,12 @@ extern void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c);
static inline u32 dcr_read(dcr_host_t host, unsigned int dcr_n)
{
- return in_be32(host.token + dcr_n * host.stride);
+ return in_be32(host.token + ((host.base + dcr_n) * host.stride));
}
static inline void dcr_write(dcr_host_t host, unsigned int dcr_n, u32 value)
{
- out_be32(host.token + dcr_n * host.stride, value);
+ out_be32(host.token + ((host.base + dcr_n) * host.stride), value);
}
extern u64 of_translate_dcr_address(struct device_node *dev,
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h
index f41058c..3bc780f 100644
--- a/include/asm-powerpc/dcr-native.h
+++ b/include/asm-powerpc/dcr-native.h
@@ -30,8 +30,8 @@ typedef struct {
#define dcr_map(dev, dcr_n, dcr_c) ((dcr_host_t){ .base = (dcr_n) })
#define dcr_unmap(host, dcr_n, dcr_c) do {} while (0)
-#define dcr_read(host, dcr_n) mfdcr(dcr_n)
-#define dcr_write(host, dcr_n, value) mtdcr(dcr_n, value)
+#define dcr_read(host, dcr_n) mfdcr(dcr_n + host.base)
+#define dcr_write(host, dcr_n, value) mtdcr(dcr_n + host.base, value)
/* Device Control Registers */
void __mtdcr(int reg, unsigned int val);
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 4/5] Use dcr_host_t.base in dcr_unmap()
From: Michael Ellerman @ 2007-10-15 9:34 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, jgarzik
In-Reply-To: <33ee227bae85a8d7ccde69a717cff47000888354.1192440801.git.michael@ellerman.id.au>
With the base stored in dcr_host_t, there's no need for callers to pass
the dcr_n into dcr_unmap(). In fact this removes the possibility of them
passing the incorrect value, which would then be iounmap()'ed.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/sysdev/dcr.c | 4 ++--
drivers/net/ibm_newemac/mal.c | 2 +-
include/asm-powerpc/dcr-mmio.h | 2 +-
include/asm-powerpc/dcr-native.h | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c
index ab11c0b..427027c 100644
--- a/arch/powerpc/sysdev/dcr.c
+++ b/arch/powerpc/sysdev/dcr.c
@@ -126,13 +126,13 @@ dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n,
}
EXPORT_SYMBOL_GPL(dcr_map);
-void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c)
+void dcr_unmap(dcr_host_t host, unsigned int dcr_c)
{
dcr_host_t h = host;
if (h.token == NULL)
return;
- h.token += dcr_n * h.stride;
+ h.token += host.base * h.stride;
iounmap(h.token);
h.token = NULL;
}
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
index 748a869..39f4cb6 100644
--- a/drivers/net/ibm_newemac/mal.c
+++ b/drivers/net/ibm_newemac/mal.c
@@ -627,7 +627,7 @@ static int __devinit mal_probe(struct of_device *ofdev,
fail2:
dma_free_coherent(&ofdev->dev, bd_size, mal->bd_virt, mal->bd_dma);
fail_unmap:
- dcr_unmap(mal->dcr_host, dcr_base, 0x100);
+ dcr_unmap(mal->dcr_host, 0x100);
fail:
kfree(mal);
diff --git a/include/asm-powerpc/dcr-mmio.h b/include/asm-powerpc/dcr-mmio.h
index a7d9eaf..08532ff 100644
--- a/include/asm-powerpc/dcr-mmio.h
+++ b/include/asm-powerpc/dcr-mmio.h
@@ -33,7 +33,7 @@ typedef struct {
extern dcr_host_t dcr_map(struct device_node *dev, unsigned int dcr_n,
unsigned int dcr_c);
-extern void dcr_unmap(dcr_host_t host, unsigned int dcr_n, unsigned int dcr_c);
+extern void dcr_unmap(dcr_host_t host, unsigned int dcr_c);
static inline u32 dcr_read(dcr_host_t host, unsigned int dcr_n)
{
diff --git a/include/asm-powerpc/dcr-native.h b/include/asm-powerpc/dcr-native.h
index 3bc780f..8dbb1ab 100644
--- a/include/asm-powerpc/dcr-native.h
+++ b/include/asm-powerpc/dcr-native.h
@@ -29,7 +29,7 @@ typedef struct {
#define DCR_MAP_OK(host) (1)
#define dcr_map(dev, dcr_n, dcr_c) ((dcr_host_t){ .base = (dcr_n) })
-#define dcr_unmap(host, dcr_n, dcr_c) do {} while (0)
+#define dcr_unmap(host, dcr_c) do {} while (0)
#define dcr_read(host, dcr_n) mfdcr(dcr_n + host.base)
#define dcr_write(host, dcr_n, value) mtdcr(dcr_n + host.base, value)
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 5/5] Remove msic_dcr_read() in axon_msi.c
From: Michael Ellerman @ 2007-10-15 9:34 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, jgarzik
In-Reply-To: <33ee227bae85a8d7ccde69a717cff47000888354.1192440801.git.michael@ellerman.id.au>
msic_dcr_read() doesn't really do anything useful, just replace it with
direct calls to dcr_read().
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/axon_msi.c | 9 ++-------
1 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index aca1500..095988f 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -80,18 +80,13 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
dcr_write(msic->dcr_host, dcr_n, val);
}
-static u32 msic_dcr_read(struct axon_msic *msic, unsigned int dcr_n)
-{
- return dcr_read(msic->dcr_host, dcr_n);
-}
-
static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
{
struct axon_msic *msic = get_irq_data(irq);
u32 write_offset, msi;
int idx;
- write_offset = msic_dcr_read(msic, MSIC_WRITE_OFFSET_REG);
+ write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG);
pr_debug("axon_msi: original write_offset 0x%x\n", write_offset);
/* write_offset doesn't wrap properly, so we have to mask it */
@@ -306,7 +301,7 @@ static int axon_msi_notify_reboot(struct notifier_block *nb,
list_for_each_entry(msic, &axon_msic_list, list) {
pr_debug("axon_msi: disabling %s\n",
msic->irq_host->of_node->full_name);
- tmp = msic_dcr_read(msic, MSIC_CTRL_REG);
+ tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
}
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH] PS3 system bus add_uevent_var() fallout
From: Geert Uytterhoeven @ 2007-10-15 9:51 UTC (permalink / raw)
To: Linus Torvalds, Andrew Morton, Paul Mackerras
Cc: Linux/PPC Development, Linux Kernel Development
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1238 bytes --]
PS3 system bus add_uevent_var() fallout: kill unused variables
Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
arch/powerpc/platforms/ps3/system-bus.c | 1 -
1 files changed, 1 deletion(-)
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -440,7 +440,6 @@ static void ps3_system_bus_shutdown(stru
static int ps3_system_bus_uevent(struct device *_dev, struct kobj_uevent_env *env)
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
- int i = 0, length = 0;
if (add_uevent_var(env, "MODALIAS=ps3:%d", dev->match_id))
return -ENOMEM;
With kind regards,
Geert Uytterhoeven
Software Architect
Sony Network and Software Technology Center Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
Phone: +32 (0)2 700 8453
Fax: +32 (0)2 700 8622
E-mail: Geert.Uytterhoeven@sonycom.com
Internet: http://www.sony-europe.com/
Sony Network and Software Technology Center Europe
A division of Sony Service Centre (Europe) N.V.
Registered office: Technologielaan 7 · B-1840 Londerzeel · Belgium
VAT BE 0413.825.160 · RPR Brussels
Fortis Bank Zaventem · Swift GEBABEBB08A · IBAN BE39001382358619
^ permalink raw reply
* Re: [PATCH v3 4/4] FEC mpc52xx: phy part of the driver\
From: Domen Puncer @ 2007-10-15 10:56 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, jgarzik, netdev
In-Reply-To: <fa686aa40710141505w1787e7e1g6116185001561a4d@mail.gmail.com>
On 14/10/07 16:05 -0600, Grant Likely wrote:
> On 10/14/07, Domen Puncer <domen.puncer@telargo.com> wrote:
> > PHY part of the driver for mpc5200(b) ethernet.
>
> Assuming I understand correctly, this comment is not correct and this
> patch just adds an MDIO bus driver. PHY drivers are in phylib and
> data transfer is setup via the core driver, correct?
Right.
>
> It is conceivable that the PHY is connected to an alternate MDIO bus,
> or the MDIO bus is used for a PHY connected to an external Ethernet
> controller.
>
> Speaking of which, is it possible to use this MDIO bus without the
> core FEC being initialized?
IIRC fec doesn't need any initialization for MDIO bus registers to work.
>
> > +static struct of_device_id fec_mdio_match[] = {
> > + {
> > + .type = "mdio",
> > + .compatible = "mpc5200b-fec-phy",
>
> This is not a phy; it's an MDIO bus. Also, shouldn't this be
> "mpc5200-..." instead of "mpc5200b-..."?
Didn't know if it's ok for mpc5200, guess it is?
>
> > + },
> > + {},
> > +};
> > +
> > +struct of_platform_driver mpc52xx_fec_mdio_driver = {
> > + .name = "mpc5200b-fec-phy",
> > + .probe = fec_mdio_probe,
> > + .remove = fec_mdio_remove,
> > + .match_table = fec_mdio_match,
>
> Inconsistent naming. Please use the same prefix on all global/static
> symbols (ie. use "mpc52xx_mdio_" instead of the mix of
> "mpc52xx_fec_mdio_", "fec_mdio_", etc.) I also thing that "fec_mdio_"
> is too generic because there are a number of different incompatible
> FEC devices.
OK.
>
> > +};
> > +
> > +/* let fec driver call it, since this has to be registered before it */
> > +EXPORT_SYMBOL_GPL(mpc52xx_fec_mdio_driver);
>
> Why not have a module_init()/module_exit() in this file? I don't
> think the FEC driver calls this driver's functions directly anymore,
> and it's still dependent on the of_platform bus probe order anyway.
It was one way of making sure mdio driver is registered before fec.
(and of_platform bus probe order won't work for modules)
Nicer alternatives?
>
> As an added bonus, it makes your Makefile much simpler.
>
> > +
> > +
> > +MODULE_LICENSE("Dual BSD/GPL");
> > Index: linux.git/drivers/net/fec_mpc52xx/Makefile
> > ===================================================================
> > --- linux.git.orig/drivers/net/fec_mpc52xx/Makefile
> > +++ linux.git/drivers/net/fec_mpc52xx/Makefile
> > @@ -1,2 +1,7 @@
> > obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
> > fec_mpc52xx-objs := fec.o
> > +
> > +ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
> > + obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
> > + fec_mpc52xx_phy-objs := fec_phy.o
> > +endif
> > Index: linux.git/drivers/net/fec_mpc52xx/Kconfig
> > ===================================================================
> > --- linux.git.orig/drivers/net/fec_mpc52xx/Kconfig
> > +++ linux.git/drivers/net/fec_mpc52xx/Kconfig
> > @@ -11,5 +11,18 @@ config FEC_MPC52xx
> > ---help---
> > This option enables support for the MPC5200's on-chip
> > Fast Ethernet Controller
> > + If compiled as module, it will be called 'fec_mpc52xx.ko'.
>
> Drop this line and make the help text the same format as the other eth
> drivers in drivers/net.
How exactly is it different now?
And most of them have the "Module will be called xxx" line.
>
> > +
> > +config FEC_MPC52xx_MDIO
> > + bool "FEC MII PHY driver"
> > + depends on FEC_MPC52xx
> > + default y
> > + ---help---
> > + The MPC5200's FEC can connect to the Ethernet either with
> > + an external MII PHY chip or 10 Mbps 7-wire interface
> > + (Motorola? industry standard).
> > + If your board uses an external PHY, enable this.
>
> Not strictly true. This enables talking to a PHY using the internal
> MDIO controller. PHY register access could just as easily be accessed
> via an alternate interface.
Not just that is also selects which mode will it use.
If you don't enable this, fec will be set up as 7-wire
( 696 rcntrl |= FEC_RCNTRL_MII_MODE;)
>
> > + If not sure, enable.
> > + If compiled as module, it will be called 'fec_mpc52xx_phy.ko'.
>
> Drop the module name comment.
>
> Cheers,
> g.
>
> --
> Grant Likely, B.Sc., P.Eng.
> Secret Lab Technologies Ltd.
> grant.likely@secretlab.ca
> (403) 399-0195
--
Domen Puncer | Research & Development
.............................................................................................
Telargo d.o.o. | Zagrebška cesta 20 | 2000 Maribor | Slovenia
.............................................................................................
www.telargo.com
^ permalink raw reply
* [BUG] Linux 2.6.23.1 - Open Firmware exception handler invoked
From: Kamalesh Babulal @ 2007-10-15 11:08 UTC (permalink / raw)
To: linux-kernel; +Cc: linuxppc-dev, Greg Kroah-Hartman, stable
In-Reply-To: <20071012170140.GA18498@kroah.com>
Hi,
The Open Firmware exception handler is begin invoked, on power5 lpar.
boot: 2.6.23.1
Please wait, loading kernel...
Allocated 03500000 bytes for kernel @ 01c00000
Elf64 kernel loaded...
Loading ramdisk...
ramdisk loaded 0020d000 @ 06b00000
DEFAULT CATCH!, exception-handler=fff00300
at %SRR0: c00000000202705c %SRR1: 8000000000003002
Open Firmware exception handler entered from non-OF code
Client's Fix Pt Regs:
00 0223100003080000 00000000018bfac0 0000000004bbeaf8 00000000018bfb48
04 00000000018bfc90 0000000000c39a48 0000000000000000 5c3a03080000a0fa
08 0000000000000001 0000000000000000 05910000194c0223 000000005cae0000
0c 0000000003f1eaf8 0000000000000000 0000000000000000 0000000000000000
10 0000000000000000 0000000000c39a48 0000000000000000 00000000018bfc90
14 0000000000c00000 000000000020d000 0000000000000000 0000000008b00000
18 0000000000280004 00000000018bff04 0000000000000001 0000000000000000
1c 0000000008b00000 0000000000c39a48 c000000004d1e530 0000000008b00000
Special Regs:
%IV: 00000300 %CR: 44000028 %XER: 00000000 %DSISR: 08000000
%SRR0: c00000000202705c %SRR1: 8000000000003002
%LR: c000000002027428 %CTR: c0000000020273f0
%DAR: 05910000194c02eb
Virtual PID = 0
PFW: Unable to send error log!
ofdbg
0 >
# cat /proc/cpuinfo
processor : 0
cpu : POWER5+ (gs)
clock : 1498.500000MHz
revision : 2.0 (pvr 003b 0200)
processor : 1
cpu : POWER5+ (gs)
clock : 1498.500000MHz
revision : 2.0 (pvr 003b 0200)
timebase : 187199000
platform : pSeries
machine : CHRP IBM,9133-55A
--
Thanks & Regards,
Kamalesh Babulal,
Linux Technology Center,
IBM, ISTL.
^ permalink raw reply
* [PATCH take2] [POWERPC] i2c: adds support for i2c bus on 8xx
From: Jochen Friedrich @ 2007-10-15 11:10 UTC (permalink / raw)
To: linuxppc-embedded@ozlabs.org, linux-kernel, i2c; +Cc: Carsten Juttner
[-- Attachment #1: Type: text/plain, Size: 1350 bytes --]
Using the port of 2.4 code from Vitaly Bordug <vitb@kernel.crashing.org>
and the actual algorithm used by the i2c driver of the DBox code on
cvs.tuxboc.org from Tmbinc, Gillem (htoa@gmx.net). Renamed
i2c-algo-8xx.c to i2c-algo-cpm.c and i2c-rpx.c to i2c-8xx.c. Added
original i2c-rpx.c as i2c-8xx-ppc.c for pre-OF (arch ppc) devices.
Signed-off-by: Jochen Friedrich <jochen@scram.de>
---
This can be pulled from git://git.bocc.de/dbox2.git i2c
arch/powerpc/boot/dts/mpc885ads.dts | 9 +
arch/powerpc/platforms/8xx/mpc885ads_setup.c | 6 +
arch/powerpc/sysdev/fsl_soc.c | 61 +++-
drivers/i2c/algos/Kconfig | 12 +
drivers/i2c/algos/Makefile | 1 +
drivers/i2c/algos/i2c-algo-cpm.c | 563 ++++++++++++++++++++++++++
drivers/i2c/busses/Kconfig | 22 +
drivers/i2c/busses/Makefile | 2 +
drivers/i2c/busses/i2c-8xx-ppc.c | 105 +++++
drivers/i2c/busses/i2c-8xx.c | 170 ++++++++
include/linux/i2c-algo-cpm.h | 34 ++
11 files changed, 984 insertions(+), 1 deletions(-)
create mode 100644 drivers/i2c/algos/i2c-algo-cpm.c
create mode 100644 drivers/i2c/busses/i2c-8xx-ppc.c
create mode 100644 drivers/i2c/busses/i2c-8xx.c
create mode 100644 include/linux/i2c-algo-cpm.h
[-- Attachment #2: dbf0ac27a4f43181eb26453562bb701c7dbc2aa0.diff --]
[-- Type: text/x-patch, Size: 28844 bytes --]
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
index 8848e63..a526c02 100644
--- a/arch/powerpc/boot/dts/mpc885ads.dts
+++ b/arch/powerpc/boot/dts/mpc885ads.dts
@@ -213,6 +213,15 @@
fsl,cpm-command = <0080>;
linux,network-index = <2>;
};
+
+ i2c@860 {
+ device_type = "i2c";
+ compatible = "fsl-i2c-cpm";
+ reg = <860 20 3c80 30>;
+ interrupts = <10>;
+ interrupt-parent = <&CPM_PIC>;
+ fsl,cpm-command = <0010>;
+ };
};
};
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
index 2cf1b6a..350018b 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
@@ -175,6 +175,12 @@ static void __init init_ioports(void)
/* Set FEC1 and FEC2 to MII mode */
clrbits32(&mpc8xx_immr->im_cpm.cp_cptr, 0x00000180);
+
+#ifdef CONFIG_I2C_8XX
+ setbits32(&mpc8xx_immr->im_cpm.cp_pbpar, 0x00000030);
+ setbits32(&mpc8xx_immr->im_cpm.cp_pbdir, 0x00000030);
+ setbits16(&mpc8xx_immr->im_cpm.cp_pbodr, 0x0030);
+#endif
}
static void __init mpc885ads_setup_arch(void)
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 3ace747..e2c8bf8 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -28,6 +28,7 @@
#include <linux/fsl_devices.h>
#include <linux/fs_enet_pd.h>
#include <linux/fs_uart_pd.h>
+#include <linux/of_platform.h>
#include <asm/system.h>
#include <asm/atomic.h>
@@ -397,7 +398,7 @@ static int __init fsl_i2c_of_init(void)
for (np = NULL, i = 0;
(np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL;
i++) {
- struct resource r[2];
+ struct resource r[3];
struct fsl_i2c_platform_data i2c_data;
const unsigned char *flags = NULL;
@@ -1210,6 +1211,64 @@ err:
arch_initcall(cpm_smc_uart_of_init);
+static const char *i2c_regs = "regs";
+static const char *i2c_pram = "pram";
+static const char *i2c_irq = "interrupt";
+
+static int __init fsl_i2c_cpm_of_init(void)
+{
+ struct device_node *np;
+ unsigned int i;
+ struct platform_device *i2c_dev;
+ int ret;
+
+ for (np = NULL, i = 0;
+ (np = of_find_compatible_node(np, "i2c", "fsl-i2c-cpm")) != NULL;
+ i++) {
+ struct resource r[3];
+ struct fsl_i2c_platform_data i2c_data;
+
+ memset(&r, 0, sizeof(r));
+ memset(&i2c_data, 0, sizeof(i2c_data));
+
+ ret = of_address_to_resource(np, 0, &r[0]);
+ if (ret)
+ goto err;
+ r[0].name = i2c_regs;
+
+ ret = of_address_to_resource(np, 1, &r[1]);
+ if (ret)
+ goto err;
+ r[1].name = i2c_pram;
+
+ r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
+ r[2].flags = IORESOURCE_IRQ;
+ r[2].name = i2c_irq;
+
+ i2c_dev = platform_device_register_simple("fsl-i2c-cpm", i, &r[0], 3);
+ if (IS_ERR(i2c_dev)) {
+ ret = PTR_ERR(i2c_dev);
+ goto err;
+ }
+
+ ret =
+ platform_device_add_data(i2c_dev, &i2c_data,
+ sizeof(struct
+ fsl_i2c_platform_data));
+ if (ret)
+ goto unreg;
+ }
+
+ return 0;
+
+unreg:
+ platform_device_unregister(i2c_dev);
+err:
+ return ret;
+}
+
+arch_initcall(fsl_i2c_cpm_of_init);
+
#endif /* CONFIG_8xx */
#endif /* CONFIG_PPC_CPM_NEW_BINDING */
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
index 014dfa5..7a8200e 100644
--- a/drivers/i2c/algos/Kconfig
+++ b/drivers/i2c/algos/Kconfig
@@ -14,6 +14,18 @@ config I2C_ALGOBIT
This support is also available as a module. If so, the module
will be called i2c-algo-bit.
+config I2C_ALGOCPM
+ tristate "I2C MPC8xx CPM and MPC8260 CPM2 interfaces"
+ depends on ( 8xx || 8260 ) && I2C
+ help
+ CPM I2C Algorithm, supports the CPM I2C interface for mpc8xx
+ and mpc8260 CPUs. Say Y if you own a CPU of this class and wish
+ to use the I2C interface and say Y to the specific driver for the
+ particular CPU.
+
+ This support is also available as a module. If so, the module
+ will be called i2c-algo-cpm.
+
config I2C_ALGOPCF
tristate "I2C PCF 8584 interfaces"
help
diff --git a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile
index cac1051..b5fe28c 100644
--- a/drivers/i2c/algos/Makefile
+++ b/drivers/i2c/algos/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o
obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o
+obj-$(CONFIG_I2C_ALGOCPM) += i2c-algo-cpm.o
ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/algos/i2c-algo-cpm.c b/drivers/i2c/algos/i2c-algo-cpm.c
new file mode 100644
index 0000000..08552cb
--- /dev/null
+++ b/drivers/i2c/algos/i2c-algo-cpm.c
@@ -0,0 +1,563 @@
+/*
+ * i2c-algo-cpm.c i2x driver algorithms for MPC8XX CPM and MPC8260 CPM2
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
+ *
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * moved into proper i2c interface; separated out platform specific
+ * parts into i2c-8xx.c
+ * Brad Parker (brad@heeltoe.com)
+ *
+ * Parts from dbox2_i2c.c (cvs.tuxbox.org)
+ * (C) 2000-2001 Tmbinc, Gillem (htoa@gmx.net)
+ *
+ * (C) 2007 Montavista Software, Inc.
+ * Vitaly Bordug <vitb@kernel.crashing.org>
+ *
+ * (C) 2007 Jochen Friedrich <jochen@scram.de>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-cpm.h>
+#include <linux/io.h>
+#include <linux/time.h>
+#include <linux/dma-mapping.h>
+#include <asm/mpc8xx.h>
+
+/* Try to define this if you have an older CPU (earlier than rev D4) */
+#undef I2C_CHIP_ERRATA
+
+static int cpm_debug = 1;
+#ifdef DEBUG
+module_param(cpm_debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(cpm_debug, "debug level - 0 off; 1 normal");
+#endif
+
+static irqreturn_t cpm_iic_interrupt(int irq, void *dev_id)
+{
+ struct i2c_adapter *adap;
+ struct i2c_algo_cpm_data *cpm;
+ i2c8xx_t *i2c;
+ int i;
+
+ adap = (struct i2c_adapter *) dev_id;
+ cpm = adap->algo_data;
+ i2c = cpm->i2c;
+
+ /* Clear interrupt.
+ */
+ i = in_8(&i2c->i2c_i2cer);
+ out_8(&i2c->i2c_i2cer, i);
+
+ if (cpm_debug)
+ dev_dbg(&adap->dev, "Interrupt: %x\n", i);
+
+ /* Get 'me going again.
+ */
+ wake_up_interruptible(&cpm->iic_wait);
+
+ return IRQ_HANDLED;
+}
+
+static int cpm_iic_init(struct i2c_adapter *adap)
+{
+ struct i2c_algo_cpm_data *cpm = adap->algo_data;
+ iic_t *iip = cpm->iip;
+ i2c8xx_t *i2c = cpm->i2c;
+ unsigned char brg;
+ int ret, i;
+
+ if (cpm_debug)
+ dev_dbg(&adap->dev, "cpm_iic_init()\n");
+
+ ret = 0;
+ init_waitqueue_head(&cpm->iic_wait);
+ mutex_init(&cpm->iic_mutex);
+ /* Initialize the parameter ram.
+ * We need to make sure many things are initialized to zero,
+ * especially in the case of a microcode patch.
+ */
+ out_be32(&iip->iic_rstate, 0);
+ out_be32(&iip->iic_rdp, 0);
+ out_be16(&iip->iic_rbptr, 0);
+ out_be16(&iip->iic_rbc, 0);
+ out_be32(&iip->iic_rxtmp, 0);
+ out_be32(&iip->iic_tstate, 0);
+ out_be32(&iip->iic_tdp, 0);
+ out_be16(&iip->iic_tbptr, 0);
+ out_be16(&iip->iic_tbc, 0);
+ out_be32(&iip->iic_txtmp, 0);
+
+ /* Set up the IIC parameters in the parameter ram.
+ */
+ out_be16(&iip->iic_tbase, cpm->dp_addr);
+ out_be16(&iip->iic_rbase, cpm->dp_addr + sizeof(cbd_t) * CPM_MAXBD);
+
+ if (cpm_debug) {
+ dev_dbg(&adap->dev, "iip %p, dp_addr 0x%x\n", cpm->iip,
+ cpm->dp_addr);
+ dev_dbg(&adap->dev, "iic_tbase %d, iic_rbase %d\n",
+ in_be16(&iip->iic_tbase), in_be16(&iip->iic_rbase));
+ }
+
+ out_8(&iip->iic_tfcr, SMC_EB);
+ out_8(&iip->iic_rfcr, SMC_EB);
+
+ /* Set maximum receive size.
+ */
+ out_be16(&iip->iic_mrblr, CPM_MAX_READ);
+
+ /* Initialize Tx/Rx parameters.
+ */
+ if (cpm->reloc == 0) {
+ cpm8xx_t *cp = cpm->cp;
+ int res;
+
+ u16 v = mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ out_be16(&cp->cp_cpcr, v);
+ res = wait_event_timeout(cpm->iic_wait,
+ !(in_be16(&cp->cp_cpcr) & CPM_CR_FLG),
+ HZ * 10);
+ if (!res)
+ return -EIO;
+
+ } else {
+ iip->iic_rbptr = iip->iic_rbase;
+ iip->iic_tbptr = iip->iic_tbase;
+ iip->iic_rstate = 0;
+ iip->iic_tstate = 0;
+ }
+
+ /* Select an arbitrary address. Just make sure it is unique.
+ */
+ out_8(&i2c->i2c_i2add, 0xfe);
+
+ /* Make clock run at 60 kHz.
+ */
+ /* brg = ppc_proc_freq / (32 * 2 * 60000) - 3; */
+ brg = 7;
+ out_8(&i2c->i2c_i2brg, brg);
+
+ out_8(&i2c->i2c_i2mod, 0x00);
+ out_8(&i2c->i2c_i2com, 0x01); /* Master mode */
+
+ /* Disable interrupts.
+ */
+ out_8(&i2c->i2c_i2cmr, 0);
+ out_8(&i2c->i2c_i2cer, 0xff);
+
+ /* Allocate TX and RX buffers */
+ for (i = 0; i < CPM_MAXBD; i++) {
+ cpm->rxbuf[i] = (unsigned char *)dma_alloc_coherent(
+ NULL, CPM_MAX_READ + 1, &cpm->rxdma[i], GFP_KERNEL);
+ if (!cpm->rxbuf[i]) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ cpm->txbuf[i] = (unsigned char *)dma_alloc_coherent(
+ NULL, CPM_MAX_READ + 1, &cpm->txdma[i], GFP_KERNEL);
+ if (!cpm->txbuf[i]) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+
+ /* Install interrupt handler.
+ */
+ if (request_irq(cpm->irq, cpm_iic_interrupt, 0, "8xx_i2c", adap)) {
+ ret = -EIO;
+ goto out;
+ }
+
+ return 0;
+out:
+ for (i = 0; i < CPM_MAXBD; i++) {
+ if (cpm->rxbuf[i]) dma_free_coherent(NULL, CPM_MAX_READ + 1,
+ cpm->rxbuf[i], cpm->rxdma[i]);
+ if (cpm->txbuf[i]) dma_free_coherent(NULL, CPM_MAX_READ + 1,
+ cpm->txbuf[i], cpm->txdma[i]);
+ }
+ return ret;
+}
+
+static int cpm_iic_shutdown(struct i2c_adapter *adap)
+{
+ struct i2c_algo_cpm_data *cpm = adap->algo_data;
+ int i;
+
+ i2c8xx_t *i2c = cpm->i2c;
+
+ /* Shut down IIC.
+ */
+ out_8(&i2c->i2c_i2mod, in_8(&i2c->i2c_i2mod) | ~1);
+ out_8(&i2c->i2c_i2cmr, 0);
+ out_8(&i2c->i2c_i2cer, 0xff);
+
+ for (i = 0; i < CPM_MAXBD; i++) {
+ if (cpm->rxbuf[i]) dma_free_coherent(NULL, CPM_MAX_READ + 1,
+ cpm->rxbuf[i], cpm->rxdma[i]);
+ if (cpm->txbuf[i]) dma_free_coherent(NULL, CPM_MAX_READ + 1,
+ cpm->txbuf[i], cpm->txdma[i]);
+ }
+
+ free_irq(cpm->irq, adap);
+
+ return (0);
+}
+
+static void cpm_reset_iic_params(struct i2c_algo_cpm_data *cpm)
+{
+ iic_t *iip = cpm->iip;
+
+ out_be16(&iip->iic_tbase, cpm->dp_addr);
+ out_be16(&iip->iic_rbase, cpm->dp_addr + sizeof(cbd_t) * CPM_MAXBD);
+
+ out_8(&iip->iic_tfcr, SMC_EB);
+ out_8(&iip->iic_rfcr, SMC_EB);
+
+ out_be16(&iip->iic_mrblr, CPM_MAX_READ);
+
+ out_be32(&iip->iic_rstate, 0);
+ out_be32(&iip->iic_rdp, 0);
+ out_be16(&iip->iic_rbptr, in_be16(&iip->iic_rbase));
+ out_be16(&iip->iic_rbc, 0);
+ out_be32(&iip->iic_rxtmp, 0);
+ out_be32(&iip->iic_tstate, 0);
+ out_be32(&iip->iic_tdp, 0);
+ out_be16(&iip->iic_tbptr, in_be16(&iip->iic_tbase));
+ out_be16(&iip->iic_tbc, 0);
+ out_be32(&iip->iic_txtmp, 0);
+}
+
+#define BD_SC_NAK ((ushort)0x0004) /* NAK - did not respond */
+#define BD_SC_OV ((ushort)0x0002) /* OV - receive overrun */
+#define CPM_CR_CLOSE_RXBD ((ushort)0x0007)
+
+static void force_close(struct i2c_adapter *adap)
+{
+ struct i2c_algo_cpm_data *cpm = adap->algo_data;
+ i2c8xx_t *i2c = cpm->i2c;
+ if (cpm->reloc == 0) { /* micro code disabled */
+ cpm8xx_t *cp = cpm->cp;
+ u16 v =
+ mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_CLOSE_RXBD) | CPM_CR_FLG;
+
+ if (cpm_debug)
+ printk(KERN_INFO "force_close()\n");
+
+ out_be16(&cp->cp_cpcr, v);
+ wait_event_timeout(cpm->iic_wait,
+ !(in_be16(&cp->cp_cpcr) & CPM_CR_FLG),
+ HZ * 5);
+ }
+ out_8(&i2c->i2c_i2cmr, 0x00); /* Disable all interrupts */
+ out_8(&i2c->i2c_i2cer, 0xff);
+}
+
+static void cpm_parse_message(struct i2c_adapter *adap, struct i2c_msg *pmsg,
+ int num, int tx, int rx)
+{
+ cbd_t *tbdf, *rbdf;
+ u_char addr;
+ u_char *tb;
+ u_char *rb;
+ struct i2c_algo_cpm_data *cpm = adap->algo_data;
+ iic_t *iip = cpm->iip;
+ int i, dscan;
+
+ tbdf = (cbd_t *) cpm_dpram_addr(in_be16(&iip->iic_tbase));
+ rbdf = (cbd_t *) cpm_dpram_addr(in_be16(&iip->iic_rbase));
+
+ /* This chip can't do zero lenth writes. However, the i2c core uses
+ them to scan for devices. The best we can do is to convert them
+ into 1 byte reads */
+
+ dscan = ((pmsg->len == 0) && (num == 1));
+
+ addr = pmsg->addr << 1;
+ if ((pmsg->flags & I2C_M_RD) || dscan)
+ addr |= 1;
+
+ tb = cpm->txbuf[tx];
+ rb = cpm->rxbuf[rx];
+
+ /* Align read buffer */
+ rb = (u_char *) (((uint) rb + 1) & ~1);
+
+ if ((pmsg->flags & I2C_M_RD) || dscan) {
+ /* To read, we need an empty buffer of the proper length.
+ * All that is used is the first byte for address, the remainder
+ * is just used for timing (and doesn't really have to exist).
+ */
+ tb[0] = addr; /* Device address byte w/rw flag */
+
+ if (cpm_debug)
+ dev_dbg(&adap->dev, "cpm_iic_read(abyte=0x%x)\n", addr);
+ tbdf[tx].cbd_bufaddr = cpm->txdma[tx];
+ if (dscan)
+ tbdf[tx].cbd_datlen = 2;
+ else
+ tbdf[tx].cbd_datlen = pmsg->len + 1;
+ tbdf[tx].cbd_sc = 0;
+ if (!(pmsg->flags & I2C_M_NOSTART))
+ tbdf[tx].cbd_sc |= BD_IIC_START;
+ if (tx + 1 == num)
+ tbdf[tx].cbd_sc |= BD_SC_LAST | BD_SC_WRAP;
+
+ rbdf[rx].cbd_datlen = 0;
+ rbdf[rx].cbd_bufaddr = ((cpm->rxdma[rx] + 1) & ~1);
+ rbdf[rx].cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
+ if (rx + 1 == CPM_MAXBD)
+ tbdf[rx].cbd_sc |= BD_SC_WRAP;
+
+ tbdf[tx].cbd_sc |= BD_SC_READY;
+ } else {
+ tb[0] = addr; /* Device address byte w/rw flag */
+ for (i = 0; i < pmsg->len; i++)
+ tb[i+1] = pmsg->buf[i];
+
+ if (cpm_debug)
+ dev_dbg(&adap->dev, "cpm_iic_write(abyte=0x%x)\n",
+ addr);
+ tbdf[tx].cbd_bufaddr = cpm->txdma[tx];
+ tbdf[tx].cbd_datlen = pmsg->len + 1;
+ tbdf[tx].cbd_sc = 0;
+ if (!(pmsg->flags & I2C_M_NOSTART))
+ tbdf[tx].cbd_sc |= BD_IIC_START;
+ if (tx + 1 == num)
+ tbdf[tx].cbd_sc |= BD_SC_LAST | BD_SC_WRAP;
+ tbdf[tx].cbd_sc |= BD_SC_READY | BD_SC_INTRPT;
+ dev_dbg(&adap->dev, "tx sc %d %04x\n",
+ tx, tbdf[tx].cbd_sc);
+ }
+}
+
+static int cpm_check_message(struct i2c_adapter *adap, struct i2c_msg *pmsg,
+ int tx, int rx)
+{
+ cbd_t *tbdf, *rbdf;
+ u_char *tb;
+ u_char *rb;
+ struct i2c_algo_cpm_data *cpm = adap->algo_data;
+ iic_t *iip = cpm->iip;
+ int i;
+
+ tbdf = (cbd_t *) cpm_dpram_addr(in_be16(&iip->iic_tbase));
+ rbdf = (cbd_t *) cpm_dpram_addr(in_be16(&iip->iic_rbase));
+
+ tb = cpm->txbuf[tx];
+ rb = cpm->rxbuf[rx];
+
+ /* Align read buffer */
+ rb = (u_char *) (((uint) rb + 1) & ~1);
+
+ if (pmsg->flags & I2C_M_RD) {
+ if (cpm_debug)
+ dev_dbg(&adap->dev, "rx sc %04x, rx sc %04x\n",
+ tbdf[tx].cbd_sc, rbdf[rx].cbd_sc);
+ if (tbdf[tx].cbd_sc & BD_SC_NAK) {
+ if (cpm_debug)
+ dev_dbg(&adap->dev, "IIC read; no ack\n");
+ if (pmsg->flags & I2C_M_IGNORE_NAK)
+ return 0;
+ else
+ return -EREMOTEIO;
+ }
+ if (rbdf[rx].cbd_sc & BD_SC_EMPTY) {
+ if (cpm_debug) {
+ dev_dbg(&adap->dev,
+ "IIC read; complete but rbuf empty\n");
+ }
+ return -EREMOTEIO;
+ }
+ if (rbdf[rx].cbd_sc & BD_SC_OV) {
+ if (cpm_debug)
+ dev_dbg(&adap->dev, "IIC read; Overrun\n");
+ return -EREMOTEIO;
+ }
+ for (i = 0; i < pmsg->len; i++)
+ pmsg->buf[i] = rb[i];
+ } else {
+ if (cpm_debug)
+ dev_dbg(&adap->dev, "tx sc %d %04x\n",
+ tx, tbdf[tx].cbd_sc);
+ if (tbdf[tx].cbd_sc & BD_SC_NAK) {
+ if (cpm_debug)
+ dev_dbg(&adap->dev, "IIC write; no ack\n");
+ if (pmsg->flags & I2C_M_IGNORE_NAK)
+ return 0;
+ else
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+static int cpm_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+ struct i2c_algo_cpm_data *cpm = adap->algo_data;
+ i2c8xx_t *i2c = cpm->i2c;
+ iic_t *iip = cpm->iip;
+ struct i2c_msg *pmsg, *rmsg;
+ int ret, i;
+ int tptr;
+ int rptr;
+ cbd_t *tbdf, *rbdf;
+
+ if (num > CPM_MAXBD)
+ return -EREMOTEIO;
+
+ /* Check if we have any oversized READ requests */
+ for (i = 0; i < num; i++) {
+ pmsg = &msgs[i];
+ if (pmsg->len >= CPM_MAX_READ)
+ return -EREMOTEIO;
+ }
+
+ mutex_lock(&cpm->iic_mutex);
+
+ /* check for and use a microcode relocation patch */
+ if (cpm->reloc)
+ cpm_reset_iic_params(cpm);
+
+ /* Reset to use first buffer */
+ out_be16(&iip->iic_rbptr, in_be16(&iip->iic_rbase));
+ out_be16(&iip->iic_tbptr, in_be16(&iip->iic_tbase));
+
+ tbdf = (cbd_t *) cpm_dpram_addr(in_be16(&iip->iic_tbase));
+ rbdf = (cbd_t *) cpm_dpram_addr(in_be16(&iip->iic_rbase));
+
+ tptr = 0;
+ rptr = 0;
+
+ while (tptr < num) {
+ pmsg = &msgs[tptr];
+ if (cpm_debug)
+ dev_dbg(&adap->dev, "i2c-algo-cpm.o: "
+ "R: %d T: %d\n",
+ rptr, tptr);
+
+ cpm_parse_message(adap, pmsg, num, tptr, rptr);
+ if (pmsg->flags & I2C_M_RD)
+ rptr++;
+ tptr++;
+ }
+ /* Start transfer now */
+ /* Chip bug, set enable here */
+ out_8(&i2c->i2c_i2cmr, 0x13); /* Enable some interupts */
+ out_8(&i2c->i2c_i2cer, 0xff);
+ out_8(&i2c->i2c_i2mod, in_8(&i2c->i2c_i2mod) | 1); /* Enable */
+ /* Begin transmission */
+ out_8(&i2c->i2c_i2com, in_8(&i2c->i2c_i2com) | 0x80);
+
+ tptr = 0;
+ rptr = 0;
+
+ while (tptr < num) {
+ /* Check for outstanding messages */
+ dev_dbg(&adap->dev, "test ready.\n");
+ if (!(tbdf[tptr].cbd_sc & BD_SC_READY)) {
+ dev_dbg(&adap->dev, "ready.\n");
+ rmsg = &msgs[tptr];
+ ret = cpm_check_message(adap, rmsg, tptr, rptr);
+ tptr++;
+ if (rmsg->flags & I2C_M_RD)
+ rptr++;
+ if (ret) {
+ force_close(adap);
+ mutex_unlock(&cpm->iic_mutex);
+ return -EREMOTEIO;
+ }
+ } else {
+ dev_dbg(&adap->dev, "not ready.\n");
+ ret = wait_event_interruptible_timeout(cpm->iic_wait,
+ !(tbdf[tptr].cbd_sc & BD_SC_READY), 1 * HZ);
+ if (ret == 0) {
+ force_close(adap);
+ if (cpm_debug)
+ dev_dbg(&adap->dev,
+ "IIC read: timeout!\n");
+ mutex_unlock(&cpm->iic_mutex);
+ return -EREMOTEIO;
+ }
+ }
+ }
+#ifdef I2C_CHIP_ERRATA
+ /* Chip errata, clear enable. This is not needed on rev D4 CPUs.
+ Disabling I2C too early may cause too short stop condition */
+ udelay(4);
+ out_8(&i2c->i2c_i2mod, in_8(&i2c->i2c_i2mod) | ~1);
+#endif
+ mutex_unlock(&cpm->iic_mutex);
+ return (num);
+}
+
+static u32 cpm_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+/* -----exported algorithm data: ------------------------------------- */
+
+static struct i2c_algorithm cpm_algo = {
+ .master_xfer = cpm_xfer,
+ .functionality = cpm_func,
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+int i2c_cpm_add_bus(struct i2c_adapter *adap)
+{
+ int res;
+
+ if (cpm_debug)
+ dev_dbg(&adap->dev,
+ "i2c-algo-cpm.o: hw routines for %s registered.\n",
+ adap->name);
+
+ /* register new adapter to i2c module... */
+
+ adap->algo = &cpm_algo;
+
+ res = cpm_iic_init(adap);
+
+ if (res)
+ return res;
+
+ return i2c_add_adapter(adap);
+}
+EXPORT_SYMBOL(i2c_cpm_add_bus);
+
+int i2c_cpm_del_bus(struct i2c_adapter *adap)
+{
+ i2c_del_adapter(adap);
+
+ return cpm_iic_shutdown(adap);
+}
+EXPORT_SYMBOL(i2c_cpm_del_bus);
+
+MODULE_AUTHOR("Brad Parker <brad@heeltoe.com>");
+MODULE_DESCRIPTION("I2C-Bus CPM algorithm");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index de95c75..705997b 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -4,6 +4,28 @@
menu "I2C Hardware Bus support"
+config I2C_8XX_PPC
+ tristate "MPC8xx CPM oldstyle (no OF)"
+ depends on 8xx && I2C && !OF
+ select I2C_ALGOCPM
+ help
+ This supports the use of the I2C interface on Freescale MPC8xx
+ processors.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-8xx-ppc.
+
+config I2C_8XX
+ tristate "MPC8xx CPM with Open Firmware"
+ depends on 8xx && I2C && OF
+ select I2C_ALGOCPM
+ help
+ This supports the use of the I2C interface on Freescale MPC8xx
+ processors.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-8xx.
+
config I2C_ALI1535
tristate "ALI 1535"
depends on PCI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 81d43c2..f2feb4b 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -2,6 +2,8 @@
# Makefile for the i2c bus drivers.
#
+obj-$(CONFIG_I2C_8XX_PPC) += i2c-8xx-ppc.o
+obj-$(CONFIG_I2C_8XX) += i2c-8xx.o
obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o
obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o
obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
diff --git a/drivers/i2c/busses/i2c-8xx-ppc.c b/drivers/i2c/busses/i2c-8xx-ppc.c
new file mode 100644
index 0000000..88b1642
--- /dev/null
+++ b/drivers/i2c/busses/i2c-8xx-ppc.c
@@ -0,0 +1,105 @@
+/*
+ * Embedded Planet RPX Lite MPC8xx CPM I2C interface.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
+ *
+ * moved into proper i2c interface;
+ * Brad Parker (brad@heeltoe.com)
+ *
+ * RPX lite specific parts of the i2c interface
+ * Update: There actually isn't anything RPXLite-specific about this module.
+ * This should work for most any 8xx board. The console messages have been
+ * changed to eliminate RPXLite references.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/stddef.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-cpm.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/mpc8xx.h>
+#include <asm/commproc.h>
+
+static int
+m8xx_iic_init(struct i2c_algo_cpm_data *data)
+{
+ cpm8xx_t *cp;
+ immap_t *immap;
+
+ immap = (immap_t *)IMAP_ADDR; /* and to internal registers */
+ /* Get pointer to Communication Processor */
+ cp = (cpm8xx_t *)&immap->im_cpm;
+
+ data->iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+
+ /* Check for and use a microcode relocation patch.
+ */
+ data->reloc = in_be16(&data->iip->iic_rpbase);
+ if (data->reloc)
+ data->iip = (iic_t *)&cp->cp_dpmem[data->reloc];
+
+ data->i2c = (i2c8xx_t *)&(immap->im_i2c);
+ data->cp = cp;
+
+ /* Initialize Port B IIC pins.
+ */
+ setbits32(&cp->cp_pbpar, 0x00000030);
+ setbits32(&cp->cp_pbdir, 0x00000030);
+ setbits16(&cp->cp_pbodr, 0x0030);
+
+ /* Allocate space for transmit and receive buffer
+ * descriptors in the DP ram.
+ */
+ data->dp_addr = cpm_dpalloc(sizeof(cbd_t) * 2 * CPM_MAXBD, 8);
+ if (!data->dp_addr)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static struct i2c_algo_cpm_data m8xx_data = {
+ .irq = CPM_IRQ_OFFSET + CPMVEC_I2C,
+};
+
+static struct i2c_adapter m8xx_ops = {
+ .owner = THIS_MODULE,
+ .name = "i2c-8xx-ppc",
+ .id = I2C_HW_MPC8XX_EPON,
+ .algo_data = &m8xx_data,
+ .dev.parent = &platform_bus,
+ .class = I2C_CLASS_HWMON,
+};
+
+int __init i2c_8xx_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "i2c-8xx-ppc: i2c MPC8xx driver\n");
+
+ /* reset hardware to sane state */
+ ret = m8xx_iic_init(&m8xx_data);
+ if (ret)
+ return ret;
+
+ if (i2c_cpm_add_bus(&m8xx_ops) < 0) {
+ printk(KERN_ERR "i2c-8xx-ppc: Unable to register with I2C\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+void __exit i2c_8xx_exit(void)
+{
+ i2c_cpm_del_bus(&m8xx_ops);
+}
+
+module_init(i2c_8xx_init);
+module_exit(i2c_8xx_exit);
+
+MODULE_AUTHOR("Dan Malek <dmalek@jlc.net>");
+MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-8xx.c b/drivers/i2c/busses/i2c-8xx.c
new file mode 100644
index 0000000..c38b52e
--- /dev/null
+++ b/drivers/i2c/busses/i2c-8xx.c
@@ -0,0 +1,170 @@
+/*
+ * Embedded Planet RPX Lite MPC8xx CPM I2C interface.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
+ *
+ * moved into proper i2c interface;
+ * Brad Parker (brad@heeltoe.com)
+ *
+ * (C) 2007 Montavista Software, Inc.
+ * Vitaly Bordug <vitb@kernel.crashing.org>
+ *
+ * RPX lite specific parts of the i2c interface
+ * Update: There actually isn't anything RPXLite-specific about this module.
+ * This should work for most any 8xx board. The console messages have been
+ * changed to eliminate RPXLite references.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/stddef.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-cpm.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <asm/mpc8xx.h>
+#include <asm/commproc.h>
+#include <asm/fs_pd.h>
+
+
+struct m8xx_i2c {
+ char *base;
+ struct of_device *ofdev;
+ struct i2c_adapter adap;
+ struct i2c_algo_cpm_data *algo_8xx;
+};
+
+static struct i2c_algo_cpm_data m8xx_data;
+
+static const struct i2c_adapter m8xx_ops = {
+ .owner = THIS_MODULE,
+ .name = "i2c-8xx",
+ .id = I2C_HW_MPC8XX_EPON,
+ .algo_data = &m8xx_data,
+ .dev.parent = &platform_bus,
+ .class = I2C_CLASS_HWMON,
+};
+
+static int m8xx_iic_init(struct m8xx_i2c *i2c)
+{
+ cpm8xx_t *cp;
+ struct resource r;
+ struct i2c_algo_cpm_data *data = i2c->algo_8xx;
+ struct of_device *ofdev = i2c->ofdev;
+ struct device_node *np = ofdev->node;
+
+ /* Pointer to Communication Processor
+ */
+ cp = (cpm8xx_t *)immr_map(im_cpm);
+ data->cp = cp;
+
+ data->irq = irq_of_parse_and_map(np, 0);
+ if (data->irq < 0)
+ return -EINVAL;
+
+ if (of_address_to_resource(np, 1, &r))
+ return -EINVAL;
+
+ data->iip = ioremap(r.start, r.end - r.start + 1);
+ if (data->iip == NULL)
+ return -EINVAL;
+
+ /* Check for and use a microcode relocation patch.
+ */
+ data->reloc = data->iip->iic_rpbase;
+ if (data->reloc)
+ data->iip = (iic_t *)&cp->cp_dpmem[data->iip->iic_rpbase];
+
+ if (of_address_to_resource(np, 0, &r))
+ return -EINVAL;
+
+ data->i2c = ioremap(r.start, r.end - r.start + 1);
+ if (data->i2c == NULL)
+ return -EINVAL;
+
+ /* Allocate space for two transmit and two receive buffer
+ * descriptors in the DP ram.
+ */
+ data->dp_addr = cpm_dpalloc(sizeof(cbd_t) * 4, 8);
+ if (!data->dp_addr)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int i2c_8xx_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ int result;
+ struct m8xx_i2c *i2c;
+
+ i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
+ if (!i2c)
+ return -ENOMEM;
+
+ i2c->ofdev = ofdev;
+ i2c->algo_8xx = &m8xx_data;
+
+ m8xx_iic_init(i2c);
+
+ dev_set_drvdata(&ofdev->dev, i2c);
+
+ i2c->adap = m8xx_ops;
+ i2c_set_adapdata(&i2c->adap, i2c);
+ i2c->adap.dev.parent = &ofdev->dev;
+
+ result = i2c_cpm_add_bus(&i2c->adap);
+ if (result < 0) {
+ printk(KERN_ERR "i2c-8xx: Unable to register with I2C\n");
+ kfree(i2c);
+ }
+
+ return result;
+}
+
+static int i2c_8xx_remove(struct of_device *ofdev)
+{
+ struct m8xx_i2c *i2c = dev_get_drvdata(&ofdev->dev);
+
+ i2c_cpm_del_bus(&i2c->adap);
+ dev_set_drvdata(&ofdev->dev, NULL);
+
+ kfree(i2c);
+ return 0;
+}
+
+static struct of_device_id i2c_8xx_match[] = {
+ {
+ .type = "i2c",
+ .compatible = "fsl,i2c-cpm",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, i2c_8xx_match);
+
+static struct of_platform_driver i2c_8xx_driver = {
+ .name = "fsl-i2c-cpm",
+ .match_table = i2c_8xx_match,
+ .probe = i2c_8xx_probe,
+ .remove = i2c_8xx_remove,
+};
+
+static int __init i2c_8xx_init(void)
+{
+ return of_register_platform_driver(&i2c_8xx_driver);
+}
+
+static void __exit i2c_8xx_exit(void)
+{
+ of_unregister_platform_driver(&i2c_8xx_driver);
+}
+
+module_init(i2c_8xx_init);
+module_exit(i2c_8xx_exit);
+
+MODULE_AUTHOR("Dan Malek <dmalek@jlc.net>");
+MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/i2c-algo-cpm.h b/include/linux/i2c-algo-cpm.h
new file mode 100644
index 0000000..2192b7d
--- /dev/null
+++ b/include/linux/i2c-algo-cpm.h
@@ -0,0 +1,34 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-algo-cpm.h i2c driver algorithms for MPX8XX CPM or MPC8250 CPM2 */
+/* ------------------------------------------------------------------------- */
+
+#ifndef I2C_ALGO_CPM_H
+#define I2C_ALGO_CPM_H
+
+#include <linux/i2c.h>
+#include <asm/8xx_immap.h>
+#include <asm/commproc.h>
+
+#define CPM_MAX_READ 513
+#define CPM_MAXBD 4
+
+struct i2c_algo_cpm_data {
+ uint dp_addr;
+ int reloc;
+ int irq;
+ i2c8xx_t *i2c;
+ iic_t *iip;
+ cpm8xx_t *cp;
+ wait_queue_head_t iic_wait;
+ struct mutex iic_mutex; /* Protects I2C CPM */
+ u_char *txbuf[CPM_MAXBD];
+ u_char *rxbuf[CPM_MAXBD];
+ u32 txdma[CPM_MAXBD];
+ u32 rxdma[CPM_MAXBD];
+};
+
+extern int i2c_cpm_add_bus(struct i2c_adapter *);
+extern int i2c_cpm_del_bus(struct i2c_adapter *);
+
+#endif /* I2C_ALGO_CPM_H */
+
^ permalink raw reply related
* RE: [PATCH] [POWERPC] ucc_geth: Fix build break introduced by commit 09f75cd7bf13720738e6a196cc0107ce9a5bd5a0
From: Li Yang-r58472 @ 2007-10-15 11:17 UTC (permalink / raw)
To: Medve Emilian-EMMEDVE1, akpm, jgarzik, netdev, linuxppc-dev
In-Reply-To: <1192231588-17516-1-git-send-email-Emilian.Medve@Freescale.com>
> -----Original Message-----
> From: Medve Emilian-EMMEDVE1=20
> Sent: Saturday, October 13, 2007 7:26 AM
> To: akpm@linux-foundation.org; jgarzik@pobox.com; Li=20
> Yang-r58472; netdev@vger.kernel.org; linuxppc-dev@ozlabs.org
> Cc: Medve Emilian-EMMEDVE1
> Subject: [PATCH] [POWERPC] ucc_geth: Fix build break=20
> introduced by commit 09f75cd7bf13720738e6a196cc0107ce9a5bd5a0
>=20
>=20
> CC drivers/net/ucc_geth.o
> drivers/net/ucc_geth.c: In function 'ucc_geth_startup':
> drivers/net/ucc_geth.c:2614: warning: assignment makes=20
> integer from pointer without a cast
> drivers/net/ucc_geth.c:2651: warning: assignment makes=20
> integer from pointer without a cast
> drivers/net/ucc_geth.c: In function 'ucc_geth_rx':
> drivers/net/ucc_geth.c:3483: error: 'dev' undeclared (first=20
> use in this function)
> drivers/net/ucc_geth.c:3483: error: (Each undeclared=20
> identifier is reported only once
> drivers/net/ucc_geth.c:3483: error: for each function it appears in.)
> make[2]: *** [drivers/net/ucc_geth.o] Error 1
Thanks for the patch. Here are some comments.
The patch fixes the dev undeclared compile error not the warnings. So
they shouldn't be listed here.
>=20
> Signed-off-by: Emil Medve <Emilian.Medve@Freescale.com>
> ---
>=20
> Here is a convenient link for the culprit patch:=20
> http://git.kernel.org/?p=3Dlinux/kernel/git/jgarzik/netdev-2.6.g
> it;a=3Dcommit;h=3D09f75cd7bf13720738e6a196cc0107ce9a5bd5a0
>=20
> netdev-2.6> scripts/checkpatch.pl=20
> 0001-POWERPC-ucc_geth-Fix-build-break-introduced-by-co.patch
> Your patch has no obvious style problems and is ready for submission.
>=20
> drivers/net/ucc_geth.c | 10 +++++-----
> 1 files changed, 5 insertions(+), 5 deletions(-)
>=20
> diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c=20
> index d00e7d4..c43d4d1 100644
> --- a/drivers/net/ucc_geth.c
> +++ b/drivers/net/ucc_geth.c
> @@ -63,7 +63,7 @@
> #define UGETH_MSG_DEFAULT (NETIF_MSG_IFUP << 1 ) - 1
> =20
> void uec_set_ethtool_ops(struct net_device *netdev);
> -=09
> +
> static DEFINE_SPINLOCK(ugeth_lock);
> =20
> static struct {
There are quite a few references to the dev structure. I would prefer
to add a new variable dev here.
- Leo
> @@ -3480,9 +3480,9 @@ static int ucc_geth_rx(struct=20
> ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
> dev_kfree_skb_any(skb);
> =20
> =09
> ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] =3D NULL;
> - dev->stats.rx_dropped++;
> + ugeth->dev->stats.rx_dropped++;
> } else {
> - dev->stats.rx_packets++;
> + ugeth->dev->stats.rx_packets++;
> howmany++;
> =20
> /* Prep the skb for the packet */
> @@ -3491,7 +3491,7 @@ static int ucc_geth_rx(struct=20
> ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
> /* Tell the skb what kind of packet this is */
> skb->protocol =3D eth_type_trans(skb, ugeth->dev);
> =20
> - dev->stats.rx_bytes +=3D length;
> + ugeth->dev->stats.rx_bytes +=3D length;
> /* Send the packet up the stack */
> #ifdef CONFIG_UGETH_NAPI
> netif_receive_skb(skb);
> @@ -3506,7 +3506,7 @@ static int ucc_geth_rx(struct=20
> ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
> if (!skb) {
> if (netif_msg_rx_err(ugeth))
> ugeth_warn("%s: No Rx Data=20
> Buffer", __FUNCTION__);
> - dev->stats.rx_dropped++;
> + ugeth->dev->stats.rx_dropped++;
> break;
> }
> =20
> --
> 1.5.3.GIT
>=20
>=20
^ permalink raw reply
* Re: mpc52xx bestcomm patches.
From: Matt Sealey @ 2007-10-15 11:30 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <DDF4941D-02CA-49FA-999D-8BD08740902C@kernel.crashing.org>
Kumar Gala wrote:
>> The problem is that bestcomm is completely stalled on Sylvain. He's
>> done good work, but he isn't able to put in the effort for the last
>> push to get it fixed and in. But until that happens, nobody else will
>> step in to add patches on top of it to fix it up.
>
> If Sylvain doesn't have the time can't someone else pick up what he's
> done and fixup the issues with it?
I second that motion!
There are a few minor quibbles I have with Sylvain's implementation (it
seems to have ditched some perfectly sound ideas of the original API plus
additions made by bplan for using the device tree to resolve tasks, in
favour of making the API entirely driver-dependant, and Linux-dependant
(it trashes any existing device table) also it has a few "5200-specific"
features like disabling task prefetch (errata not present in 5200B onwards).
It needs some looking at. But, this can be merged in my opinion, we can
just throw it to the list right now, and take the niggles to the list
and have a discussion about it..
In the absense of one guy hammering at the code let's just get 20 people
to review it, right here, with a new submission..
--
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations
^ permalink raw reply
* RE: [PATCH v2] drivers/ata: add support to Freescale 3.0Gbps SATA Controller
From: Kalra Ashish-B00888 @ 2007-10-15 11:30 UTC (permalink / raw)
To: Arnd Bergmann, linuxppc-dev; +Cc: linux-ide, jgarzik, Kalra Ashish-B00888
In-Reply-To: <200710121621.50649.arnd@arndb.de>
Hello Arnd,
Thanks for your comments and feedback.
Actually, for PowerPC platforms iowrite32/ioread32 internally call
writel/readl, which are again mapped to out_le32/in_le32,
therefore we will modify our code to use of_iomap() to combine
functionalities of both of_address_to_resource() & ioremap().
We will also incorporate your other suggestions and then resubmit the
patch.
Ashish
-----Original Message-----
From: Arnd Bergmann [mailto:arnd@arndb.de]=20
Sent: Friday, October 12, 2007 7:52 PM
To: linuxppc-dev@ozlabs.org
Cc: Li Yang-r58472; jgarzik@pobox.com; linux-ide@vger.kernel.org; Kalra
Ashish-B00888
Subject: Re: [PATCH v2] drivers/ata: add support to Freescale 3.0Gbps
SATA Controller
On Friday 12 October 2007, Li Yang wrote:
> This patch adds support for Freescale 3.0Gbps SATA Controller=20
> supporting Native Command Queueing(NCQ), device hotplug, and ATAPI. =20
> This controller can be found on MPC8315 and MPC8378.
Most of the driver looks really good, but here are a few things that
stick out:
> +static int sata_fsl_probe(struct of_device *ofdev,
> + const struct of_device_id *match)
> +{
> + int retval =3D 0;
> + void __iomem *hcr_base =3D NULL;
> + void __iomem *ssr_base =3D NULL;
> + void __iomem *csr_base =3D NULL;
> + struct sata_fsl_host_priv *host_priv =3D NULL;
> + struct resource *r;
> + int irq;
> + struct ata_host *host;
> +
> + struct ata_port_info pi =3D sata_fsl_port_info[0];
> + const struct ata_port_info *ppi[] =3D { &pi, NULL };
> +
> + dev_printk(KERN_INFO, &ofdev->dev,
> + "Sata FSL Platform/CSB Driver init\n");
> +
> + r =3D kmalloc(sizeof(struct resource), GFP_KERNEL);
> + retval =3D of_address_to_resource(ofdev->node, 0, r);
> + if (retval)
> + return -EINVAL;
> +
> + DPRINTK("start i/o @0x%x\n", r->start);
> +
> + hcr_base =3D ioremap(r->start, r->end - r->start + 1);
> + if (!hcr_base)
> + goto error_exit_with_cleanup;
Hmm, I think we should redefine of_iomap to do the right thing for you.
currently, it is the combination of of_address_to_resource and ioremap,
which you do as well, so your code can be simplified to do that.
However, ioremap is meant to be used with readl/writel or
in_le32/out_le32 and similar functions, not with ioread32/iowrite32
which you are using.
I had planned to do a patch to get that right for some time so you can
use of_iomap with ioread in all cases, but I guess you should start
using of_iomap even now.
> +
> +error_exit_with_cleanup:
> +
> + if (hcr_base)
> + iounmap(hcr_base);
> + if (host_priv)
> + kfree(host_priv);
> +
> + return retval;
> +}
Once of_iomap start using devres, we would no longer need to iounmap
here.
> +static int sata_fsl_remove(struct of_device *ofdev) {
> + struct ata_host *host =3D dev_get_drvdata(&ofdev->dev);
> + struct sata_fsl_host_priv *host_priv =3D host->private_data;
> +
> + dev_set_drvdata(&ofdev->dev, NULL);
> +
> + iounmap(host_priv->hcr_base);
> + kfree(host_priv);
> +
> + return 0;
> +}
Should you also free the irq mapping here?
> --- /dev/null
> +++ b/drivers/ata/sata_fsl.h
> @@ -0,0 +1,92 @@
> +/*
> + * drivers/ata/sata_fsl.h
> + *
> + * Freescale 3.0Gbps SATA device driver
The header file is entirely pointless, since all definitions in here are
only used in a single file. Please merge the header into the
implementation.
> +static int sata_fsl_probe(struct of_device *ofdev,
> + const struct of_device_id *match); static int=20
> +sata_fsl_remove(struct of_device *ofdev); static int=20
> +sata_fsl_scr_read(struct ata_port *, unsigned int, u32 *); static int
> +sata_fsl_scr_write(struct ata_port *, unsigned int, u32); static=20
> +unsigned int sata_fsl_qc_issue(struct ata_queued_cmd *); static=20
> +irqreturn_t sata_fsl_interrupt(int, void *); static void=20
> +sata_fsl_irq_clear(struct ata_port *); static int=20
> +sata_fsl_port_start(struct ata_port *); static void=20
> +sata_fsl_port_stop(struct ata_port *); static void=20
> +sata_fsl_tf_read(struct ata_port *, struct ata_taskfile *); static=20
> +void sata_fsl_qc_prep(struct ata_queued_cmd *); static u8=20
> +sata_fsl_check_status(struct ata_port *); static void=20
> +sata_fsl_freeze(struct ata_port *); static void sata_fsl_thaw(struct=20
> +ata_port *); static void sata_fsl_error_handler(struct ata_port *);=20
> +static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *);
> +
> +static inline unsigned int sata_fsl_tag(unsigned int, void __iomem=20
> +*);
In particular, get rid of the forward declarations for static functions.
All functions in a simple driver should be ordered in a way that you
always reference only code that was previously defined. This helps avoid
accidental recursions and makes it easier to review.
Arnd <><
^ permalink raw reply
* Re: [PATCH v2] drivers/ata: add support to Freescale 3.0Gbps SATA Controller
From: Arnd Bergmann @ 2007-10-15 11:45 UTC (permalink / raw)
To: Kalra Ashish-B00888; +Cc: linuxppc-dev, jgarzik, linux-ide
In-Reply-To: <2A6F278C5B66C4459AF4013E77A40CD3FCBB59@zin33exm20.fsl.freescale.net>
On Monday 15 October 2007, Kalra Ashish-B00888 wrote:
> Thanks for your comments and feedback.
>
> Actually, for PowerPC platforms iowrite32/ioread32 internally call
> writel/readl, which are again mapped to out_le32/in_le32,
This is correct on 6xx and e500 for now, but it's a little more
complicated than that in general:
iowriteXX/ioreadXX are either the simple readX/writeX wrappers
from arch/powerpc/kernel/iomap.c, or the more complex functions
from lib/iomap.c, depending on whether any of the active platforms
has set CONFIG_PPC_INDIRECT_IO.
writeX/readX can either map directly to out_leXX/in_leXX, or do
something more complicated, again depending on the platform.
In general, writeX/readX may need to consider PCI specific error
handling or synchronization requirements, while out_leXX/in_leXX
are low-level accessors that should only be used by device drivers
when they are used on directly connected (non-PCI) devices.
Since iowriteXX/ioreadXX is supposed to be the most generic
variant covering both PCI MMIO (writeX/readX) and PCI PIO
(outX/inX) transfers, it would make sense to extend them to
also do SOC MMIO (out_leXX/in_leXX/out_beXX/in_beXX) and
DCR (dcr_write/dcr_read) accesses in the future.
Arnd <><
^ permalink raw reply
* Re: [PATCH v2 4/7] bestcomm: core bestcomm support for Freescale MPC5200
From: Matt Sealey @ 2007-10-15 11:55 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, paulus, domen.puncer
In-Reply-To: <20071014044205.23438.36036.stgit@trillian.cg.shawcable.net>
My nits:
Grant Likely wrote:
> From: Sylvain Munaut <tnt@246tNt.com>
> +static int __devinit
> +bcom_engine_init(void)
Why "bcom" and not "bestcomm"?
> + /* Disable COMM Bus Prefetch, apparently it's not reliable yet */
> + /* FIXME: This should be done on 5200 and not 5200B ... */
> + out_be16(&bcom_eng->regs->PtdCntrl, in_be16(&bcom_eng->regs->PtdCntrl) | 1);
This really, really shouldn't even be here, could it be moved to a platform
init, or switched on a PVR/SVR here?
> +int bcom_sram_init(struct device_node *sram_node, char *owner)
> +{
> + int rv;
> + const u32 *regaddr_p;
> + u64 regaddr64, size64;
> + unsigned int psize;
> +
> + /* Create our state struct */
> + if (bcom_sram) {
> + printk(KERN_ERR "%s: bcom_sram_init: "
> + "Already initialiwed !\n", owner);
> + return -EBUSY;
> + }
initialised or initialized :)
> + printk(KERN_ERR "%s: bcom_sram_init: "
> + "Couln't request region !\n", owner);
> + rv = -EBUSY;
> + goto error_free;
Couldn't or could not.
--
Matt Sealey <matt@genesi-usa.com>
Genesi, Manager, Developer Relations
^ permalink raw reply
* RE: [PATCH v3 3/9] add Freescale SerDes PHY support
From: Li Yang-r58472 @ 2007-10-15 12:30 UTC (permalink / raw)
To: Arnd Bergmann, linuxppc-dev; +Cc: linuxppc-dev, paulus
In-Reply-To: <200710121633.49263.arnd@arndb.de>
> -----Original Message-----
> From: linuxppc-dev-bounces+leoli=3Dfreescale.com@ozlabs.org=20
> [mailto:linuxppc-dev-bounces+leoli=3Dfreescale.com@ozlabs.org]=20
> On Behalf Of Arnd Bergmann
> Sent: Friday, October 12, 2007 10:34 PM
> To: linuxppc-dev@ozlabs.org
> Cc: linuxppc-dev@ozlabs.org; paulus@samba.org
> Subject: Re: [PATCH v3 3/9] add Freescale SerDes PHY support
>=20
> On Friday 12 October 2007, Li Yang wrote:
> > The SerDes(serializer/deserializer) PHY block is a new SoC=20
> block used=20
> > in Freescale chips to support multiple serial interfaces,=20
> such as PCI=20
> > Express, SGMII, SATA.
>=20
> Some of my comments here are similar to those for the ata=20
> driver, so I won't be as verbose here
>=20
> > +static int __init setup_serdes(struct device_node *np) {
> > + void __iomem *regs;
> > + const void *prot;
> > + const unsigned int *freq;
> > + struct resource res;
> > + u32 rfcks;
> > +
> > + of_address_to_resource(np, 0, &res);
> > + regs =3D ioremap(res.start, res.end - res.start + 1);
>=20
> of_iomap?
I'd like to but of_iomap() couldn't provide the physical address of the
device used as identification.
- Leo
^ permalink raw reply
* [PATCH 1/2] i2c: ibm_iic: Whitespace cleanup
From: Stefan Roese @ 2007-10-15 13:28 UTC (permalink / raw)
To: i2c, linuxppc-dev; +Cc: Jean Delvare
Signed-off-by: Stefan Roese <sr@denx.de>
=2D--
drivers/i2c/busses/i2c-ibm_iic.c | 192 +++++++++++++++++++---------------=
=2D---
drivers/i2c/busses/i2c-ibm_iic.h | 8 +-
2 files changed, 100 insertions(+), 100 deletions(-)
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_=
iic.c
index e08baca..956b947 100644
=2D-- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -6,7 +6,7 @@
* Copyright (c) 2003, 2004 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
=2D * Based on original work by=20
+ * Based on original work by
* Ian DaSilva <idasilva@mvista.com>
* Armin Kuster <akuster@mvista.com>
* Matt Porter <mporter@mvista.com>
@@ -18,7 +18,7 @@
* Copyright 1995-97 Simon G. Vogl
* 1998-99 Hans Berglund
*
=2D * With some changes from Ky=F6sti M=E4lkki <kmalkki@cc.hut.fi>=20
+ * With some changes from Ky=F6sti M=E4lkki <kmalkki@cc.hut.fi>
* and even Frodo Looijaard <frodol@dds.nl>
*
* This program is free software; you can redistribute it and/or modify it
@@ -86,8 +86,8 @@ static void dump_iic_regs(const char* header, struct ibm_=
iic_private* dev)
KERN_DEBUG " sts =3D 0x%02x, extsts =3D 0x%02x\n"
KERN_DEBUG " clkdiv =3D 0x%02x, xfrcnt =3D 0x%02x\n"
KERN_DEBUG " xtcntlss =3D 0x%02x, directcntl =3D 0x%02x\n",
=2D in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts),=20
=2D in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt),=20
+ in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts),
+ in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt),
in_8(&iic->xtcntlss), in_8(&iic->directcntl));
}
# define DUMP_REGS(h,dev) dump_iic_regs((h),(dev))
@@ -125,7 +125,7 @@ static inline void iic_interrupt_mode(struct ibm_iic_pr=
ivate* dev, int enable)
{
out_8(&dev->vaddr->intmsk, enable ? INTRMSK_EIMTC : 0);
}
=2D=20
+
/*
* Initialize IIC interface.
*/
@@ -134,7 +134,7 @@ static void iic_dev_init(struct ibm_iic_private* dev)
volatile struct iic_regs __iomem *iic =3D dev->vaddr;
=20
DBG("%d: init\n", dev->idx);
=2D=09
+
/* Clear master address */
out_8(&iic->lmadr, 0);
out_8(&iic->hmadr, 0);
@@ -160,7 +160,7 @@ static void iic_dev_init(struct ibm_iic_private* dev)
=20
/* Clear control register */
out_8(&iic->cntl, 0);
=2D=09
+
/* Enable interrupts if possible */
iic_interrupt_mode(dev, dev->irq >=3D 0);
=20
@@ -171,7 +171,7 @@ static void iic_dev_init(struct ibm_iic_private* dev)
DUMP_REGS("iic_init", dev);
}
=20
=2D/*=20
+/*
* Reset IIC interface
*/
static void iic_dev_reset(struct ibm_iic_private* dev)
@@ -179,42 +179,42 @@ static void iic_dev_reset(struct ibm_iic_private* dev)
volatile struct iic_regs __iomem *iic =3D dev->vaddr;
int i;
u8 dc;
=2D=09
+
DBG("%d: soft reset\n", dev->idx);
DUMP_REGS("reset", dev);
=2D=09
+
/* Place chip in the reset state */
out_8(&iic->xtcntlss, XTCNTLSS_SRST);
=2D=09
+
/* Check if bus is free */
=2D dc =3D in_8(&iic->directcntl);=09
+ dc =3D in_8(&iic->directcntl);
if (!DIRCTNL_FREE(dc)){
DBG("%d: trying to regain bus control\n", dev->idx);
=2D=09
+
/* Try to set bus free state */
=2D out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC);=09
=2D=09
+ out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC);
+
/* Wait until we regain bus control */
for (i =3D 0; i < 100; ++i){
dc =3D in_8(&iic->directcntl);
if (DIRCTNL_FREE(dc))
break;
=2D =09
+
/* Toggle SCL line */
dc ^=3D DIRCNTL_SCC;
out_8(&iic->directcntl, dc);
udelay(10);
dc ^=3D DIRCNTL_SCC;
out_8(&iic->directcntl, dc);
=2D =09
+
/* be nice */
cond_resched();
}
}
=2D=09
+
/* Remove reset */
out_8(&iic->xtcntlss, 0);
=2D=09
+
/* Reinitialize interface */
iic_dev_init(dev);
}
@@ -324,14 +324,14 @@ static irqreturn_t iic_handler(int irq, void *dev_id)
{
struct ibm_iic_private* dev =3D (struct ibm_iic_private*)dev_id;
volatile struct iic_regs __iomem *iic =3D dev->vaddr;
=2D=09
=2D DBG2("%d: irq handler, STS =3D 0x%02x, EXTSTS =3D 0x%02x\n",=20
+
+ DBG2("%d: irq handler, STS =3D 0x%02x, EXTSTS =3D 0x%02x\n",
dev->idx, in_8(&iic->sts), in_8(&iic->extsts));
=2D=09
+
/* Acknowledge IRQ and wakeup iic_wait_for_tc */
out_8(&iic->sts, STS_IRQA | STS_SCMP);
wake_up_interruptible(&dev->wq);
=2D=09
+
return IRQ_HANDLED;
}
=20
@@ -341,19 +341,19 @@ static irqreturn_t iic_handler(int irq, void *dev_id)
*/
static int iic_xfer_result(struct ibm_iic_private* dev)
{
=2D volatile struct iic_regs __iomem *iic =3D dev->vaddr;=09
=2D=09
+ volatile struct iic_regs __iomem *iic =3D dev->vaddr;
+
if (unlikely(in_8(&iic->sts) & STS_ERR)){
=2D DBG("%d: xfer error, EXTSTS =3D 0x%02x\n", dev->idx,=20
+ DBG("%d: xfer error, EXTSTS =3D 0x%02x\n", dev->idx,
in_8(&iic->extsts));
=2D =09
+
/* Clear errors and possible pending IRQs */
=2D out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD |=20
+ out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD |
EXTSTS_LA | EXTSTS_ICT | EXTSTS_XFRA);
=2D =09
+
/* Flush master data buffer */
out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB);
=2D =09
+
/* Is bus free?
* If error happened during combined xfer
* IIC interface is usually stuck in some strange
@@ -376,11 +376,11 @@ static void iic_abort_xfer(struct ibm_iic_private* de=
v)
{
volatile struct iic_regs __iomem *iic =3D dev->vaddr;
unsigned long x;
=2D=09
+
DBG("%d: iic_abort_xfer\n", dev->idx);
=2D=09
+
out_8(&iic->cntl, CNTL_HMT);
=2D=09
+
/*
* Wait for the abort command to complete.
* It's not worth to be optimized, just poll (timeout >=3D 1 tick)
@@ -405,13 +405,13 @@ static void iic_abort_xfer(struct ibm_iic_private* de=
v)
* Returns the number of transferred bytes or error (<0)
*/
static int iic_wait_for_tc(struct ibm_iic_private* dev){
=2D=09
+
volatile struct iic_regs __iomem *iic =3D dev->vaddr;
int ret =3D 0;
=2D=09
+
if (dev->irq >=3D 0){
/* Interrupt mode */
=2D ret =3D wait_event_interruptible_timeout(dev->wq,=20
+ ret =3D wait_event_interruptible_timeout(dev->wq,
!(in_8(&iic->sts) & STS_PT), dev->adap.timeout * HZ);
=20
if (unlikely(ret < 0))
@@ -424,37 +424,37 @@ static int iic_wait_for_tc(struct ibm_iic_private* de=
v){
else {
/* Polling mode */
unsigned long x =3D jiffies + dev->adap.timeout * HZ;
=2D =09
+
while (in_8(&iic->sts) & STS_PT){
if (unlikely(time_after(jiffies, x))){
DBG("%d: poll timeout\n", dev->idx);
ret =3D -ETIMEDOUT;
break;
}
=2D =09
+
if (unlikely(signal_pending(current))){
DBG("%d: poll interrupted\n", dev->idx);
ret =3D -ERESTARTSYS;
break;
}
schedule();
=2D }=09
+ }
}
=2D=09
+
if (unlikely(ret < 0))
iic_abort_xfer(dev);
else
ret =3D iic_xfer_result(dev);
=2D=09
+
DBG2("%d: iic_wait_for_tc -> %d\n", dev->idx, ret);
=2D=09
+
return ret;
}
=20
/*
* Low level master transfer routine
*/
=2Dstatic int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* p=
m,=20
+static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm,
int combined_xfer)
{
volatile struct iic_regs __iomem *iic =3D dev->vaddr;
@@ -465,48 +465,48 @@ static int iic_xfer_bytes(struct ibm_iic_private* dev=
, struct i2c_msg* pm,
u8 cntl =3D (in_8(&iic->cntl) & CNTL_AMD) | CNTL_PT;
if (pm->flags & I2C_M_RD)
cntl |=3D CNTL_RW;
=2D=09
+
loops =3D (len + 3) / 4;
for (i =3D 0; i < loops; ++i, len -=3D 4){
int count =3D len > 4 ? 4 : len;
u8 cmd =3D cntl | ((count - 1) << CNTL_TCT_SHIFT);
=2D =09
+
if (!(cntl & CNTL_RW))
for (j =3D 0; j < count; ++j)
out_8((void __iomem *)&iic->mdbuf, *buf++);
=2D =09
+
if (i < loops - 1)
cmd |=3D CNTL_CHT;
else if (combined_xfer)
cmd |=3D CNTL_RPST;
=2D =09
+
DBG2("%d: xfer_bytes, %d, CNTL =3D 0x%02x\n", dev->idx, count, cmd);
=2D =09
+
/* Start transfer */
out_8(&iic->cntl, cmd);
=2D =09
+
/* Wait for completion */
ret =3D iic_wait_for_tc(dev);
=20
if (unlikely(ret < 0))
break;
else if (unlikely(ret !=3D count)){
=2D DBG("%d: xfer_bytes, requested %d, transfered %d\n",=20
+ DBG("%d: xfer_bytes, requested %d, transfered %d\n",
dev->idx, count, ret);
=2D =09
+
/* If it's not a last part of xfer, abort it */
if (combined_xfer || (i < loops - 1))
iic_abort_xfer(dev);
=2D =09
+
ret =3D -EREMOTEIO;
=2D break; =09
+ break;
}
=2D =09
+
if (cntl & CNTL_RW)
for (j =3D 0; j < count; ++j)
*buf++ =3D in_8((void __iomem *)&iic->mdbuf);
}
=2D=09
+
return ret > 0 ? 0 : ret;
}
=20
@@ -517,10 +517,10 @@ static inline void iic_address(struct ibm_iic_private=
* dev, struct i2c_msg* msg)
{
volatile struct iic_regs __iomem *iic =3D dev->vaddr;
u16 addr =3D msg->addr;
=2D=09
=2D DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx,=20
+
+ DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx,
addr, msg->flags & I2C_M_TEN ? 10 : 7);
=2D=09
+
if (msg->flags & I2C_M_TEN){
out_8(&iic->cntl, CNTL_AMD);
out_8(&iic->lmadr, addr);
@@ -537,15 +537,15 @@ static inline int iic_invalid_address(const struct i2=
c_msg* p)
return (p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN) && (p->addr > 0x7f));
}
=20
=2Dstatic inline int iic_address_neq(const struct i2c_msg* p1,=20
+static inline int iic_address_neq(const struct i2c_msg* p1,
const struct i2c_msg* p2)
{
=2D return (p1->addr !=3D p2->addr)=20
+ return (p1->addr !=3D p2->addr)
|| ((p1->flags & I2C_M_TEN) !=3D (p2->flags & I2C_M_TEN));
=2D}=20
+}
=20
/*
=2D * Generic master transfer entrypoint.=20
+ * Generic master transfer entrypoint.
* Returns the number of processed messages or error (<0)
*/
static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int nu=
m)
@@ -553,20 +553,20 @@ static int iic_xfer(struct i2c_adapter *adap, struct =
i2c_msg *msgs, int num)
struct ibm_iic_private* dev =3D (struct ibm_iic_private*)(i2c_get_ada=
pdata(adap));
volatile struct iic_regs __iomem *iic =3D dev->vaddr;
int i, ret =3D 0;
=2D=09
+
DBG2("%d: iic_xfer, %d msg(s)\n", dev->idx, num);
=2D=09
+
if (!num)
return 0;
=2D=09
+
/* Check the sanity of the passed messages.
* Uhh, generic i2c layer is more suitable place for such code...
*/
if (unlikely(iic_invalid_address(&msgs[0]))){
=2D DBG("%d: invalid address 0x%03x (%d-bit)\n", dev->idx,=20
+ DBG("%d: invalid address 0x%03x (%d-bit)\n", dev->idx,
msgs[0].addr, msgs[0].flags & I2C_M_TEN ? 10 : 7);
return -EINVAL;
=2D } =09
+ }
for (i =3D 0; i < num; ++i){
if (unlikely(msgs[i].len <=3D 0)){
if (num =3D=3D 1 && !msgs[0].len){
@@ -576,7 +576,7 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2=
c_msg *msgs, int num)
*/
return iic_smbus_quick(dev, &msgs[0]);
}
=2D DBG("%d: invalid len %d in msg[%d]\n", dev->idx,=20
+ DBG("%d: invalid len %d in msg[%d]\n", dev->idx,
msgs[i].len, i);
return -EINVAL;
}
@@ -585,34 +585,34 @@ static int iic_xfer(struct i2c_adapter *adap, struct =
i2c_msg *msgs, int num)
return -EINVAL;
}
}
=2D=09
+
/* Check bus state */
if (unlikely((in_8(&iic->extsts) & EXTSTS_BCS_MASK) !=3D EXTSTS_BCS_FREE)=
){
DBG("%d: iic_xfer, bus is not free\n", dev->idx);
=2D =09
+
/* Usually it means something serious has happend.
* We *cannot* have unfinished previous transfer
* so it doesn't make any sense to try to stop it.
=2D * Probably we were not able to recover from the=20
+ * Probably we were not able to recover from the
* previous error.
* The only *reasonable* thing I can think of here
* is soft reset. --ebs
*/
iic_dev_reset(dev);
=2D =09
+
if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) !=3D EXTSTS_BCS_FREE){
DBG("%d: iic_xfer, bus is still not free\n", dev->idx);
return -EREMOTEIO;
}
=2D }=20
+ }
else {
/* Flush master data buffer (just in case) */
out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB);
}
=2D=09
+
/* Load slave address */
iic_address(dev, &msgs[0]);
=2D=09
+
/* Do real transfer */
for (i =3D 0; i < num && !ret; ++i)
ret =3D iic_xfer_bytes(dev, &msgs[i], i < num - 1);
@@ -648,7 +648,7 @@ static inline u8 iic_clckdiv(unsigned int opb)
=20
/* Convert to MHz */
opb /=3D 1000000;
=2D=09
+
if (opb < 20 || opb > 150){
printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n",
opb);
@@ -666,7 +666,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
struct i2c_adapter* adap;
struct ocp_func_iic_data* iic_data =3D ocp->def->additions;
int ret;
=2D=09
+
if (!iic_data)
printk(KERN_WARNING"ibm-iic%d: missing additional data!\n",
ocp->def->index);
@@ -679,7 +679,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
=20
dev->idx =3D ocp->def->index;
ocp_set_drvdata(ocp, dev);
=2D=09
+
if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs),
"ibm_iic")) {
ret =3D -EBUSY;
@@ -692,7 +692,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
ret =3D -ENXIO;
goto fail2;
}
=2D=09
+
init_waitqueue_head(&dev->wq);
=20
dev->irq =3D iic_force_poll ? -1 : ocp->def->irq;
@@ -702,29 +702,29 @@ static int __devinit iic_probe(struct ocp_device *ocp=
){
*/
iic_interrupt_mode(dev, 0);
if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){
=2D printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n",=20
+ printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n",
dev->idx, dev->irq);
=2D /* Fallback to the polling mode */=09
+ /* Fallback to the polling mode */
dev->irq =3D -1;
}
}
=2D=09
+
if (dev->irq < 0)
=2D printk(KERN_WARNING "ibm-iic%d: using polling mode\n",=20
+ printk(KERN_WARNING "ibm-iic%d: using polling mode\n",
dev->idx);
=2D =09
+
/* Board specific settings */
dev->fast_mode =3D iic_force_fast ? 1 : (iic_data ? iic_data->fast_mode :=
0);
=2D=09
=2D /* clckdiv is the same for *all* IIC interfaces,=20
+
+ /* clckdiv is the same for *all* IIC interfaces,
* but I'd rather make a copy than introduce another global. --ebs
*/
dev->clckdiv =3D iic_clckdiv(ocp_sys_info.opb_bus_freq);
DBG("%d: clckdiv =3D %d\n", dev->idx, dev->clckdiv);
=2D=09
+
/* Initialize IIC interface */
iic_dev_init(dev);
=2D=09
+
/* Register it with i2c layer */
adap =3D &dev->adap;
adap->dev.parent =3D &ocp->dev;
@@ -750,24 +750,24 @@ static int __devinit iic_probe(struct ocp_device *ocp=
){
dev->idx);
goto fail;
}
=2D=09
+
printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx,
dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
=20
return 0;
=20
=2Dfail:=09
+fail:
if (dev->irq >=3D 0){
iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
=2D }=09
+ }
=20
iounmap(dev->vaddr);
=2Dfail2:=09
+fail2:
release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
fail1:
ocp_set_drvdata(ocp, NULL);
=2D kfree(dev);=09
+ kfree(dev);
return ret;
}
=20
@@ -783,13 +783,13 @@ static void __devexit iic_remove(struct ocp_device *o=
cp)
dev->idx);
/* That's *very* bad, just shutdown IRQ ... */
if (dev->irq >=3D 0){
=2D iic_interrupt_mode(dev, 0);=09
+ iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
dev->irq =3D -1;
}
} else {
if (dev->irq >=3D 0){
=2D iic_interrupt_mode(dev, 0);=09
+ iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
}
iounmap(dev->vaddr);
@@ -798,7 +798,7 @@ static void __devexit iic_remove(struct ocp_device *ocp)
}
}
=20
=2Dstatic struct ocp_device_id ibm_iic_ids[] __devinitdata =3D=20
+static struct ocp_device_id ibm_iic_ids[] __devinitdata =3D
{
{ .vendor =3D OCP_VENDOR_IBM, .function =3D OCP_FUNC_IIC },
{ .vendor =3D OCP_VENDOR_INVALID }
diff --git a/drivers/i2c/busses/i2c-ibm_iic.h b/drivers/i2c/busses/i2c-ibm_=
iic.h
index 59d7b43..fdaa482 100644
=2D-- a/drivers/i2c/busses/i2c-ibm_iic.h
+++ b/drivers/i2c/busses/i2c-ibm_iic.h
@@ -2,11 +2,11 @@
* drivers/i2c/busses/i2c-ibm_iic.h
*
* Support for the IIC peripheral on IBM PPC 4xx
=2D *=20
+ *
* Copyright (c) 2003 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
=2D * Based on original work by=20
+ * Based on original work by
* Ian DaSilva <idasilva@mvista.com>
* Armin Kuster <akuster@mvista.com>
* Matt Porter <mporter@mvista.com>
@@ -22,7 +22,7 @@
#ifndef __I2C_IBM_IIC_H_
#define __I2C_IBM_IIC_H_
=20
=2D#include <linux/i2c.h>=20
+#include <linux/i2c.h>
=20
struct iic_regs {
u16 mdbuf;
@@ -58,7 +58,7 @@ struct ibm_iic_private {
#define CNTL_TCT_MASK 0x30
#define CNTL_TCT_SHIFT 4
#define CNTL_RPST 0x08
=2D#define CNTL_CHT 0x04=20
+#define CNTL_CHT 0x04
#define CNTL_RW 0x02
#define CNTL_PT 0x01
=20
=2D-=20
1.5.3.4
^ permalink raw reply
* can and mpc5200b
From: S. Fricke @ 2007-10-15 13:32 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 514 bytes --]
Hello Friends,
what is the reasonable can-driver for a mpc5200b?
I have seen for the peak-3.17 driver a port for the mpc5200 from denx on their
website, but with kernel 2.6.23 I dont have a chance to use this?
greetings,
Silvio Fricke
--
-- S. Fricke ----------------------------- MAILTO:silvio.fricke@gmail.com --
Diplom-Informatiker (FH)
Linux-Entwicklung JABBER: silvio@jabber.ccc.de
----------------------------------------------------------------------------
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: libfdt: Test rw functions on more trees
From: Jon Loeliger @ 2007-10-15 13:34 UTC (permalink / raw)
To: David Gibson; +Cc: linuxppc-dev
In-Reply-To: <20070928045701.GB25743@localhost.localdomain>
So, like, the other day David Gibson mumbled:
> At present, the testcases for read/write functions (setprop,
> del_property and del_node) are only invoked on the single
> asm-generated tree, not on any of the other tree images which should
> be equivalent. The functions in question will (correctly) not work on
> the "unfinished" tree output from sw_tree1, but should work on most of
> the others.
>
> This patch extends the run_tests script to invoke the r/w testcases on
> more example trees. The testsuite still passes clean with this
> addition.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Applied.
Thanks,
jdl
^ permalink raw reply
* Re: libfdt: Make unit address optional for finding nodes
From: Jon Loeliger @ 2007-10-15 13:35 UTC (permalink / raw)
To: David Gibson; +Cc: linuxppc-dev
In-Reply-To: <20070928055104.GE25743@localhost.localdomain>
So, like, the other day David Gibson mumbled:
> At present, the fdt_subnode_offset() and fdt_path_offset() functions
> in libfdt require the exact name of the nodes in question be passed,
> including unit address.
>
> This is contrary to traditional OF-like finddevice() behaviour, which
> allows the unit address to be omitted (which is useful when the device
> name is unambiguous without the address).
>
> This patch introduces similar behaviour to
> fdt_subnode_offset_namelen(), and hence to fdt_subnode_offset() and
> fdt_path_offset() which are implemented in terms of the former. The
> unit address can be omitted from the given node name. If this is
> ambiguous, the first such node in the flattened tree will be selected
> (this behaviour is consistent with IEEE1275 which specifies only that
> an arbitrary node matching the given information be selected).
>
> This very small change is then followed by many more diffs which
> change the test examples and testcases to exercise this behaviour.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
Applied.
> Jon, I initially considered making this behaviour optional,
> i.e. adding a flag to subnode_offset() determining if it needed exact
> matches or name-without-address matches. I couldn't see that it was
> actually any use, though.
Yeah, sounds fine to me too.
Thanks,
jdl
^ permalink raw reply
* [PATCH 2/2] i2c: Add devtree-aware iic support for PPC4xx
From: Stefan Roese @ 2007-10-15 13:29 UTC (permalink / raw)
To: i2c, linuxppc-dev; +Cc: Jean Delvare
This patch reworks existing ibm-iic driver to support of_platform_device
and enables it to talk to device tree directly. The "old" OCP interface
for arch/ppc is still supported via #ifdef's and shall be removed when
arch/ppc is gone in a few months.
This is done to enable I2C support for the PPC4xx platforms now
being moved from arch/ppc (ocp) to arch/powerpc (of).
Signed-off-by: Stefan Roese <sr@denx.de>
---
drivers/i2c/busses/Kconfig | 2 +-
drivers/i2c/busses/i2c-ibm_iic.c | 209 +++++++++++++++++++++++++++++++++++++-
drivers/i2c/busses/i2c-ibm_iic.h | 2 +
3 files changed, 211 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index de95c75..a47b5e6 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -241,7 +241,7 @@ config I2C_PIIX4
config I2C_IBM_IIC
tristate "IBM PPC 4xx on-chip I2C interface"
- depends on IBM_OCP
+ depends on 4xx
help
Say Y here if you want to use IIC peripheral found on
embedded IBM PPC 4xx based systems.
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 956b947..78c6bf4 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -39,8 +39,13 @@
#include <asm/io.h>
#include <linux/i2c.h>
#include <linux/i2c-id.h>
+
+#ifdef CONFIG_PPC_MERGE
+#include <linux/of_platform.h>
+#else
#include <asm/ocp.h>
#include <asm/ibm4xx.h>
+#endif
#include "i2c-ibm_iic.h"
@@ -57,6 +62,10 @@ static int iic_force_fast;
module_param(iic_force_fast, bool, 0);
MODULE_PARM_DESC(iic_fast_poll, "Force fast mode (400 kHz)");
+#ifdef CONFIG_PPC_MERGE
+static int device_idx = -1;
+#endif
+
#define DBG_LEVEL 0
#ifdef DBG
@@ -660,8 +669,205 @@ static inline u8 iic_clckdiv(unsigned int opb)
/*
* Register single IIC interface
*/
-static int __devinit iic_probe(struct ocp_device *ocp){
+#ifdef CONFIG_PPC_MERGE
+/*
+ * device-tree (of) when used from arch/powerpc
+ */
+static int __devinit iic_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct ibm_iic_private* dev;
+ struct i2c_adapter* adap;
+ struct device_node *np;
+ int ret = -ENODEV;
+ int irq, len;
+ const u32 *prop;
+ struct resource res;
+
+ np = ofdev->node;
+ if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) {
+ printk(KERN_CRIT "ibm-iic(%s): failed to allocate device data\n",
+ np->full_name);
+ return -ENOMEM;
+ }
+
+ dev_set_drvdata(&ofdev->dev, dev);
+
+ dev->np = np;
+ irq = irq_of_parse_and_map(np, 0);
+
+ if (of_address_to_resource(np, 0, &res)) {
+ printk(KERN_ERR "ibd-iic(%s): Can't get registers address\n",
+ np->full_name);
+ goto fail1;
+ }
+ dev->paddr = res.start;
+
+ if (!request_mem_region(dev->paddr, sizeof(struct iic_regs), "ibm_iic")) {
+ ret = -EBUSY;
+ goto fail1;
+ }
+ dev->vaddr = ioremap(dev->paddr, sizeof(struct iic_regs));
+
+ if (dev->vaddr == NULL) {
+ printk(KERN_CRIT "ibm-iic(%s): failed to ioremap device regs\n",
+ dev->np->full_name);
+ ret = -ENXIO;
+ goto fail2;
+ }
+
+ init_waitqueue_head(&dev->wq);
+
+ dev->irq = iic_force_poll ? -1 : (irq == NO_IRQ) ? -1 : irq;
+ if (dev->irq >= 0){
+ /* Disable interrupts until we finish initialization,
+ * assumes level-sensitive IRQ setup...
+ */
+ iic_interrupt_mode(dev, 0);
+ if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)) {
+ printk(KERN_ERR "ibm-iic(%s): request_irq %d failed\n",
+ dev->np->full_name, dev->irq);
+ /* Fallback to the polling mode */
+ dev->irq = -1;
+ }
+ }
+
+ if (dev->irq < 0)
+ printk(KERN_WARNING "ibm-iic(%s): using polling mode\n",
+ dev->np->full_name);
+
+ /* Board specific settings */
+ prop = of_get_property(np, "iic-mode", &len);
+ /* use 400kHz only if stated in dts, 100kHz otherwise */
+ dev->fast_mode = (prop && (*prop == 400));
+ /* clckdiv is the same for *all* IIC interfaces,
+ * but I'd rather make a copy than introduce another global. --ebs
+ */
+ /* Parent bus should have frequency filled */
+ prop = of_get_property(of_get_parent(np), "clock-frequency", &len);
+ if (prop == NULL) {
+ printk(KERN_ERR
+ "ibm-iic(%s):no clock-frequency prop on parent bus!\n",
+ dev->np->full_name);
+ goto fail;
+ }
+
+ dev->clckdiv = iic_clckdiv(*prop);
+ DBG("%s: clckdiv = %d\n", dev->np->full_name, dev->clckdiv);
+
+ /* Initialize IIC interface */
+ iic_dev_init(dev);
+
+ /* Register it with i2c layer */
+ adap = &dev->adap;
+ adap->dev.parent = &ofdev->dev;
+ strcpy(adap->name, "IBM IIC");
+ i2c_set_adapdata(adap, dev);
+ adap->id = I2C_HW_OCP;
+ adap->class = I2C_CLASS_HWMON;
+ adap->algo = &iic_algo;
+ adap->client_register = NULL;
+ adap->client_unregister = NULL;
+ adap->timeout = 1;
+ adap->retries = 1;
+
+ dev->idx = ++device_idx;
+ adap->nr = dev->idx;
+ if ((ret = i2c_add_numbered_adapter(adap)) < 0) {
+ printk(KERN_CRIT"ibm-iic(%s): failed to register i2c adapter\n",
+ dev->np->full_name);
+ goto fail;
+ }
+
+ printk(KERN_INFO "ibm-iic(%s): using %s mode\n", dev->np->full_name,
+ dev->fast_mode ?
+ "fast (400 kHz)" : "standard (100 kHz)");
+
+ return 0;
+
+fail:
+ if (dev->irq >= 0){
+ iic_interrupt_mode(dev, 0);
+ free_irq(dev->irq, dev);
+ }
+
+ iounmap(dev->vaddr);
+fail2:
+ release_mem_region(dev->paddr, sizeof(struct iic_regs));
+fail1:
+ dev_set_drvdata(&ofdev->dev, NULL);
+ kfree(dev);
+
+ return ret;
+}
+
+/*
+ * Cleanup initialized IIC interface
+ */
+static int __devexit iic_remove(struct of_device *ofdev)
+{
+ struct ibm_iic_private *dev =
+ (struct ibm_iic_private *)dev_get_drvdata(&ofdev->dev);
+ BUG_ON(dev == NULL);
+ if (i2c_del_adapter(&dev->adap)){
+ printk(KERN_CRIT "ibm-iic(%s): failed to delete i2c adapter\n",
+ dev->np->full_name);
+ /* That's *very* bad, just shutdown IRQ ... */
+ if (dev->irq >= 0){
+ iic_interrupt_mode(dev, 0);
+ free_irq(dev->irq, dev);
+ dev->irq = -1;
+ }
+ } else {
+ if (dev->irq >= 0){
+ iic_interrupt_mode(dev, 0);
+ free_irq(dev->irq, dev);
+ }
+ iounmap(dev->vaddr);
+ release_mem_region(dev->paddr, sizeof(struct iic_regs));
+ kfree(dev);
+ }
+ return 0;
+}
+
+static struct of_device_id ibm_iic_match[] = {
+ {
+ .type = "i2c",
+ .compatible = "ibm,iic",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, ibm_iic_match);
+
+static struct of_platform_driver ibm_iic_driver = {
+ .name = "ibm-iic",
+ .match_table = ibm_iic_match,
+ .probe = iic_probe,
+ .remove = iic_remove,
+#if defined(CONFIG_PM)
+ .suspend = NULL,
+ .resume = NULL,
+#endif
+};
+
+static int __init iic_init(void)
+{
+ printk(KERN_INFO "IBM IIC driver v" DRIVER_VERSION "\n");
+ return of_register_platform_driver(&ibm_iic_driver);
+}
+
+static void __exit iic_exit(void)
+{
+ of_unregister_platform_driver(&ibm_iic_driver);
+}
+#else
+/*
+ * OCP when used from arch/ppc
+ */
+static int __devinit iic_probe(struct ocp_device *ocp)
+{
struct ibm_iic_private* dev;
struct i2c_adapter* adap;
struct ocp_func_iic_data* iic_data = ocp->def->additions;
@@ -828,6 +1034,7 @@ static void __exit iic_exit(void)
{
ocp_unregister_driver(&ibm_iic_driver);
}
+#endif /* CONFIG_PPC_MERGE */
module_init(iic_init);
module_exit(iic_exit);
diff --git a/drivers/i2c/busses/i2c-ibm_iic.h b/drivers/i2c/busses/i2c-ibm_iic.h
index fdaa482..c15b091 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.h
+++ b/drivers/i2c/busses/i2c-ibm_iic.h
@@ -50,6 +50,8 @@ struct ibm_iic_private {
int irq;
int fast_mode;
u8 clckdiv;
+ struct device_node *np;
+ phys_addr_t paddr;
};
/* IICx_CNTL register */
--
1.5.3.4
^ permalink raw reply related
* Re: dtc: Refactor Makefiles (v2)
From: Jon Loeliger @ 2007-10-15 13:35 UTC (permalink / raw)
To: David Gibson; +Cc: linuxppc-dev
In-Reply-To: <20071004053743.GI6024@localhost.localdomain>
So, like, the other day David Gibson mumbled:
>
> Here's a corrected version.
>
> dtc: Refactor Makefiles
>
> This patch makes a number of Makefile cleanups and improvements:
> - We use more generic rules to invoke flex and bison, which is
> useful for some of the other changes.
> - We use the name dtc-lexer.lex.c for the flex output, instead
> of the default lex.yy.c. That means less potential for confusion if
> dtc is embedded into other projects (e.g. the kernel).
> - We separate out a Makefile.dtc designed for embedding into
> other projects, analagous to Makefile.libfdt.
> - Makefile.libfdt is cleaned up to be more useful based on
> some actual trial runs of embedding libfdt in the kernel bootwrapper.
> - Versioning related rules and variables are collected into
> one place in the Makefile.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Applied.
Thanks,
jdl
^ permalink raw reply
* Re: libfdt: Add functions to get/add/delete memory reservemap entries
From: Jon Loeliger @ 2007-10-15 13:37 UTC (permalink / raw)
To: David Gibson; +Cc: linuxppc-dev
In-Reply-To: <20071010071212.GC6135@localhost.localdomain>
So, like, the other day David Gibson mumbled:
> This patch adds functions to libfdt for accessing the memory
> reservation map section of a device tree blob. fdt_num_mem_rsv()
> retreives the number of reservation entries in a dtb, and
> fdt_get_mem_rsv() retreives a specific reservation entry.
> fdt_add_mem_rsv() adds a new entry, and fdt_del_mem_rsv() removes a
> specific numbered entry.
>
> Testcases for these new functions are also included.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Applied.
Thanks,
jdl
^ permalink raw reply
* Re: [PATCH v2 2/7] rheap: Changes config mechanism
From: Kumar Gala @ 2007-10-15 13:43 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, paulus, domen.puncer
In-Reply-To: <20071014044154.23438.58701.stgit@trillian.cg.shawcable.net>
On Oct 13, 2007, at 11:41 PM, Grant Likely wrote:
> From: Sylvain Munaut <tnt@246tNt.com>
>
> Instead of having in the makefile all the option that
> requires rheap, we define a configuration symbol
> and when needed we make sure it's selected.
>
> Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
>
> arch/powerpc/Kconfig | 4 ++++
> arch/powerpc/lib/Makefile | 5 +----
> arch/powerpc/platforms/Kconfig | 2 ++
> arch/powerpc/platforms/Kconfig.cputype | 1 +
> arch/ppc/Kconfig | 6 ++++++
> 5 files changed, 14 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 037664d..8300e6a 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -698,3 +698,7 @@ source "crypto/Kconfig"
> config PPC_CLOCK
> bool
> default n
> +
> +config PPC_LIB_RHEAP
we should really have help for this option.
> + bool
> +
- k
^ permalink raw reply
* [PATCH v2] [POWERPC] ucc_geth: Fix build break introduced by commit 09f75cd7bf13720738e6a196cc0107ce9a5bd5a0
From: Emil Medve @ 2007-10-15 13:43 UTC (permalink / raw)
To: akpm, jgarzik, leoli, netdev, linuxppc-dev; +Cc: Emil Medve
drivers/net/ucc_geth.c: In function 'ucc_geth_rx':
drivers/net/ucc_geth.c:3483: error: 'dev' undeclared (first use in this function)
drivers/net/ucc_geth.c:3483: error: (Each undeclared identifier is reported only once
drivers/net/ucc_geth.c:3483: error: for each function it appears in.)
make[2]: *** [drivers/net/ucc_geth.o] Error 1
Signed-off-by: Emil Medve <Emilian.Medve@Freescale.com>
---
Here is a convenient link for the culprit patch: http://git.kernel.org/?p=linux/kernel/git/jgarzik/netdev-2.6.git;a=commit;h=09f75cd7bf13720738e6a196cc0107ce9a5bd5a0
netdev-2.6> scripts/checkpatch.pl 0001-POWERPC-ucc_geth-Fix-build-break-introduced-by-co.patch
Your patch has no obvious style problems and is ready for submission.
drivers/net/ucc_geth.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index d00e7d4..bec413b 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -63,7 +63,7 @@
#define UGETH_MSG_DEFAULT (NETIF_MSG_IFUP << 1 ) - 1
void uec_set_ethtool_ops(struct net_device *netdev);
-
+
static DEFINE_SPINLOCK(ugeth_lock);
static struct {
@@ -3454,9 +3454,12 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
u16 length, howmany = 0;
u32 bd_status;
u8 *bdBuffer;
+ struct net_device * dev;
ugeth_vdbg("%s: IN", __FUNCTION__);
+ dev = ugeth->dev;
+
/* collect received buffers */
bd = ugeth->rxBd[rxQ];
--
1.5.3.GIT
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox