* Re: [PATCH] [SERIAL] qe-uart: add support for Freescale QUICCEngine UART
From: Kumar Gala @ 2008-01-15 14:21 UTC (permalink / raw)
To: Timur Tabi; +Cc: linuxppc-dev, linux-serial
In-Reply-To: <119992170854-git-send-email-timur@freescale.com>
On Jan 9, 2008, at 5:35 PM, Timur Tabi wrote:
> Add file ucc_uart.c, a serial device driver for the Freescale
> QUICCEngine.
> Update the Kconfig and Makefile accordingly.
>
> Signed-off-by: Timur Tabi <timur@freescale.com>
> ---
> drivers/serial/Kconfig | 10 +
> drivers/serial/Makefile | 1 +
> drivers/serial/ucc_uart.c | 1507 ++++++++++++++++++++++++++++++++++++
> +++++++++
> 3 files changed, 1518 insertions(+), 0 deletions(-)
> create mode 100644 drivers/serial/ucc_uart.c
>
>
> diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
> new file mode 100644
> index 0000000..6fe4cfc
> --- /dev/null
> +++ b/drivers/serial/ucc_uart.c
> @@ -0,0 +1,1507 @@
> +/*
> + * Freescale QUICC Engine UART device driver
> + *
> + * Author: Timur Tabi <timur@freescale.com>
> + *
> + * Copyright 2007 Freescale Semiconductor, Inc. This file is
> licensed under
> + * the terms of the GNU General Public License version 2. This
> program
> + * is licensed "as is" without any warranty of any kind, whether
> express
> + * or implied.
> + *
> + * This driver adds support for UART devices via Freescale's QUICC
> Engine
> + * found on some Freescale SOCs.
> + *
> + * If Soft-UART support is needed but not already present, then
> this driver
> + * will request and upload the "Soft-UART" microcode upon probe. The
> + * filename of the microcode should be fsl_qe_ucode_uart_X_YZ.bin,
> where "X"
> + * is the name of the SOC (e.g. 8323), and YZ is the revision of
> the SOC,
> + * (e.g. "11" for 1.1).
> + */
> +
what is the define for? you commented all the others :)
>
> +#define UCC_WAIT_CLOSING 100
> +
> +struct ucc_uart_pram {
> + struct ucc_slow_pram common;
> + u8 res1[8]; /* reserved */
> + __be16 maxidl; /* Maximum idle chars */
> + __be16 idlc; /* temp idle counter */
> + __be16 brkcr; /* Break count register */
> + __be16 parec; /* receive parity error counter */
> + __be16 frmec; /* receive framing error counter */
> + __be16 nosec; /* receive noise counter */
> + __be16 brkec; /* receive break condition counter */
> + __be16 brkln; /* last received break length */
> + __be16 uaddr[2]; /* UART address character 1 & 2 */
> + __be16 rtemp; /* Temp storage */
> + __be16 toseq; /* Transmit out of sequence char */
> + __be16 cchars[8]; /* control characters 1-8 */
> + __be16 rccm; /* receive control character mask */
> + __be16 rccr; /* receive control character register */
> + __be16 rlbc; /* receive last break character */
> + __be16 res2; /* reserved */
> + __be32 res3; /* reserved, should be cleared */
> + u8 res4; /* reserved, should be cleared */
> + u8 res5[3]; /* reserved, should be cleared */
> + __be32 res6; /* reserved, should be cleared */
> + __be32 res7; /* reserved, should be cleared */
> + __be32 res8; /* reserved, should be cleared */
> + __be32 res9; /* reserved, should be cleared */
> + __be32 res10; /* reserved, should be cleared */
> + __be32 res11; /* reserved, should be cleared */
> + __be32 res12; /* reserved, should be cleared */
> + __be32 res13; /* reserved, should be cleared */
> +/* The rest is for Soft-UART only */
> + __be16 supsmr; /* 0x90, Shadow UPSMR */
> + __be16 res92; /* 0x92, reserved, initialize to 0 */
> + __be32 rx_state; /* 0x94, RX state, initialize to 0 */
> + __be32 rx_cnt; /* 0x98, RX count, initialize to 0 */
> + u8 rx_length; /* 0x9C, Char length, set to 1+CL+PEN+1+SL */
> + u8 rx_bitmark; /* 0x9D, reserved, initialize to 0 */
> + u8 rx_temp_dlst_qe; /* 0x9E, reserved, initialize to 0 */
> + u8 res14[0xBC - 0x9F]; /* reserved */
> + __be32 dump_ptr; /* 0xBC, Dump pointer */
> + __be32 rx_frame_rem; /* 0xC0, reserved, initialize to 0 */
> + u8 rx_frame_rem_size; /* 0xC4, reserved, initialize to 0 */
> + u8 tx_mode; /* 0xC5, mode, 0=AHDLC, 1=UART */
> + u16 tx_state; /* 0xC6, TX state */
__be16?
>
> + u8 res15[0xD0 - 0xC8]; /* reserved */
> + __be32 resD0; /* 0xD0, reserved, initialize to 0 */
> + u8 resD4; /* 0xD4, reserved, initialize to 0 */
> + __be16 resD5; /* 0xD5, reserved, initialize to 0 */
> +} __attribute__ ((packed));
> +
>
>
> +/*
> + * Set the modem control lines
> + *
> + * We currently don't support setting modem control lines, but this
> function
> + * needs to exist, otherwise the kernel will panic.
> + */
> +void qe_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
> +{
> +}
What's the issue w/support of this? (maybe a comment related to why
its not supported -- if not here in the git commit message)
> +/*
> + * Enable status change interrupts
> + *
> + * We don't support status change interrupts, but we need to define
> this
> + * function otherwise the kernel will panic.
> + */
> +static void qe_uart_enable_ms(struct uart_port *port)
> +{
same question as above.
- k
^ permalink raw reply
* Re: [PATCH] Fix carry bug in 128-bit unsigned integer adding
From: Kumar Gala @ 2008-01-15 14:37 UTC (permalink / raw)
To: Liu Yu; +Cc: linuxppc-dev
In-Reply-To: <6EBEC19BF4A8F843BCD6B9155BBE2515D1B58B@zch01exm26.fsl.freescale.net>
On Jan 8, 2008, at 9:05 PM, Liu Yu wrote:
>
>>
>> take a look at how include/math-emu/op-4.h implements
>> __FP_FRAC_ADD_4 & __FP_FRAC_SUB_4. Will that fix the bug, if
>> so we should make the code match how its done there.
>>
>> - k
>>
>>
>
> The macro define __FP_FRAC_ADD_4 is below. It can fix the carry bug.
> But still exist a problem that r[0-2] and x[0-2] cannot be referred to
> the same variable.
> If r0 and x0 are the same variable, the comparison ( r0 < x0 ) will
> always fail.
> I don't know whether we need to fix this problem.
Not sure. Probably worth asking this on the glibc list and see if
they have theories. (For the short term I'd say lets use the version
from include/math-emu/op-4.h as a fix. If r0 & x0 can be the same
variable the bug exists in a lot more places (glibc soft-fp and
generic kernel mathemu)
- k
^ permalink raw reply
* Re: psc and spi
From: Grant Likely @ 2008-01-15 14:51 UTC (permalink / raw)
To: S. Fricke; +Cc: linuxppc-dev
In-Reply-To: <20080115135306.GE14333@sfrouter>
On 1/15/08, S. Fricke <silvio.fricke@googlemail.com> wrote:
> Hello friends,
>
> I have on the psc3 the spi-interface of a fpga connected.
>
> psc3-0 - MOSI
> psc3-1 - MISO
> psc3-2 - CLK
> psc3-3 - SlaveSelect
> psc3-4 - CS-FPGA
> psc3-5 - CS Another device
> psc3-6 - SPI-SEL0
> psc3-7 - SPI-SEL1
> psc3-8/9 - Not connected
>
> Can I use the mpc52xx_psc_spi-driver? And if yes, how I have to use this
> driver? Or must I write a own spi-master/slave thing? Can anyone point me
> to a good start-position?
Yes, you should be able to use the mpc52xx_psc_spi driver. You'' need
to add the activate_cs and deactivate_cs hooks in your platform code
to activate your SPI CS lines. You'll also need to set port_config to
have the PSC3 pins in "CODEC3" mode.
Cheers,
g.
>
> Best regards,
> Silvio Fricke
>
> --
> -- S. Fricke ----------------------------- MAILTO:silvio.fricke@gmail.com --
> Diplom-Informatiker (FH)
> Linux-Entwicklung
> ----------------------------------------------------------------------------
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
>
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* problem with CF
From: raul.moreno @ 2008-01-15 14:49 UTC (permalink / raw)
To: linuxppc-embedded
Hi,
I am trying to use a compact Flash (CF) throu PCMCIA. So I selected the=
CONFIG_BLK_DEV_IDECS and CONFIG_PCMCIA_M8XX kernel options, but not the=
CONFIG_BLK_DEV_MPC8xx_IDE one.
The problem occurs when I insert the CF, because the ide_config fails:=
ide-cs: ide_register() 0x 0 & 0x e, irq 7 failed
I think the issue is in the idecs_register function that always returns=
-1.
I guess the problem is the two first parameter of this function (io_bas=
e
and ctl_base are 0x0 and 0xe respectively), but I don't know if it must=
be
so or what values they must have.
I am using a MPC866 with a linux kernel 2.6.22.
I would thank some help.
Ra=FAl Moreno=
^ permalink raw reply
* Re: [PATCH] [SERIAL] qe-uart: add support for Freescale QUICCEngine UART
From: Timur Tabi @ 2008-01-15 15:03 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, linux-serial
In-Reply-To: <1CFD37C9-F06C-4C7E-836D-31C94EF464DF@kernel.crashing.org>
Kumar Gala wrote:
> what is the define for? you commented all the others :)
I thought you said there were no more issues? :-)
>> +#define UCC_WAIT_CLOSING 100
This is how long to wait after receiving a close request for characters to be
sent out before actually closing the device. I just used the same value as the
CPM serial driver.
>> + u16 tx_state; /* 0xC6, TX state */
>
> __be16?
Oops.
>> +/*
>> + * Set the modem control lines
>> + *
>> + * We currently don't support setting modem control lines, but this
>> function
>> + * needs to exist, otherwise the kernel will panic.
>> + */
>> +void qe_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
>> +{
>> +}
>
> What's the issue w/support of this? (maybe a comment related to why its
> not supported -- if not here in the git commit message)
I didn't want to add any serial functionality that wasn't in the CPM serial
driver, mostly because I don't really understand the technical details of serial
communication at this level. I figured if it's okay for the CPM driver not to
handle modem control, then the QE driver doesn't have to do it either.
>> +static void qe_uart_enable_ms(struct uart_port *port)
>> +{
>
> same question as above.
Same answer!
I suppose you want me to post another version of this patch?
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* Re: [PATCH] [POWERPC] Add of_find_matching_node() helper function
From: Grant Likely @ 2008-01-15 15:09 UTC (permalink / raw)
To: linuxppc-dev, Paul Mackerras, Benjamin Herrenschmidt,
Stephen Rothwell
In-Reply-To: <20080108192040.9556.28899.stgit@trillian.secretlab.ca>
Ben, Paul, Stephen,
Any comments/concerns on this patch? I've got a series of patches
which I haven't published yet as they depend on this one. If this
patch doesn't go in then I need to rework the series, in which case
I'd like to know sooner rather than later so that I've got time for
the rework..
Paul, if everyone is okay with this one, can you please pick it up
into your 2.6.25 branch? Or if you prefer, I can add it to the front
of my 5200 patch series so that it is part of my next pull request.
Thanks,
g.
On 1/8/08, Grant Likely <grant.likely@secretlab.ca> wrote:
> From: Grant Likely <grant.likely@secretlab.ca>
>
> Similar to of_find_compatible_node(), of_find_matching_node() and
> for_each_matching_node() allow you to iterate over the device tree
> looking for specific nodes except that it accepts a of_device_id
> table instead of strings.
>
> This patch also moves of_match_node() from driver/of/device.c to
> driver/of/base.c to colocate it with the of_find_matching_node which
> depends on it.
>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
>
> arch/powerpc/kernel/ibmebus.c | 1
> arch/powerpc/kernel/of_platform.c | 1
> arch/powerpc/platforms/celleb/io-workarounds.c | 1
> arch/powerpc/platforms/celleb/pci.c | 1
> drivers/net/ibm_newemac/core.c | 1
> drivers/of/base.c | 58 ++++++++++++++++++++++++
> drivers/of/device.c | 29 ------------
> drivers/serial/mpc52xx_uart.c | 3 +
> include/linux/of.h | 8 +++
> include/linux/of_device.h | 2 -
> 10 files changed, 73 insertions(+), 32 deletions(-)
>
> diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
> index caae49f..3b70844 100644
> --- a/arch/powerpc/kernel/ibmebus.c
> +++ b/arch/powerpc/kernel/ibmebus.c
> @@ -41,6 +41,7 @@
> #include <linux/kobject.h>
> #include <linux/dma-mapping.h>
> #include <linux/interrupt.h>
> +#include <linux/of.h>
> #include <linux/of_platform.h>
> #include <asm/ibmebus.h>
> #include <asm/abs_addr.h>
> diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
> index de36e23..7a3cafb 100644
> --- a/arch/powerpc/kernel/of_platform.c
> +++ b/arch/powerpc/kernel/of_platform.c
> @@ -19,6 +19,7 @@
> #include <linux/mod_devicetable.h>
> #include <linux/slab.h>
> #include <linux/pci.h>
> +#include <linux/of.h>
> #include <linux/of_device.h>
> #include <linux/of_platform.h>
>
> diff --git a/arch/powerpc/platforms/celleb/io-workarounds.c b/arch/powerpc/platforms/celleb/io-workarounds.c
> index b939c0e..423339b 100644
> --- a/arch/powerpc/platforms/celleb/io-workarounds.c
> +++ b/arch/powerpc/platforms/celleb/io-workarounds.c
> @@ -22,6 +22,7 @@
>
> #undef DEBUG
>
> +#include <linux/of.h>
> #include <linux/of_device.h>
> #include <linux/irq.h>
>
> diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c
> index 5d399e0..51b390d 100644
> --- a/arch/powerpc/platforms/celleb/pci.c
> +++ b/arch/powerpc/platforms/celleb/pci.c
> @@ -31,6 +31,7 @@
> #include <linux/init.h>
> #include <linux/bootmem.h>
> #include <linux/pci_regs.h>
> +#include <linux/of.h>
> #include <linux/of_device.h>
>
> #include <asm/io.h>
> diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
> index cb06280..fced441 100644
> --- a/drivers/net/ibm_newemac/core.c
> +++ b/drivers/net/ibm_newemac/core.c
> @@ -37,6 +37,7 @@
> #include <linux/mii.h>
> #include <linux/bitops.h>
> #include <linux/workqueue.h>
> +#include <linux/of.h>
>
> #include <asm/processor.h>
> #include <asm/io.h>
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 9377f3b..b306fef 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -273,3 +273,61 @@ struct device_node *of_find_compatible_node(struct device_node *from,
> return np;
> }
> EXPORT_SYMBOL(of_find_compatible_node);
> +
> +/**
> + * of_match_node - Tell if an device_node has a matching of_match structure
> + * @matches: array of of device match structures to search in
> + * @node: the of device structure to match against
> + *
> + * Low level utility function used by device matching.
> + */
> +const struct of_device_id *of_match_node(const struct of_device_id *matches,
> + const struct device_node *node)
> +{
> + while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
> + int match = 1;
> + if (matches->name[0])
> + match &= node->name
> + && !strcmp(matches->name, node->name);
> + if (matches->type[0])
> + match &= node->type
> + && !strcmp(matches->type, node->type);
> + if (matches->compatible[0])
> + match &= of_device_is_compatible(node,
> + matches->compatible);
> + if (match)
> + return matches;
> + matches++;
> + }
> + return NULL;
> +}
> +EXPORT_SYMBOL(of_match_node);
> +
> +/**
> + * of_find_matching_node - Find a node based on an of_device_id match
> + * table.
> + * @from: The node to start searching from or NULL, the node
> + * you pass will not be searched, only the next one
> + * will; typically, you pass what the previous call
> + * returned. of_node_put() will be called on it
> + * @matches: array of of device match structures to search in
> + *
> + * Returns a node pointer with refcount incremented, use
> + * of_node_put() on it when done.
> + */
> +struct device_node *of_find_matching_node(struct device_node *from,
> + const struct of_device_id *matches)
> +{
> + struct device_node *np;
> +
> + read_lock(&devtree_lock);
> + np = from ? from->allnext : allnodes;
> + for (; np; np = np->allnext) {
> + if (of_match_node(matches, np) && of_node_get(np))
> + break;
> + }
> + of_node_put(from);
> + read_unlock(&devtree_lock);
> + return np;
> +}
> +EXPORT_SYMBOL(of_find_matching_node);
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index 6245f06..29681c4 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -10,35 +10,6 @@
> #include <asm/errno.h>
>
> /**
> - * of_match_node - Tell if an device_node has a matching of_match structure
> - * @ids: array of of device match structures to search in
> - * @node: the of device structure to match against
> - *
> - * Low level utility function used by device matching.
> - */
> -const struct of_device_id *of_match_node(const struct of_device_id *matches,
> - const struct device_node *node)
> -{
> - while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
> - int match = 1;
> - if (matches->name[0])
> - match &= node->name
> - && !strcmp(matches->name, node->name);
> - if (matches->type[0])
> - match &= node->type
> - && !strcmp(matches->type, node->type);
> - if (matches->compatible[0])
> - match &= of_device_is_compatible(node,
> - matches->compatible);
> - if (match)
> - return matches;
> - matches++;
> - }
> - return NULL;
> -}
> -EXPORT_SYMBOL(of_match_node);
> -
> -/**
> * of_match_device - Tell if an of_device structure has a matching
> * of_match structure
> * @ids: array of of device match structures to search in
> diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
> index ec36ad7..7e3ba8b 100644
> --- a/drivers/serial/mpc52xx_uart.c
> +++ b/drivers/serial/mpc52xx_uart.c
> @@ -72,7 +72,8 @@
> #include <asm/io.h>
>
> #if defined(CONFIG_PPC_MERGE)
> -#include <asm/of_platform.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> #else
> #include <linux/platform_device.h>
> #endif
> diff --git a/include/linux/of.h b/include/linux/of.h
> index c65af7b..b5f33ef 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -17,6 +17,7 @@
> */
> #include <linux/types.h>
> #include <linux/bitops.h>
> +#include <linux/mod_devicetable.h>
>
> #include <asm/prom.h>
>
> @@ -41,6 +42,11 @@ extern struct device_node *of_find_compatible_node(struct device_node *from,
> #define for_each_compatible_node(dn, type, compatible) \
> for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
> dn = of_find_compatible_node(dn, type, compatible))
> +extern struct device_node *of_find_matching_node(struct device_node *from,
> + const struct of_device_id *matches);
> +#define for_each_matching_node(dn, matches) \
> + for (dn = of_find_matching_node(NULL, matches); dn; \
> + dn = of_find_matching_node(dn, matches))
> extern struct device_node *of_find_node_by_path(const char *path);
> extern struct device_node *of_find_node_by_phandle(phandle handle);
> extern struct device_node *of_get_parent(const struct device_node *node);
> @@ -60,5 +66,7 @@ extern const void *of_get_property(const struct device_node *node,
> int *lenp);
> extern int of_n_addr_cells(struct device_node *np);
> extern int of_n_size_cells(struct device_node *np);
> +extern const struct of_device_id *of_match_node(
> + const struct of_device_id *matches, const struct device_node *node);
>
> #endif /* _LINUX_OF_H */
> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
> index 212bffb..6dc1195 100644
> --- a/include/linux/of_device.h
> +++ b/include/linux/of_device.h
> @@ -10,8 +10,6 @@
>
> #define to_of_device(d) container_of(d, struct of_device, dev)
>
> -extern const struct of_device_id *of_match_node(
> - const struct of_device_id *matches, const struct device_node *node);
> extern const struct of_device_id *of_match_device(
> const struct of_device_id *matches, const struct of_device *dev);
>
>
>
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* crash in kmem_cache_init
From: Olaf Hering @ 2008-01-15 15:09 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev
Current linus tree crashes in kmem_cache_init, as shown below. The
system is a 8cpu 2.2GHz POWER5 system, model 9117-570, with 4GB ram.
Firmware is 240_332, 2.6.23 boots ok with the same config.
There is a series of mm related patches in 2.6.24-rc1:
commit 04231b3002ac53f8a64a7bd142fde3fa4b6808c6 seems to break it,
==> .git/BISECT_LOG <==
git-bisect start
# good: [0b8bc8b91cf6befea20fe78b90367ca7b61cfa0d] Linux 2.6.23
git-bisect good 0b8bc8b91cf6befea20fe78b90367ca7b61cfa0d
# bad: [cebdeed27b068dcc3e7c311d7ec0d9c33b5138c2] Linux 2.6.24-rc1
git-bisect bad cebdeed27b068dcc3e7c311d7ec0d9c33b5138c2
# good: [9ac52315d4cf5f561f36dabaf0720c00d3553162] sched: guest CPU accounting: add guest-CPU /proc/<pid>/stat fields
git-bisect good 9ac52315d4cf5f561f36dabaf0720c00d3553162
# bad: [b9ec0339d8e22cadf2d9d1b010b51dc53837dfb0] add consts where appropriate in fs/nls/Kconfig fs/nls/Makefile fs/nls/nls_ascii.c fs/nls/nls_base.c fs/nls/nls_cp1250.c fs/nls/nls_cp1251.c fs/nls/nls_cp1255.c fs/nls/nls_cp437.c fs/nls/nls_cp737.c fs/nls/nls_cp775.c fs/nls/nls_cp850.c fs/nls/nls_cp852.c fs/nls/nls_cp855.c fs/nls/nls_cp857.c fs/nls/nls_cp860.c fs/nls/nls_cp861.c fs/nls/nls_cp862.c fs/nls/nls_cp863.c fs/nls/nls_cp864.c fs/nls/nls_cp865.c fs/nls/nls_cp866.c fs/nls/nls_cp869.c fs/nls/nls_cp874.c fs/nls/nls_cp932.c fs/nls/nls_cp936.c fs/nls/nls_cp949.c fs/nls/nls_cp950.c fs/nls/nls_euc-jp.c fs/nls/nls_iso8859-1.c fs/nls/nls_iso8859-13.c fs/nls/nls_iso8859-14.c fs/nls/nls_iso8859-15.c fs/nls/nls_iso8859-2.c fs/nls/nls_iso8859-3.c fs/nls/nls_iso8859-4.c fs/nls/nls_iso8859-5.c fs/nls/nls_iso8859-6.c fs/nls/nls_iso8859-7.c fs/nls/nls_iso8859-9.c fs/nls/nls_koi8-r.c fs/nls/nls_koi8-ru.c fs/nls/nls_koi8-u.c fs/nls/nls_utf8.c
git-bisect bad b9ec0339d8e22cadf2d9d1b010b51dc53837dfb0
# bad: [78a26e25ce4837a03ac3b6c32cdae1958e547639] uml: separate timer initialization
git-bisect bad 78a26e25ce4837a03ac3b6c32cdae1958e547639
# good: [4acad72ded8e3f0211bd2a762e23c28229c61a51] [IPV6]: Consolidate the ip6_pol_route_(input|output) pair
git-bisect good 4acad72ded8e3f0211bd2a762e23c28229c61a51
# good: [64da82efae0d7b5f7c478021840fd329f76d965d] Add support for PCMCIA card Sierra WIreless AC850
git-bisect good 64da82efae0d7b5f7c478021840fd329f76d965d
# bad: [37b07e4163f7306aa735a6e250e8d22293e5b8de] memoryless nodes: fixup uses of node_online_map in generic code
git-bisect bad 37b07e4163f7306aa735a6e250e8d22293e5b8de
# good: [64649a58919e66ec21792dbb6c48cb3da22cbd7f] mm: trim more holes
git-bisect good 64649a58919e66ec21792dbb6c48cb3da22cbd7f
# good: [fb53b3094888be0cf8ddf052277654268904bdf5] smbfs: convert to new aops
git-bisect good fb53b3094888be0cf8ddf052277654268904bdf5
# good: [13808910713a98cc1159291e62cdfec92cc94d05] Memoryless nodes: Generic management of nodemasks for various purposes
.............
Please wait, loading kernel...
Allocated 00a00000 bytes for kernel @ 00200000
Elf64 kernel loaded...
OF stdout device is: /vdevice/vty@30000000
Hypertas detected, assuming LPAR !
command line: panic=1 debug xmon=on
memory layout at init:
alloc_bottom : 0000000000ac1000
alloc_top : 0000000010000000
alloc_top_hi : 00000000da000000
rmo_top : 0000000010000000
ram_top : 00000000da000000
Looking for displays
found display : /pci@800000020000002/pci@2/pci@1/display@0, opening ... done
instantiating rtas at 0x000000000f6a1000 ... done
0000000000000000 : boot cpu 0000000000000000
0000000000000002 : starting cpu hw idx 0000000000000002... done
0000000000000004 : starting cpu hw idx 0000000000000004... done
0000000000000006 : starting cpu hw idx 0000000000000006... done
copying OF device tree ...
Building dt strings...
Building dt structure...
Device tree strings 0x0000000000cc2000 -> 0x0000000000cc34e4
Device tree struct 0x0000000000cc4000 -> 0x0000000000cd6000
Calling quiesce ...
returning from prom_init
Partition configured for 8 cpus.
Starting Linux PPC64 #2 SMP Tue Jan 15 14:23:02 CET 2008
-----------------------------------------------------
ppc64_pft_size = 0x1c
physicalMemorySize = 0xda000000
htab_hash_mask = 0x1fffff
-----------------------------------------------------
Linux version 2.6.24-rc7-ppc64 (olaf@lingonberry) (gcc version 4.1.2 20070115 (prerelease) (SUSE Linux)) #2 SMP Tue Jan 15 14:23:02 CET 2008
[boot]0012 Setup Arch
EEH: PCI Enhanced I/O Error Handling Enabled
PPC64 nvram contains 8192 bytes
Zone PFN ranges:
DMA 0 -> 892928
Normal 892928 -> 892928
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
1: 0 -> 892928
Could not find start_pfn for node 0
[boot]0015 Setup Done
Built 2 zonelists in Node order, mobility grouping on. Total pages: 880720
Policy zone: DMA
Kernel command line: panic=1 debug xmon=on
[boot]0020 XICS Init
xics: no ISA interrupt controller
[boot]0021 XICS Done
PID hash table entries: 4096 (order: 12, 32768 bytes)
time_init: decrementer frequency = 275.070000 MHz
time_init: processor frequency = 2197.800000 MHz
clocksource: timebase mult[e8ab05] shift[22] registered
clockevent: decrementer mult[466a] shift[16] cpu[0]
Console: colour dummy device 80x25
console handover: boot [udbg-1] -> real [hvc0]
Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes)
Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes)
freeing bootmem node 1
Memory: 3496632k/3571712k available (6188k kernel code, 75080k reserved, 1324k data, 1220k bss, 304k init)
Unable to handle kernel paging request for data at address 0x00000040
Faulting instruction address: 0xc000000000437470
cpu 0x0: Vector: 300 (Data Access) at [c00000000075b830]
pc: c000000000437470: ._spin_lock+0x20/0x88
lr: c0000000000f78a8: .cache_grow+0x7c/0x338
sp: c00000000075bab0
msr: 8000000000009032
dar: 40
dsisr: 40000000
current = 0xc000000000665a50
paca = 0xc000000000666380
pid = 0, comm = swapper
enter ? for help
[c00000000075bb30] c0000000000f78a8 .cache_grow+0x7c/0x338
[c00000000075bbf0] c0000000000f7d04 .fallback_alloc+0x1a0/0x1f4
[c00000000075bca0] c0000000000f8544 .kmem_cache_alloc+0xec/0x150
[c00000000075bd40] c0000000000fb1c0 .kmem_cache_create+0x208/0x478
[c00000000075be20] c0000000005e670c .kmem_cache_init+0x218/0x4f4
[c00000000075bee0] c0000000005bf8ec .start_kernel+0x2f8/0x3fc
[c00000000075bf90] c000000000008590 .start_here_common+0x60/0xd0
0:mon>
^ permalink raw reply
* Re: [PATCH] [SERIAL] qe-uart: add support for Freescale QUICCEngine UART
From: Kumar Gala @ 2008-01-15 15:13 UTC (permalink / raw)
To: Timur Tabi; +Cc: linuxppc-dev, linux-serial
In-Reply-To: <478CCB44.3000805@freescale.com>
On Jan 15, 2008, at 9:03 AM, Timur Tabi wrote:
> Kumar Gala wrote:
>
>> what is the define for? you commented all the others :)
>
> I thought you said there were no more issues? :-)
I lied, get use to it ;)
(I was going to apply the patch and thus scanned over it).
>
>
>>> +#define UCC_WAIT_CLOSING 100
>
> This is how long to wait after receiving a close request for
> characters to be sent out before actually closing the device. I
> just used the same value as the CPM serial driver.
Yeah, I just meant a comment to this fact would be nice.
>
>
>
>>> + u16 tx_state; /* 0xC6, TX state */
>> __be16?
>
> Oops.
>
>>> +/*
>>> + * Set the modem control lines
>>> + *
>>> + * We currently don't support setting modem control lines, but
>>> this function
>>> + * needs to exist, otherwise the kernel will panic.
>>> + */
>>> +void qe_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
>>> +{
>>> +}
>> What's the issue w/support of this? (maybe a comment related to
>> why its not supported -- if not here in the git commit message)
>
> I didn't want to add any serial functionality that wasn't in the CPM
> serial driver, mostly because I don't really understand the
> technical details of serial communication at this level. I figured
> if it's okay for the CPM driver not to handle modem control, then
> the QE driver doesn't have to do it either.
This is fine, can we make it clear that we aren't implementing them
because we didn't need them not because of some board issue. (Looking
at the 8250.c driver it looks like this has to do with CTS support --
which the QE UCC supports, we just aren't using).
>>> +static void qe_uart_enable_ms(struct uart_port *port)
>>> +{
>> same question as above.
>
> Same answer!
>
> I suppose you want me to post another version of this patch?
yes.
- k
^ permalink raw reply
* [PATCH] [POWERPC] bootwrapper: Add find_node_by_alias and dt_fixup_mac_address_by_alias
From: Kumar Gala @ 2008-01-15 15:35 UTC (permalink / raw)
To: linuxppc-dev
Add the ability to set the mac address given the alias for the device.
Removes the need for having a linux,network-index property.
---
in my git tree.
arch/powerpc/boot/devtree.c | 14 ++++++++++++++
arch/powerpc/boot/ops.h | 14 ++++++++++++++
2 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c
index e5dfe44..60f561e 100644
--- a/arch/powerpc/boot/devtree.c
+++ b/arch/powerpc/boot/devtree.c
@@ -88,6 +88,20 @@ void dt_fixup_clock(const char *path, u32 freq)
}
}
+void dt_fixup_mac_address_by_alias(const char *alias, const u8 *addr)
+{
+ void *devp = find_node_by_alias(alias);
+
+ if (devp) {
+ printf("%s: local-mac-address <-"
+ " %02x:%02x:%02x:%02x:%02x:%02x\n\r", alias,
+ addr[0], addr[1], addr[2],
+ addr[3], addr[4], addr[5]);
+
+ setprop(devp, "local-mac-address", addr, 6);
+ }
+}
+
void dt_fixup_mac_address(u32 index, const u8 *addr)
{
void *devp = find_node_by_prop_value(NULL, "linux,network-index",
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index 6036a98..5872ef1 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -159,9 +159,23 @@ static inline void *find_node_by_devtype(const void *prev,
return find_node_by_prop_value_str(prev, "device_type", type);
}
+static inline void *find_node_by_alias(const char *alias)
+{
+ void *devp = finddevice("/aliases");
+
+ if (devp) {
+ char path[MAX_PATH_LEN];
+ if (getprop(devp, alias, path, MAX_PATH_LEN) > 0)
+ return finddevice(path);
+ }
+
+ return NULL;
+}
+
void dt_fixup_memory(u64 start, u64 size);
void dt_fixup_cpu_clocks(u32 cpufreq, u32 tbfreq, u32 busfreq);
void dt_fixup_clock(const char *path, u32 freq);
+void dt_fixup_mac_address_by_alias(const char *alias, const u8 *addr);
void dt_fixup_mac_address(u32 index, const u8 *addr);
void __dt_fixup_mac_addresses(u32 startindex, ...);
#define dt_fixup_mac_addresses(...) \
--
1.5.3.7
^ permalink raw reply related
* [PATCH] [POWERPC] bootwrapper: convert cuboot-8{3,5}xx to dt_fixup_mac_address_by_alias
From: Kumar Gala @ 2008-01-15 15:36 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Scott Wood
---
in my git tree.
arch/powerpc/boot/cuboot-83xx.c | 3 ++-
arch/powerpc/boot/cuboot-85xx.c | 5 +++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/boot/cuboot-83xx.c b/arch/powerpc/boot/cuboot-83xx.c
index acd860e..61af1c1 100644
--- a/arch/powerpc/boot/cuboot-83xx.c
+++ b/arch/powerpc/boot/cuboot-83xx.c
@@ -24,7 +24,8 @@ static void platform_fixups(void)
void *soc;
dt_fixup_memory(bd.bi_memstart, bd.bi_memsize);
- dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr);
+ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
+ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 4, bd.bi_busfreq);
/* Unfortunately, the specific model number is encoded in the
diff --git a/arch/powerpc/boot/cuboot-85xx.c b/arch/powerpc/boot/cuboot-85xx.c
index 943779e..6776a1a 100644
--- a/arch/powerpc/boot/cuboot-85xx.c
+++ b/arch/powerpc/boot/cuboot-85xx.c
@@ -24,8 +24,9 @@ static void platform_fixups(void)
void *soc;
dt_fixup_memory(bd.bi_memstart, bd.bi_memsize);
- dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr,
- bd.bi_enet2addr);
+ dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
+ dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr);
+ dt_fixup_mac_address_by_alias("ethernet2", bd.bi_enet2addr);
dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 8, bd.bi_busfreq);
/* Unfortunately, the specific model number is encoded in the
--
1.5.3.7
^ permalink raw reply related
* [PATCH] [POWERPC] 85xx: convert boards to use machine_device_initcall
From: Kumar Gala @ 2008-01-15 15:48 UTC (permalink / raw)
To: linuxppc-dev
---
arch/powerpc/platforms/85xx/mpc85xx_ads.c | 6 ++----
arch/powerpc/platforms/85xx/mpc85xx_cds.c | 6 +-----
arch/powerpc/platforms/85xx/mpc85xx_mds.c | 7 ++-----
3 files changed, 5 insertions(+), 14 deletions(-)
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index bccdc25..eb0a46b 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -233,13 +233,11 @@ static struct of_device_id __initdata of_bus_ids[] = {
static int __init declare_of_platform_devices(void)
{
- if (!machine_is(mpc85xx_ads))
- return 0;
-
of_platform_bus_probe(NULL, of_bus_ids, NULL);
+
return 0;
}
-device_initcall(declare_of_platform_devices);
+machine_device_initcall(mpc85xx_ads, declare_of_platform_devices);
/*
* Called very early, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 4d063ee..8b1de78 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -222,9 +222,6 @@ static int mpc85xx_cds_8259_attach(void)
struct device_node *cascade_node = NULL;
int cascade_irq;
- if (!machine_is(mpc85xx_cds))
- return 0;
-
/* Initialize the i8259 controller */
for_each_node_by_type(np, "interrupt-controller")
if (of_device_is_compatible(np, "chrp,iic")) {
@@ -262,8 +259,7 @@ static int mpc85xx_cds_8259_attach(void)
return 0;
}
-
-device_initcall(mpc85xx_cds_8259_attach);
+machine_device_initcall(mpc85xx_cds, mpc85xx_cds_8259_attach);
#endif /* CONFIG_PPC_I8259 */
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index e6c63a5..4fdf5ab 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -144,15 +144,12 @@ static struct of_device_id mpc85xx_ids[] = {
static int __init mpc85xx_publish_devices(void)
{
- if (!machine_is(mpc85xx_mds))
- return 0;
-
/* Publish the QE devices */
- of_platform_bus_probe(NULL,mpc85xx_ids,NULL);
+ of_platform_bus_probe(NULL, mpc85xx_ids, NULL);
return 0;
}
-device_initcall(mpc85xx_publish_devices);
+machine_device_initcall(mpc85xx_mds, mpc85xx_publish_devices);
static void __init mpc85xx_mds_pic_init(void)
{
--
1.5.3.7
^ permalink raw reply related
* [PATCH] [POWERPC] 83xx: convert boards to use machine_device_initcall
From: Kumar Gala @ 2008-01-15 15:48 UTC (permalink / raw)
To: linuxppc-dev
---
arch/powerpc/platforms/83xx/mpc832x_mds.c | 5 +----
arch/powerpc/platforms/83xx/mpc832x_rdb.c | 10 ++--------
arch/powerpc/platforms/83xx/mpc834x_mds.c | 5 +----
arch/powerpc/platforms/83xx/mpc836x_mds.c | 5 +----
arch/powerpc/platforms/83xx/mpc837x_mds.c | 5 +----
5 files changed, 6 insertions(+), 24 deletions(-)
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 1e570bb..dbdd4ad 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -110,15 +110,12 @@ static struct of_device_id mpc832x_ids[] = {
static int __init mpc832x_declare_of_platform_devices(void)
{
- if (!machine_is(mpc832x_mds))
- return 0;
-
/* Publish the QE devices */
of_platform_bus_probe(NULL, mpc832x_ids, NULL);
return 0;
}
-device_initcall(mpc832x_declare_of_platform_devices);
+machine_device_initcall(mpc832x_mds, mpc832x_declare_of_platform_devices);
static void __init mpc832x_sys_init_IRQ(void)
{
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index ffb2e93..5fddd22 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -63,9 +63,6 @@ static struct spi_board_info mpc832x_spi_boardinfo = {
static int __init mpc832x_spi_init(void)
{
- if (!machine_is(mpc832x_rdb))
- return 0;
-
par_io_config_pin(3, 0, 3, 0, 1, 0); /* SPI1 MOSI, I/O */
par_io_config_pin(3, 1, 3, 0, 1, 0); /* SPI1 MISO, I/O */
par_io_config_pin(3, 2, 3, 0, 1, 0); /* SPI1 CLK, I/O */
@@ -80,7 +77,7 @@ static int __init mpc832x_spi_init(void)
mpc83xx_spi_deactivate_cs);
}
-device_initcall(mpc832x_spi_init);
+machine_device_initcall(mpc832x_rdb, mpc832x_spi_init);
/* ************************************************************************
*
@@ -123,15 +120,12 @@ static struct of_device_id mpc832x_ids[] = {
static int __init mpc832x_declare_of_platform_devices(void)
{
- if (!machine_is(mpc832x_rdb))
- return 0;
-
/* Publish the QE devices */
of_platform_bus_probe(NULL, mpc832x_ids, NULL);
return 0;
}
-device_initcall(mpc832x_declare_of_platform_devices);
+machine_device_initcall(mpc832x_rdb, mpc832x_declare_of_platform_devices);
void __init mpc832x_rdb_init_IRQ(void)
{
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index 459fb72..2b8a0a3 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -115,13 +115,10 @@ static struct of_device_id mpc834x_ids[] = {
static int __init mpc834x_declare_of_platform_devices(void)
{
- if (!machine_is(mpc834x_mds))
- return 0;
-
of_platform_bus_probe(NULL, mpc834x_ids, NULL);
return 0;
}
-device_initcall(mpc834x_declare_of_platform_devices);
+machine_device_initcall(mpc834x_mds, mpc834x_declare_of_platform_devices);
/*
* Called very early, MMU is off, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index 2ac9890..db491ec 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -141,15 +141,12 @@ static struct of_device_id mpc836x_ids[] = {
static int __init mpc836x_declare_of_platform_devices(void)
{
- if (!machine_is(mpc836x_mds))
- return 0;
-
/* Publish the QE devices */
of_platform_bus_probe(NULL, mpc836x_ids, NULL);
return 0;
}
-device_initcall(mpc836x_declare_of_platform_devices);
+machine_device_initcall(mpc836x_mds, mpc836x_declare_of_platform_devices);
static void __init mpc836x_mds_init_IRQ(void)
{
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
index 9cdc32b..cfd0548 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
@@ -50,15 +50,12 @@ static struct of_device_id mpc837x_ids[] = {
static int __init mpc837x_declare_of_platform_devices(void)
{
- if (!machine_is(mpc837x_mds))
- return 0;
-
/* Publish of_device */
of_platform_bus_probe(NULL, mpc837x_ids, NULL);
return 0;
}
-device_initcall(mpc837x_declare_of_platform_devices);
+machine_device_initcall(mpc837x_mds, mpc837x_declare_of_platform_devices);
static void __init mpc837x_mds_init_IRQ(void)
{
--
1.5.3.7
^ permalink raw reply related
* [PATCH v2] [SERIAL] qe-uart: add support for Freescale QUICCEngine UART
From: Timur Tabi @ 2008-01-15 15:56 UTC (permalink / raw)
To: galak, linuxppc-dev, linux-serial; +Cc: Timur Tabi
Add file ucc_uart.c, a serial device driver for the Freescale QUICCEngine.
Update the Kconfig and Makefile accordingly.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
Updated to reflect comments from Kumar.
drivers/serial/Kconfig | 10 +
drivers/serial/Makefile | 1 +
drivers/serial/ucc_uart.c | 1514 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 1525 insertions(+), 0 deletions(-)
create mode 100644 drivers/serial/ucc_uart.c
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index d7e1996..d962b74 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1284,4 +1284,14 @@ config SERIAL_OF_PLATFORM
Currently, only 8250 compatible ports are supported, but
others can easily be added.
+config SERIAL_QE
+ tristate "Freescale QUICC Engine serial port support"
+ depends on QUICC_ENGINE
+ select SERIAL_CORE
+ select FW_LOADER
+ default n
+ help
+ This driver supports the QE serial ports on Freescale embedded
+ PowerPC that contain a QUICC Engine.
+
endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index af6377d..7eb4553 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -64,3 +64,4 @@ obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
+obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
new file mode 100644
index 0000000..e0994f0
--- /dev/null
+++ b/drivers/serial/ucc_uart.c
@@ -0,0 +1,1514 @@
+/*
+ * Freescale QUICC Engine UART device driver
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2007 Freescale Semiconductor, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * This driver adds support for UART devices via Freescale's QUICC Engine
+ * found on some Freescale SOCs.
+ *
+ * If Soft-UART support is needed but not already present, then this driver
+ * will request and upload the "Soft-UART" microcode upon probe. The
+ * filename of the microcode should be fsl_qe_ucode_uart_X_YZ.bin, where "X"
+ * is the name of the SOC (e.g. 8323), and YZ is the revision of the SOC,
+ * (e.g. "11" for 1.1).
+ */
+
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/fs_uart_pd.h>
+#include <asm/ucc_slow.h>
+
+#include <linux/firmware.h>
+#include <asm/reg.h>
+
+/*
+ * The GUMR flag for Soft UART. This would normally be defined in qe.h,
+ * but Soft-UART is a hack and we want to keep everything related to it in
+ * this file.
+ */
+#define UCC_SLOW_GUMR_H_SUART 0x00004000 /* Soft-UART */
+
+/*
+ * soft_uart is 1 if we need to use Soft-UART mode
+ */
+static int soft_uart;
+/*
+ * firmware_loaded is 1 if the firmware has been loaded, 0 otherwise.
+ */
+static int firmware_loaded;
+
+/* Enable this macro to configure all serial ports in internal loopback
+ mode */
+/* #define LOOPBACK */
+
+/* The major and minor device numbers are defined in
+ * http://www.lanana.org/docs/device-list/devices-2.6+.txt. For the QE
+ * UART, we have major number 204 and minor numbers 46 - 49, which are the
+ * same as for the CPM2. This decision was made because no Freescale part
+ * has both a CPM and a QE.
+ */
+#define SERIAL_QE_MAJOR 204
+#define SERIAL_QE_MINOR 46
+
+/* Since we only have minor numbers 46 - 49, there is a hard limit of 4 ports */
+#define UCC_MAX_UART 4
+
+/* The number of buffer descriptors for receiving characters. */
+#define RX_NUM_FIFO 4
+
+/* The number of buffer descriptors for transmitting characters. */
+#define TX_NUM_FIFO 4
+
+/* The maximum size of the character buffer for a single RX BD. */
+#define RX_BUF_SIZE 32
+
+/* The maximum size of the character buffer for a single TX BD. */
+#define TX_BUF_SIZE 32
+
+/*
+ * The number of jiffies to wait after receiving a close command before the
+ * device is actually closed. This allows the last few characters to be
+ * sent over the wire.
+ */
+#define UCC_WAIT_CLOSING 100
+
+struct ucc_uart_pram {
+ struct ucc_slow_pram common;
+ u8 res1[8]; /* reserved */
+ __be16 maxidl; /* Maximum idle chars */
+ __be16 idlc; /* temp idle counter */
+ __be16 brkcr; /* Break count register */
+ __be16 parec; /* receive parity error counter */
+ __be16 frmec; /* receive framing error counter */
+ __be16 nosec; /* receive noise counter */
+ __be16 brkec; /* receive break condition counter */
+ __be16 brkln; /* last received break length */
+ __be16 uaddr[2]; /* UART address character 1 & 2 */
+ __be16 rtemp; /* Temp storage */
+ __be16 toseq; /* Transmit out of sequence char */
+ __be16 cchars[8]; /* control characters 1-8 */
+ __be16 rccm; /* receive control character mask */
+ __be16 rccr; /* receive control character register */
+ __be16 rlbc; /* receive last break character */
+ __be16 res2; /* reserved */
+ __be32 res3; /* reserved, should be cleared */
+ u8 res4; /* reserved, should be cleared */
+ u8 res5[3]; /* reserved, should be cleared */
+ __be32 res6; /* reserved, should be cleared */
+ __be32 res7; /* reserved, should be cleared */
+ __be32 res8; /* reserved, should be cleared */
+ __be32 res9; /* reserved, should be cleared */
+ __be32 res10; /* reserved, should be cleared */
+ __be32 res11; /* reserved, should be cleared */
+ __be32 res12; /* reserved, should be cleared */
+ __be32 res13; /* reserved, should be cleared */
+/* The rest is for Soft-UART only */
+ __be16 supsmr; /* 0x90, Shadow UPSMR */
+ __be16 res92; /* 0x92, reserved, initialize to 0 */
+ __be32 rx_state; /* 0x94, RX state, initialize to 0 */
+ __be32 rx_cnt; /* 0x98, RX count, initialize to 0 */
+ u8 rx_length; /* 0x9C, Char length, set to 1+CL+PEN+1+SL */
+ u8 rx_bitmark; /* 0x9D, reserved, initialize to 0 */
+ u8 rx_temp_dlst_qe; /* 0x9E, reserved, initialize to 0 */
+ u8 res14[0xBC - 0x9F]; /* reserved */
+ __be32 dump_ptr; /* 0xBC, Dump pointer */
+ __be32 rx_frame_rem; /* 0xC0, reserved, initialize to 0 */
+ u8 rx_frame_rem_size; /* 0xC4, reserved, initialize to 0 */
+ u8 tx_mode; /* 0xC5, mode, 0=AHDLC, 1=UART */
+ __be16 tx_state; /* 0xC6, TX state */
+ u8 res15[0xD0 - 0xC8]; /* reserved */
+ __be32 resD0; /* 0xD0, reserved, initialize to 0 */
+ u8 resD4; /* 0xD4, reserved, initialize to 0 */
+ __be16 resD5; /* 0xD5, reserved, initialize to 0 */
+} __attribute__ ((packed));
+
+/* SUPSMR definitions, for Soft-UART only */
+#define UCC_UART_SUPSMR_SL 0x8000
+#define UCC_UART_SUPSMR_RPM_MASK 0x6000
+#define UCC_UART_SUPSMR_RPM_ODD 0x0000
+#define UCC_UART_SUPSMR_RPM_LOW 0x2000
+#define UCC_UART_SUPSMR_RPM_EVEN 0x4000
+#define UCC_UART_SUPSMR_RPM_HIGH 0x6000
+#define UCC_UART_SUPSMR_PEN 0x1000
+#define UCC_UART_SUPSMR_TPM_MASK 0x0C00
+#define UCC_UART_SUPSMR_TPM_ODD 0x0000
+#define UCC_UART_SUPSMR_TPM_LOW 0x0400
+#define UCC_UART_SUPSMR_TPM_EVEN 0x0800
+#define UCC_UART_SUPSMR_TPM_HIGH 0x0C00
+#define UCC_UART_SUPSMR_FRZ 0x0100
+#define UCC_UART_SUPSMR_UM_MASK 0x00c0
+#define UCC_UART_SUPSMR_UM_NORMAL 0x0000
+#define UCC_UART_SUPSMR_UM_MAN_MULTI 0x0040
+#define UCC_UART_SUPSMR_UM_AUTO_MULTI 0x00c0
+#define UCC_UART_SUPSMR_CL_MASK 0x0030
+#define UCC_UART_SUPSMR_CL_8 0x0030
+#define UCC_UART_SUPSMR_CL_7 0x0020
+#define UCC_UART_SUPSMR_CL_6 0x0010
+#define UCC_UART_SUPSMR_CL_5 0x0000
+
+#define UCC_UART_TX_STATE_AHDLC 0x00
+#define UCC_UART_TX_STATE_UART 0x01
+#define UCC_UART_TX_STATE_X1 0x00
+#define UCC_UART_TX_STATE_X16 0x80
+
+#define UCC_UART_PRAM_ALIGNMENT 0x100
+
+#define UCC_UART_SIZE_OF_BD UCC_SLOW_SIZE_OF_BD
+#define NUM_CONTROL_CHARS 8
+
+/* Private per-port data structure */
+struct uart_qe_port {
+ struct uart_port port;
+ struct ucc_slow __iomem *uccp;
+ struct ucc_uart_pram __iomem *uccup;
+ struct ucc_slow_info us_info;
+ struct ucc_slow_private *us_private;
+ struct device_node *np;
+ unsigned int ucc_num; /* First ucc is 0, not 1 */
+
+ u16 rx_nrfifos;
+ u16 rx_fifosize;
+ u16 tx_nrfifos;
+ u16 tx_fifosize;
+ int wait_closing;
+ u32 flags;
+ struct qe_bd *rx_bd_base;
+ struct qe_bd *rx_cur;
+ struct qe_bd *tx_bd_base;
+ struct qe_bd *tx_cur;
+ unsigned char *tx_buf;
+ unsigned char *rx_buf;
+ void *bd_virt; /* virtual address of the BD buffers */
+ dma_addr_t bd_dma_addr; /* bus address of the BD buffers */
+ unsigned int bd_size; /* size of BD buffer space */
+};
+
+static struct uart_driver ucc_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = "serial",
+ .dev_name = "ttyQE",
+ .major = SERIAL_QE_MAJOR,
+ .minor = SERIAL_QE_MINOR,
+ .nr = UCC_MAX_UART,
+};
+
+/*
+ * Virtual to physical address translation.
+ *
+ * Given the virtual address for a character buffer, this function returns
+ * the physical (DMA) equivalent.
+ */
+static inline dma_addr_t cpu2qe_addr(void *addr, struct uart_qe_port *qe_port)
+{
+ if (likely((addr >= qe_port->bd_virt)) &&
+ (addr < (qe_port->bd_virt + qe_port->bd_size)))
+ return qe_port->bd_dma_addr + (addr - qe_port->bd_virt);
+
+ /* something nasty happened */
+ printk(KERN_ERR "%s: addr=%p\n", __FUNCTION__, addr);
+ BUG();
+ return 0;
+}
+
+/*
+ * Physical to virtual address translation.
+ *
+ * Given the physical (DMA) address for a character buffer, this function
+ * returns the virtual equivalent.
+ */
+static inline void *qe2cpu_addr(dma_addr_t addr, struct uart_qe_port *qe_port)
+{
+ /* sanity check */
+ if (likely((addr >= qe_port->bd_dma_addr) &&
+ (addr < (qe_port->bd_dma_addr + qe_port->bd_size))))
+ return qe_port->bd_virt + (addr - qe_port->bd_dma_addr);
+
+ /* something nasty happened */
+ printk(KERN_ERR "%s: addr=%x\n", __FUNCTION__, addr);
+ BUG();
+ return NULL;
+}
+
+/*
+ * Return 1 if the QE is done transmitting all buffers for this port
+ *
+ * This function scans each BD in sequence. If we find a BD that is not
+ * ready (READY=1), then we return 0 indicating that the QE is still sending
+ * data. If we reach the last BD (WRAP=1), then we know we've scanned
+ * the entire list, and all BDs are done.
+ */
+static unsigned int qe_uart_tx_empty(struct uart_port *port)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+ struct qe_bd *bdp = qe_port->tx_bd_base;
+
+ while (1) {
+ if (in_be16(&bdp->status) & BD_SC_READY)
+ /* This BD is not done, so return "not done" */
+ return 0;
+
+ if (in_be16(&bdp->status) & BD_SC_WRAP)
+ /*
+ * This BD is done and it's the last one, so return
+ * "done"
+ */
+ return 1;
+
+ bdp++;
+ };
+}
+
+/*
+ * Set the modem control lines
+ *
+ * Although the QE can control the modem control lines (e.g. CTS), we
+ * don't need that support. This function must exist, however, otherwise
+ * the kernel will panic.
+ */
+void qe_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+
+/*
+ * Get the current modem control line status
+ *
+ * Although the QE can control the modem control lines (e.g. CTS), this
+ * driver currently doesn't support that, so we always return Carrier
+ * Detect, Data Set Ready, and Clear To Send.
+ */
+static unsigned int qe_uart_get_mctrl(struct uart_port *port)
+{
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/*
+ * Disable the transmit interrupt.
+ *
+ * Although this function is called "stop_tx", it does not actually stop
+ * transmission of data. Instead, it tells the QE to not generate an
+ * interrupt when the UCC is finished sending characters.
+ */
+static void qe_uart_stop_tx(struct uart_port *port)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+
+ clrbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_TX);
+}
+
+/*
+ * Transmit as many characters to the HW as possible.
+ *
+ * This function will attempt to stuff of all the characters from the
+ * kernel's transmit buffer into TX BDs.
+ *
+ * A return value of non-zero indicates that it sucessfully stuffed all
+ * characters from the kernel buffer.
+ *
+ * A return value of zero indicates that there are still characters in the
+ * kernel's buffer that have not been transmitted, but there are no more BDs
+ * available. This function should be called again after a BD has been made
+ * available.
+ */
+static int qe_uart_tx_pump(struct uart_qe_port *qe_port)
+{
+ struct qe_bd *bdp;
+ unsigned char *p;
+ unsigned int count;
+ struct uart_port *port = &qe_port->port;
+ struct circ_buf *xmit = &port->info->xmit;
+
+ bdp = qe_port->rx_cur;
+
+ /* Handle xon/xoff */
+ if (port->x_char) {
+ /* Pick next descriptor and fill from buffer */
+ bdp = qe_port->tx_cur;
+
+ p = qe2cpu_addr(bdp->buf, qe_port);
+
+ *p++ = port->x_char;
+ out_be16(&bdp->length, 1);
+ setbits16(&bdp->status, BD_SC_READY);
+ /* Get next BD. */
+ if (in_be16(&bdp->status) & BD_SC_WRAP)
+ bdp = qe_port->tx_bd_base;
+ else
+ bdp++;
+ qe_port->tx_cur = bdp;
+
+ port->icount.tx++;
+ port->x_char = 0;
+ return 1;
+ }
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ qe_uart_stop_tx(port);
+ return 0;
+ }
+
+ /* Pick next descriptor and fill from buffer */
+ bdp = qe_port->tx_cur;
+
+ while (!(in_be16(&bdp->status) & BD_SC_READY) &&
+ (xmit->tail != xmit->head)) {
+ count = 0;
+ p = qe2cpu_addr(bdp->buf, qe_port);
+ while (count < qe_port->tx_fifosize) {
+ *p++ = xmit->buf[xmit->tail];
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ count++;
+ if (xmit->head == xmit->tail)
+ break;
+ }
+
+ out_be16(&bdp->length, count);
+ setbits16(&bdp->status, BD_SC_READY);
+
+ /* Get next BD. */
+ if (in_be16(&bdp->status) & BD_SC_WRAP)
+ bdp = qe_port->tx_bd_base;
+ else
+ bdp++;
+ }
+ qe_port->tx_cur = bdp;
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit)) {
+ /* The kernel buffer is empty, so turn off TX interrupts. We
+ don't need to be told when the QE is finished transmitting
+ the data. */
+ qe_uart_stop_tx(port);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Start transmitting data
+ *
+ * This function will start transmitting any available data, if the port
+ * isn't already transmitting data.
+ */
+static void qe_uart_start_tx(struct uart_port *port)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+
+ /* If we currently are transmitting, then just return */
+ if (in_be16(&qe_port->uccp->uccm) & UCC_UART_UCCE_TX)
+ return;
+
+ /* Otherwise, pump the port and start transmission */
+ if (qe_uart_tx_pump(qe_port))
+ setbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_TX);
+}
+
+/*
+ * Stop transmitting data
+ */
+static void qe_uart_stop_rx(struct uart_port *port)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+
+ clrbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX);
+}
+
+/*
+ * Enable status change interrupts
+ *
+ * We don't support status change interrupts, but we need to define this
+ * function otherwise the kernel will panic.
+ */
+static void qe_uart_enable_ms(struct uart_port *port)
+{
+}
+
+/* Start or stop sending break signal
+ *
+ * This function controls the sending of a break signal. If break_state=1,
+ * then we start sending a break signal. If break_state=0, then we stop
+ * sending the break signal.
+ */
+static void qe_uart_break_ctl(struct uart_port *port, int break_state)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+
+ if (break_state)
+ ucc_slow_stop_tx(qe_port->us_private);
+ else
+ ucc_slow_restart_tx(qe_port->us_private);
+}
+
+/* ISR helper function for receiving character.
+ *
+ * This function is called by the ISR to handling receiving characters
+ */
+static void qe_uart_int_rx(struct uart_qe_port *qe_port)
+{
+ int i;
+ unsigned char ch, *cp;
+ struct uart_port *port = &qe_port->port;
+ struct tty_struct *tty = port->info->tty;
+ struct qe_bd *bdp;
+ u16 status;
+ unsigned int flg;
+
+ /* Just loop through the closed BDs and copy the characters into
+ * the buffer.
+ */
+ bdp = qe_port->rx_cur;
+ while (1) {
+ status = in_be16(&bdp->status);
+
+ /* If this one is empty, then we assume we've read them all */
+ if (status & BD_SC_EMPTY)
+ break;
+
+ /* get number of characters, and check space in RX buffer */
+ i = in_be16(&bdp->length);
+
+ /* If we don't have enough room in RX buffer for the entire BD,
+ * then we try later, which will be the next RX interrupt.
+ */
+ if (tty_buffer_request_room(tty, i) < i) {
+ dev_dbg(port->dev, "ucc-uart: no room in RX buffer\n");
+ return;
+ }
+
+ /* get pointer */
+ cp = qe2cpu_addr(bdp->buf, qe_port);
+
+ /* loop through the buffer */
+ while (i-- > 0) {
+ ch = *cp++;
+ port->icount.rx++;
+ flg = TTY_NORMAL;
+
+ if (!i && status &
+ (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV))
+ goto handle_error;
+ if (uart_handle_sysrq_char(port, ch))
+ continue;
+
+error_return:
+ tty_insert_flip_char(tty, ch, flg);
+
+ }
+
+ /* This BD is ready to be used again. Clear status. get next */
+ clrsetbits_be16(&bdp->status, BD_SC_BR | BD_SC_FR | BD_SC_PR |
+ BD_SC_OV | BD_SC_ID, BD_SC_EMPTY);
+ if (in_be16(&bdp->status) & BD_SC_WRAP)
+ bdp = qe_port->rx_bd_base;
+ else
+ bdp++;
+
+ }
+
+ /* Write back buffer pointer */
+ qe_port->rx_cur = bdp;
+
+ /* Activate BH processing */
+ tty_flip_buffer_push(tty);
+
+ return;
+
+ /* Error processing */
+
+handle_error:
+ /* Statistics */
+ if (status & BD_SC_BR)
+ port->icount.brk++;
+ if (status & BD_SC_PR)
+ port->icount.parity++;
+ if (status & BD_SC_FR)
+ port->icount.frame++;
+ if (status & BD_SC_OV)
+ port->icount.overrun++;
+
+ /* Mask out ignored conditions */
+ status &= port->read_status_mask;
+
+ /* Handle the remaining ones */
+ if (status & BD_SC_BR)
+ flg = TTY_BREAK;
+ else if (status & BD_SC_PR)
+ flg = TTY_PARITY;
+ else if (status & BD_SC_FR)
+ flg = TTY_FRAME;
+
+ /* Overrun does not affect the current character ! */
+ if (status & BD_SC_OV)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+#ifdef SUPPORT_SYSRQ
+ port->sysrq = 0;
+#endif
+ goto error_return;
+}
+
+/* Interrupt handler
+ *
+ * This interrupt handler is called after a BD is processed.
+ */
+static irqreturn_t qe_uart_int(int irq, void *data)
+{
+ struct uart_qe_port *qe_port = (struct uart_qe_port *) data;
+ struct ucc_slow __iomem *uccp = qe_port->uccp;
+ u16 events;
+
+ /* Clear the interrupts */
+ events = in_be16(&uccp->ucce);
+ out_be16(&uccp->ucce, events);
+
+ if (events & UCC_UART_UCCE_BRKE)
+ uart_handle_break(&qe_port->port);
+
+ if (events & UCC_UART_UCCE_RX)
+ qe_uart_int_rx(qe_port);
+
+ if (events & UCC_UART_UCCE_TX)
+ qe_uart_tx_pump(qe_port);
+
+ return events ? IRQ_HANDLED : IRQ_NONE;
+}
+
+/* Initialize buffer descriptors
+ *
+ * This function initializes all of the RX and TX buffer descriptors.
+ */
+static void qe_uart_initbd(struct uart_qe_port *qe_port)
+{
+ int i;
+ void *bd_virt;
+ struct qe_bd *bdp;
+
+ /* Set the physical address of the host memory buffers in the buffer
+ * descriptors, and the virtual address for us to work with.
+ */
+ bd_virt = qe_port->bd_virt;
+ bdp = qe_port->rx_bd_base;
+ qe_port->rx_cur = qe_port->rx_bd_base;
+ for (i = 0; i < (qe_port->rx_nrfifos - 1); i++) {
+ out_be16(&bdp->status, BD_SC_EMPTY | BD_SC_INTRPT);
+ out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
+ out_be16(&bdp->length, 0);
+ bd_virt += qe_port->rx_fifosize;
+ bdp++;
+ }
+
+ /* */
+ out_be16(&bdp->status, BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT);
+ out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
+ out_be16(&bdp->length, 0);
+
+ /* Set the physical address of the host memory
+ * buffers in the buffer descriptors, and the
+ * virtual address for us to work with.
+ */
+ bd_virt = qe_port->bd_virt +
+ L1_CACHE_ALIGN(qe_port->rx_nrfifos * qe_port->rx_fifosize);
+ qe_port->tx_cur = qe_port->tx_bd_base;
+ bdp = qe_port->tx_bd_base;
+ for (i = 0; i < (qe_port->tx_nrfifos - 1); i++) {
+ out_be16(&bdp->status, BD_SC_INTRPT);
+ out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
+ out_be16(&bdp->length, 0);
+ bd_virt += qe_port->tx_fifosize;
+ bdp++;
+ }
+
+ /* Loopback requires the preamble bit to be set on the first TX BD */
+#ifdef LOOPBACK
+ setbits16(&qe_port->tx_cur->status, BD_SC_P);
+#endif
+
+ out_be16(&bdp->status, BD_SC_WRAP | BD_SC_INTRPT);
+ out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
+ out_be16(&bdp->length, 0);
+}
+
+/*
+ * Initialize a UCC for UART.
+ *
+ * This function configures a given UCC to be used as a UART device. Basic
+ * UCC initialization is handled in qe_uart_request_port(). This function
+ * does all the UART-specific stuff.
+ */
+static void qe_uart_init_ucc(struct uart_qe_port *qe_port)
+{
+ u32 cecr_subblock;
+ struct ucc_slow __iomem *uccp = qe_port->uccp;
+ struct ucc_uart_pram *uccup = qe_port->uccup;
+
+ unsigned int i;
+
+ /* First, disable TX and RX in the UCC */
+ ucc_slow_disable(qe_port->us_private, COMM_DIR_RX_AND_TX);
+
+ /* Program the UCC UART parameter RAM */
+ out_8(&uccup->common.rbmr, UCC_BMR_GBL | UCC_BMR_BO_BE);
+ out_8(&uccup->common.tbmr, UCC_BMR_GBL | UCC_BMR_BO_BE);
+ out_be16(&uccup->common.mrblr, qe_port->rx_fifosize);
+ out_be16(&uccup->maxidl, 0x10);
+ out_be16(&uccup->brkcr, 1);
+ out_be16(&uccup->parec, 0);
+ out_be16(&uccup->frmec, 0);
+ out_be16(&uccup->nosec, 0);
+ out_be16(&uccup->brkec, 0);
+ out_be16(&uccup->uaddr[0], 0);
+ out_be16(&uccup->uaddr[1], 0);
+ out_be16(&uccup->toseq, 0);
+ for (i = 0; i < 8; i++)
+ out_be16(&uccup->cchars[i], 0xC000);
+ out_be16(&uccup->rccm, 0xc0ff);
+
+ /* Configure the GUMR registers for UART */
+ if (soft_uart)
+ /* Soft-UART requires a 1X multiplier for TX */
+ clrsetbits_be32(&uccp->gumr_l,
+ UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK |
+ UCC_SLOW_GUMR_L_RDCR_MASK,
+ UCC_SLOW_GUMR_L_MODE_UART | UCC_SLOW_GUMR_L_TDCR_1 |
+ UCC_SLOW_GUMR_L_RDCR_16);
+ else
+ clrsetbits_be32(&uccp->gumr_l,
+ UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK |
+ UCC_SLOW_GUMR_L_RDCR_MASK,
+ UCC_SLOW_GUMR_L_MODE_UART | UCC_SLOW_GUMR_L_TDCR_16 |
+ UCC_SLOW_GUMR_L_RDCR_16);
+
+ clrsetbits_be32(&uccp->gumr_h, UCC_SLOW_GUMR_H_RFW,
+ UCC_SLOW_GUMR_H_TRX | UCC_SLOW_GUMR_H_TTX);
+
+#ifdef LOOPBACK
+ clrsetbits_be32(&uccp->gumr_l, UCC_SLOW_GUMR_L_DIAG_MASK,
+ UCC_SLOW_GUMR_L_DIAG_LOOP);
+ clrsetbits_be32(&uccp->gumr_h,
+ UCC_SLOW_GUMR_H_CTSP | UCC_SLOW_GUMR_H_RSYN,
+ UCC_SLOW_GUMR_H_CDS);
+#endif
+
+ /* Enable rx interrupts and clear all pending events. */
+ out_be16(&uccp->uccm, 0);
+ out_be16(&uccp->ucce, 0xffff);
+ out_be16(&uccp->udsr, 0x7e7e);
+
+ /* Initialize UPSMR */
+ out_be16(&uccp->upsmr, 0);
+
+ if (soft_uart) {
+ out_be16(&uccup->supsmr, 0x30);
+ out_be16(&uccup->res92, 0);
+ out_be32(&uccup->rx_state, 0);
+ out_be32(&uccup->rx_cnt, 0);
+ out_8(&uccup->rx_bitmark, 0);
+ out_8(&uccup->rx_length, 10);
+ out_be32(&uccup->dump_ptr, 0x4000);
+ out_8(&uccup->rx_temp_dlst_qe, 0);
+ out_be32(&uccup->rx_frame_rem, 0);
+ out_8(&uccup->rx_frame_rem_size, 0);
+ /* Soft-UART requires TX to be 1X */
+ out_8(&uccup->tx_mode,
+ UCC_UART_TX_STATE_UART | UCC_UART_TX_STATE_X1);
+ out_be16(&uccup->tx_state, 0);
+ out_8(&uccup->resD4, 0);
+ out_be16(&uccup->resD5, 0);
+
+ /* Set UART mode.
+ * Enable receive and transmit.
+ */
+
+ /* From the microcode errata:
+ * 1.GUMR_L register, set mode=0010 (QMC).
+ * 2.Set GUMR_H[17] bit. (UART/AHDLC mode).
+ * 3.Set GUMR_H[19:20] (Transparent mode)
+ * 4.Clear GUMR_H[26] (RFW)
+ * ...
+ * 6.Receiver must use 16x over sampling
+ */
+ clrsetbits_be32(&uccp->gumr_l,
+ UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK |
+ UCC_SLOW_GUMR_L_RDCR_MASK,
+ UCC_SLOW_GUMR_L_MODE_QMC | UCC_SLOW_GUMR_L_TDCR_16 |
+ UCC_SLOW_GUMR_L_RDCR_16);
+
+ clrsetbits_be32(&uccp->gumr_h,
+ UCC_SLOW_GUMR_H_RFW | UCC_SLOW_GUMR_H_RSYN,
+ UCC_SLOW_GUMR_H_SUART | UCC_SLOW_GUMR_H_TRX |
+ UCC_SLOW_GUMR_H_TTX | UCC_SLOW_GUMR_H_TFL);
+
+#ifdef LOOPBACK
+ clrsetbits_be32(&uccp->gumr_l, UCC_SLOW_GUMR_L_DIAG_MASK,
+ UCC_SLOW_GUMR_L_DIAG_LOOP);
+ clrbits32(&uccp->gumr_h, UCC_SLOW_GUMR_H_CTSP |
+ UCC_SLOW_GUMR_H_CDS);
+#endif
+
+ cecr_subblock = ucc_slow_get_qe_cr_subblock(qe_port->ucc_num);
+ qe_issue_cmd(QE_INIT_TX_RX, cecr_subblock,
+ QE_CR_PROTOCOL_UNSPECIFIED, 0);
+ }
+}
+
+/*
+ * Initialize the port.
+ */
+static int qe_uart_startup(struct uart_port *port)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+ int ret;
+
+ /*
+ * If we're using Soft-UART mode, then we need to make sure the
+ * firmware has been uploaded first.
+ */
+ if (soft_uart && !firmware_loaded) {
+ dev_err(port->dev, "Soft-UART firmware not uploaded\n");
+ return -ENODEV;
+ }
+
+ qe_uart_initbd(qe_port);
+ qe_uart_init_ucc(qe_port);
+
+ /* Install interrupt handler. */
+ ret = request_irq(port->irq, qe_uart_int, IRQF_SHARED, "ucc-uart",
+ qe_port);
+ if (ret) {
+ dev_err(port->dev, "could not claim IRQ %u\n", port->irq);
+ return ret;
+ }
+
+ /* Startup rx-int */
+ setbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX);
+ ucc_slow_enable(qe_port->us_private, COMM_DIR_RX_AND_TX);
+
+ return 0;
+}
+
+/*
+ * Shutdown the port.
+ */
+static void qe_uart_shutdown(struct uart_port *port)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+ struct ucc_slow __iomem *uccp = qe_port->uccp;
+ unsigned int timeout = 20;
+
+ /* Disable RX and TX */
+
+ /* Wait for all the BDs marked sent */
+ while (!qe_uart_tx_empty(port)) {
+ if (!--timeout) {
+ dev_warn(port->dev, "shutdown timeout\n");
+ break;
+ }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(2);
+ }
+
+ if (qe_port->wait_closing) {
+ /* Wait a bit longer */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(qe_port->wait_closing);
+ }
+
+ /* Stop uarts */
+ ucc_slow_disable(qe_port->us_private, COMM_DIR_RX_AND_TX);
+ clrbits16(&uccp->uccm, UCC_UART_UCCE_TX | UCC_UART_UCCE_RX);
+
+ /* Shut them really down and reinit buffer descriptors */
+ ucc_slow_graceful_stop_tx(qe_port->us_private);
+ qe_uart_initbd(qe_port);
+
+ free_irq(port->irq, qe_port);
+}
+
+/*
+ * Set the serial port parameters.
+ */
+static void qe_uart_set_termios(struct uart_port *port,
+ struct ktermios *termios, struct ktermios *old)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+ struct ucc_slow __iomem *uccp = qe_port->uccp;
+ unsigned int baud;
+ unsigned long flags;
+ u16 upsmr = in_be16(&uccp->upsmr);
+ struct ucc_uart_pram __iomem *uccup = qe_port->uccup;
+ u16 supsmr = in_be16(&uccup->supsmr);
+ u8 char_length = 2; /* 1 + CL + PEN + 1 + SL */
+
+ /* Character length programmed into the mode register is the
+ * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
+ * 1 or 2 stop bits, minus 1.
+ * The value 'bits' counts this for us.
+ */
+
+ /* byte size */
+ upsmr &= UCC_UART_UPSMR_CL_MASK;
+ supsmr &= UCC_UART_SUPSMR_CL_MASK;
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ upsmr |= UCC_UART_UPSMR_CL_5;
+ supsmr |= UCC_UART_SUPSMR_CL_5;
+ char_length += 5;
+ break;
+ case CS6:
+ upsmr |= UCC_UART_UPSMR_CL_6;
+ supsmr |= UCC_UART_SUPSMR_CL_6;
+ char_length += 6;
+ break;
+ case CS7:
+ upsmr |= UCC_UART_UPSMR_CL_7;
+ supsmr |= UCC_UART_SUPSMR_CL_7;
+ char_length += 7;
+ break;
+ default: /* case CS8 */
+ upsmr |= UCC_UART_UPSMR_CL_8;
+ supsmr |= UCC_UART_SUPSMR_CL_8;
+ char_length += 8;
+ break;
+ }
+
+ /* If CSTOPB is set, we want two stop bits */
+ if (termios->c_cflag & CSTOPB) {
+ upsmr |= UCC_UART_UPSMR_SL;
+ supsmr |= UCC_UART_SUPSMR_SL;
+ char_length++; /* + SL */
+ }
+
+ if (termios->c_cflag & PARENB) {
+ upsmr |= UCC_UART_UPSMR_PEN;
+ supsmr |= UCC_UART_SUPSMR_PEN;
+ char_length++; /* + PEN */
+
+ if (!(termios->c_cflag & PARODD)) {
+ upsmr &= ~(UCC_UART_UPSMR_RPM_MASK |
+ UCC_UART_UPSMR_TPM_MASK);
+ upsmr |= UCC_UART_UPSMR_RPM_EVEN |
+ UCC_UART_UPSMR_TPM_EVEN;
+ supsmr &= ~(UCC_UART_SUPSMR_RPM_MASK |
+ UCC_UART_SUPSMR_TPM_MASK);
+ supsmr |= UCC_UART_SUPSMR_RPM_EVEN |
+ UCC_UART_SUPSMR_TPM_EVEN;
+ }
+ }
+
+ /*
+ * Set up parity check flag
+ */
+ port->read_status_mask = BD_SC_EMPTY | BD_SC_OV;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= BD_SC_FR | BD_SC_PR;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ port->read_status_mask |= BD_SC_BR;
+
+ /*
+ * Characters to ignore
+ */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
+ if (termios->c_iflag & IGNBRK) {
+ port->ignore_status_mask |= BD_SC_BR;
+ /*
+ * If we're ignore parity and break indicators, ignore
+ * overruns too. (For real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= BD_SC_OV;
+ }
+ /*
+ * !!! ignore all characters if CREAD is not set
+ */
+ if ((termios->c_cflag & CREAD) == 0)
+ port->read_status_mask &= ~BD_SC_EMPTY;
+
+ baud = uart_get_baud_rate(port, termios, old, 0, 115200);
+
+ /* Do we really need a spinlock here? */
+ spin_lock_irqsave(&port->lock, flags);
+
+ out_be16(&uccp->upsmr, upsmr);
+ if (soft_uart) {
+ out_be16(&uccup->supsmr, supsmr);
+ out_8(&uccup->rx_length, char_length);
+
+ /* Soft-UART requires a 1X multiplier for TX */
+ qe_setbrg(qe_port->us_info.rx_clock, baud, 16);
+ qe_setbrg(qe_port->us_info.tx_clock, baud, 1);
+ } else {
+ qe_setbrg(qe_port->us_info.rx_clock, baud, 16);
+ qe_setbrg(qe_port->us_info.tx_clock, baud, 16);
+ }
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/*
+ * Return a pointer to a string that describes what kind of port this is.
+ */
+static const char *qe_uart_type(struct uart_port *port)
+{
+ return "QE";
+}
+
+/*
+ * Allocate any memory and I/O resources required by the port.
+ */
+static int qe_uart_request_port(struct uart_port *port)
+{
+ int ret;
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+ struct ucc_slow_info *us_info = &qe_port->us_info;
+ struct ucc_slow_private *uccs;
+ unsigned int rx_size, tx_size;
+ void *bd_virt;
+ dma_addr_t bd_dma_addr = 0;
+
+ ret = ucc_slow_init(us_info, &uccs);
+ if (ret) {
+ dev_err(port->dev, "could not initialize UCC%u\n",
+ qe_port->ucc_num);
+ return ret;
+ }
+
+ qe_port->us_private = uccs;
+ qe_port->uccp = uccs->us_regs;
+ qe_port->uccup = (struct ucc_uart_pram *) uccs->us_pram;
+ qe_port->rx_bd_base = uccs->rx_bd;
+ qe_port->tx_bd_base = uccs->tx_bd;
+
+ /*
+ * Allocate the transmit and receive data buffers.
+ */
+
+ rx_size = L1_CACHE_ALIGN(qe_port->rx_nrfifos * qe_port->rx_fifosize);
+ tx_size = L1_CACHE_ALIGN(qe_port->tx_nrfifos * qe_port->tx_fifosize);
+
+ bd_virt = dma_alloc_coherent(NULL, rx_size + tx_size, &bd_dma_addr,
+ GFP_KERNEL);
+ if (!bd_virt) {
+ dev_err(port->dev, "could not allocate buffer descriptors\n");
+ return -ENOMEM;
+ }
+
+ qe_port->bd_virt = bd_virt;
+ qe_port->bd_dma_addr = bd_dma_addr;
+ qe_port->bd_size = rx_size + tx_size;
+
+ qe_port->rx_buf = bd_virt;
+ qe_port->tx_buf = qe_port->rx_buf + rx_size;
+
+ return 0;
+}
+
+/*
+ * Configure the port.
+ *
+ * We say we're a CPM-type port because that's mostly true. Once the device
+ * is configured, this driver operates almost identically to the CPM serial
+ * driver.
+ */
+static void qe_uart_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE) {
+ port->type = PORT_CPM;
+ qe_uart_request_port(port);
+ }
+}
+
+/*
+ * Release any memory and I/O resources that were allocated in
+ * qe_uart_request_port().
+ */
+static void qe_uart_release_port(struct uart_port *port)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+ struct ucc_slow_private *uccs = qe_port->us_private;
+
+ dma_free_coherent(NULL, qe_port->bd_size, qe_port->bd_virt,
+ qe_port->bd_dma_addr);
+
+ ucc_slow_free(uccs);
+}
+
+/*
+ * Verify that the data in serial_struct is suitable for this device.
+ */
+static int qe_uart_verify_port(struct uart_port *port,
+ struct serial_struct *ser)
+{
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
+ return -EINVAL;
+
+ if (ser->irq < 0 || ser->irq >= NR_IRQS)
+ return -EINVAL;
+
+ if (ser->baud_base < 9600)
+ return -EINVAL;
+
+ return 0;
+}
+/* UART operations
+ *
+ * Details on these functions can be found in Documentation/serial/driver
+ */
+static struct uart_ops qe_uart_pops = {
+ .tx_empty = qe_uart_tx_empty,
+ .set_mctrl = qe_uart_set_mctrl,
+ .get_mctrl = qe_uart_get_mctrl,
+ .stop_tx = qe_uart_stop_tx,
+ .start_tx = qe_uart_start_tx,
+ .stop_rx = qe_uart_stop_rx,
+ .enable_ms = qe_uart_enable_ms,
+ .break_ctl = qe_uart_break_ctl,
+ .startup = qe_uart_startup,
+ .shutdown = qe_uart_shutdown,
+ .set_termios = qe_uart_set_termios,
+ .type = qe_uart_type,
+ .release_port = qe_uart_release_port,
+ .request_port = qe_uart_request_port,
+ .config_port = qe_uart_config_port,
+ .verify_port = qe_uart_verify_port,
+};
+
+/*
+ * Obtain the SOC model number and revision level
+ *
+ * This function parses the device tree to obtain the SOC model. It then
+ * reads the SVR register to the revision.
+ *
+ * The device tree stores the SOC model two different ways.
+ *
+ * The new way is:
+ *
+ * cpu@0 {
+ * compatible = "PowerPC,8323";
+ * device_type = "cpu";
+ * ...
+ *
+ *
+ * The old way is:
+ * PowerPC,8323@0 {
+ * device_type = "cpu";
+ * ...
+ *
+ * This code first checks the new way, and then the old way.
+ */
+static unsigned int soc_info(unsigned int *rev_h, unsigned int *rev_l)
+{
+ struct device_node *np;
+ const char *soc_string;
+ unsigned int svr;
+ unsigned int soc;
+
+ /* Find the CPU node */
+ np = of_find_node_by_type(NULL, "cpu");
+ if (!np)
+ return 0;
+ /* Find the compatible property */
+ soc_string = of_get_property(np, "compatible", NULL);
+ if (!soc_string)
+ /* No compatible property, so try the name. */
+ soc_string = np->name;
+
+ /* Extract the SOC number from the "PowerPC," string */
+ if ((sscanf(soc_string, "PowerPC,%u", &soc) != 1) || !soc)
+ return 0;
+
+ /* Get the revision from the SVR */
+ svr = mfspr(SPRN_SVR);
+ *rev_h = (svr >> 4) & 0xf;
+ *rev_l = svr & 0xf;
+
+ return soc;
+}
+
+/*
+ * requst_firmware_nowait() callback function
+ *
+ * This function is called by the kernel when a firmware is made available,
+ * or if it times out waiting for the firmware.
+ */
+static void uart_firmware_cont(const struct firmware *fw, void *context)
+{
+ struct qe_firmware *firmware;
+ struct device *dev = context;
+ int ret;
+
+ if (!fw) {
+ dev_err(dev, "firmware not found\n");
+ return;
+ }
+
+ firmware = (struct qe_firmware *) fw->data;
+
+ if (firmware->header.length != fw->size) {
+ dev_err(dev, "invalid firmware\n");
+ return;
+ }
+
+ ret = qe_upload_firmware(firmware);
+ if (ret) {
+ dev_err(dev, "could not load firmware\n");
+ return;
+ }
+
+ firmware_loaded = 1;
+}
+
+static int ucc_uart_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = ofdev->node;
+ const unsigned int *iprop; /* Integer OF properties */
+ const char *sprop; /* String OF properties */
+ struct uart_qe_port *qe_port = NULL;
+ struct resource res;
+ int ret;
+
+ /*
+ * Determine if we need Soft-UART mode
+ */
+ if (of_find_property(np, "soft-uart", NULL)) {
+ dev_dbg(&ofdev->dev, "using Soft-UART mode\n");
+ soft_uart = 1;
+ }
+
+ /*
+ * If we are using Soft-UART, determine if we need to upload the
+ * firmware, too.
+ */
+ if (soft_uart) {
+ struct qe_firmware_info *qe_fw_info;
+
+ qe_fw_info = qe_get_firmware_info();
+
+ /* Check if the firmware has been uploaded. */
+ if (qe_fw_info && strstr(qe_fw_info->id, "Soft-UART")) {
+ firmware_loaded = 1;
+ } else {
+ char filename[32];
+ unsigned int soc;
+ unsigned int rev_h;
+ unsigned int rev_l;
+
+ soc = soc_info(&rev_h, &rev_l);
+ if (!soc) {
+ dev_err(&ofdev->dev, "unknown CPU model\n");
+ return -ENXIO;
+ }
+ sprintf(filename, "fsl_qe_ucode_uart_%u_%u%u.bin",
+ soc, rev_h, rev_l);
+
+ dev_info(&ofdev->dev, "waiting for firmware %s\n",
+ filename);
+
+ /*
+ * We call request_firmware_nowait instead of
+ * request_firmware so that the driver can load and
+ * initialize the ports without holding up the rest of
+ * the kernel. If hotplug support is enabled in the
+ * kernel, then we use it.
+ */
+ ret = request_firmware_nowait(THIS_MODULE,
+ FW_ACTION_HOTPLUG, filename, &ofdev->dev,
+ &ofdev->dev, uart_firmware_cont);
+ if (ret) {
+ dev_err(&ofdev->dev,
+ "could not load firmware %s\n",
+ filename);
+ return ret;
+ }
+ }
+ }
+
+ qe_port = kzalloc(sizeof(struct uart_qe_port), GFP_KERNEL);
+ if (!qe_port) {
+ dev_err(&ofdev->dev, "can't allocate QE port structure\n");
+ return -ENOMEM;
+ }
+
+ /* Search for IRQ and mapbase */
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret) {
+ dev_err(&ofdev->dev, "missing 'reg' property in device tree\n");
+ kfree(qe_port);
+ return ret;
+ }
+ if (!res.start) {
+ dev_err(&ofdev->dev, "invalid 'reg' property in device tree\n");
+ kfree(qe_port);
+ return -EINVAL;
+ }
+ qe_port->port.mapbase = res.start;
+
+ /* Get the UCC number (device ID) */
+ /* UCCs are numbered 1-7 */
+ iprop = of_get_property(np, "device-id", NULL);
+ if (!iprop || (*iprop < 1) || (*iprop > UCC_MAX_NUM)) {
+ dev_err(&ofdev->dev,
+ "missing or invalid UCC specified in device tree\n");
+ kfree(qe_port);
+ return -ENODEV;
+ }
+ qe_port->ucc_num = *iprop - 1;
+
+ /*
+ * In the future, we should not require the BRG to be specified in the
+ * device tree. If no clock-source is specified, then just pick a BRG
+ * to use. This requires a new QE library function that manages BRG
+ * assignments.
+ */
+
+ sprop = of_get_property(np, "rx-clock-name", NULL);
+ if (!sprop) {
+ dev_err(&ofdev->dev, "missing rx-clock-name in device tree\n");
+ kfree(qe_port);
+ return -ENODEV;
+ }
+
+ qe_port->us_info.rx_clock = qe_clock_source(sprop);
+ if ((qe_port->us_info.rx_clock < QE_BRG1) ||
+ (qe_port->us_info.rx_clock > QE_BRG16)) {
+ dev_err(&ofdev->dev, "rx-clock-name must be a BRG for UART\n");
+ kfree(qe_port);
+ return -ENODEV;
+ }
+
+#ifdef LOOPBACK
+ /* In internal loopback mode, TX and RX must use the same clock */
+ qe_port->us_info.tx_clock = qe_port->us_info.rx_clock;
+#else
+ sprop = of_get_property(np, "tx-clock-name", NULL);
+ if (!sprop) {
+ dev_err(&ofdev->dev, "missing tx-clock-name in device tree\n");
+ kfree(qe_port);
+ return -ENODEV;
+ }
+ qe_port->us_info.tx_clock = qe_clock_source(sprop);
+#endif
+ if ((qe_port->us_info.tx_clock < QE_BRG1) ||
+ (qe_port->us_info.tx_clock > QE_BRG16)) {
+ dev_err(&ofdev->dev, "tx-clock-name must be a BRG for UART\n");
+ kfree(qe_port);
+ return -ENODEV;
+ }
+
+ /* Get the port number, numbered 0-3 */
+ iprop = of_get_property(np, "port-number", NULL);
+ if (!iprop) {
+ dev_err(&ofdev->dev, "missing port-number in device tree\n");
+ kfree(qe_port);
+ return -EINVAL;
+ }
+ qe_port->port.line = *iprop;
+ if (qe_port->port.line >= UCC_MAX_UART) {
+ dev_err(&ofdev->dev, "port-number must be 0-%u\n",
+ UCC_MAX_UART - 1);
+ kfree(qe_port);
+ return -EINVAL;
+ }
+
+ qe_port->port.irq = irq_of_parse_and_map(np, 0);
+ if (qe_port->port.irq == NO_IRQ) {
+ dev_err(&ofdev->dev, "could not map IRQ for UCC%u\n",
+ qe_port->ucc_num + 1);
+ kfree(qe_port);
+ return -EINVAL;
+ }
+
+ /*
+ * Newer device trees have an "fsl,qe" compatible property for the QE
+ * node, but we still need to support older device trees.
+ */
+ np = of_find_compatible_node(NULL, NULL, "fsl,qe");
+ if (!np) {
+ np = of_find_node_by_type(NULL, "qe");
+ if (!np) {
+ dev_err(&ofdev->dev, "could not find 'qe' node\n");
+ kfree(qe_port);
+ return -EINVAL;
+ }
+ }
+
+ iprop = of_get_property(np, "brg-frequency", NULL);
+ if (!iprop) {
+ dev_err(&ofdev->dev,
+ "missing brg-frequency in device tree\n");
+ kfree(qe_port);
+ return -EINVAL;
+ }
+
+ if (*iprop)
+ qe_port->port.uartclk = *iprop;
+ else {
+ /*
+ * Older versions of U-Boot do not initialize the brg-frequency
+ * property, so in this case we assume the BRG frequency is
+ * half the QE bus frequency.
+ */
+ iprop = of_get_property(np, "bus-frequency", NULL);
+ if (!iprop) {
+ dev_err(&ofdev->dev,
+ "missing QE bus-frequency in device tree\n");
+ kfree(qe_port);
+ return -EINVAL;
+ }
+ if (*iprop)
+ qe_port->port.uartclk = *iprop / 2;
+ else {
+ dev_err(&ofdev->dev,
+ "invalid QE bus-frequency in device tree\n");
+ kfree(qe_port);
+ return -EINVAL;
+ }
+ }
+
+ spin_lock_init(&qe_port->port.lock);
+ qe_port->np = np;
+ qe_port->port.dev = &ofdev->dev;
+ qe_port->port.ops = &qe_uart_pops;
+ qe_port->port.iotype = UPIO_MEM;
+
+ qe_port->tx_nrfifos = TX_NUM_FIFO;
+ qe_port->tx_fifosize = TX_BUF_SIZE;
+ qe_port->rx_nrfifos = RX_NUM_FIFO;
+ qe_port->rx_fifosize = RX_BUF_SIZE;
+
+ qe_port->wait_closing = UCC_WAIT_CLOSING;
+ qe_port->port.fifosize = 512;
+ qe_port->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
+
+ qe_port->us_info.ucc_num = qe_port->ucc_num;
+ qe_port->us_info.regs = (phys_addr_t) res.start;
+ qe_port->us_info.irq = qe_port->port.irq;
+
+ qe_port->us_info.rx_bd_ring_len = qe_port->rx_nrfifos;
+ qe_port->us_info.tx_bd_ring_len = qe_port->tx_nrfifos;
+
+ /* Make sure ucc_slow_init() initializes both TX and RX */
+ qe_port->us_info.init_tx = 1;
+ qe_port->us_info.init_rx = 1;
+
+ /* Add the port to the uart sub-system. This will cause
+ * qe_uart_config_port() to be called, so the us_info structure must
+ * be initialized.
+ */
+ ret = uart_add_one_port(&ucc_uart_driver, &qe_port->port);
+ if (ret) {
+ dev_err(&ofdev->dev, "could not add /dev/ttyQE%u\n",
+ qe_port->port.line);
+ kfree(qe_port);
+ return ret;
+ }
+
+ dev_set_drvdata(&ofdev->dev, qe_port);
+
+ dev_info(&ofdev->dev, "UCC%u assigned to /dev/ttyQE%u\n",
+ qe_port->ucc_num + 1, qe_port->port.line);
+
+ /* Display the mknod command for this device */
+ dev_dbg(&ofdev->dev, "mknod command is 'mknod /dev/ttyQE%u c %u %u'\n",
+ qe_port->port.line, SERIAL_QE_MAJOR,
+ SERIAL_QE_MINOR + qe_port->port.line);
+
+ return 0;
+}
+
+static int ucc_uart_remove(struct of_device *ofdev)
+{
+ struct uart_qe_port *qe_port = dev_get_drvdata(&ofdev->dev);
+
+ dev_info(&ofdev->dev, "removing /dev/ttyQE%u\n", qe_port->port.line);
+
+ uart_remove_one_port(&ucc_uart_driver, &qe_port->port);
+
+ dev_set_drvdata(&ofdev->dev, NULL);
+ kfree(qe_port);
+
+ return 0;
+}
+
+static struct of_device_id ucc_uart_match[] = {
+ {
+ .type = "serial",
+ .compatible = "ucc_uart",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ucc_uart_match);
+
+static struct of_platform_driver ucc_uart_of_driver = {
+ .owner = THIS_MODULE,
+ .name = "ucc_uart",
+ .match_table = ucc_uart_match,
+ .probe = ucc_uart_probe,
+ .remove = ucc_uart_remove,
+};
+
+static int __init ucc_uart_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "Freescale QUICC Engine UART device driver\n");
+#ifdef LOOPBACK
+ printk(KERN_INFO "ucc-uart: Using loopback mode\n");
+#endif
+
+ ret = uart_register_driver(&ucc_uart_driver);
+ if (ret) {
+ printk(KERN_ERR "ucc-uart: could not register UART driver\n");
+ return ret;
+ }
+
+ ret = of_register_platform_driver(&ucc_uart_of_driver);
+ if (ret)
+ printk(KERN_ERR
+ "ucc-uart: could not register platform driver\n");
+
+ return ret;
+}
+
+static void __exit ucc_uart_exit(void)
+{
+ printk(KERN_INFO
+ "Freescale QUICC Engine UART device driver unloading\n");
+
+ of_unregister_platform_driver(&ucc_uart_of_driver);
+ uart_unregister_driver(&ucc_uart_driver);
+}
+
+module_init(ucc_uart_init);
+module_exit(ucc_uart_exit);
+
+MODULE_DESCRIPTION("Freescale QUICC Engine (QE) UART");
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_QE_MAJOR);
+
--
1.5.2.4
^ permalink raw reply related
* Re: crash in kmem_cache_init
From: Olaf Hering @ 2008-01-15 15:58 UTC (permalink / raw)
To: linux-kernel, linuxppc-dev
In-Reply-To: <20080115150949.GA14089@aepfle.de>
On Tue, Jan 15, Olaf Hering wrote:
>
> Current linus tree crashes in kmem_cache_init, as shown below. The
> system is a 8cpu 2.2GHz POWER5 system, model 9117-570, with 4GB ram.
> Firmware is 240_332, 2.6.23 boots ok with the same config.
>
> There is a series of mm related patches in 2.6.24-rc1:
> commit 04231b3002ac53f8a64a7bd142fde3fa4b6808c6 seems to break it,
2.6.24-rc6-mm1-ppc64 boots past this point, but crashes later.
Likely unrelated to the kmem_cache_init bug:
...
matroxfb: 640x480x8bpp (virtual: 640x26214)
matroxfb: framebuffer at 0x40178000000, mapped to 0xd000080080080000, size 33554432
Console: switching to colour frame buffer device 80x30
fb0: MATROX frame buffer device
matroxfb_crtc2: secondary head of fb0 was registered as fb1
vio_register_driver: driver hvc_console registering
HVSI: registered 0 devices
Generic RTC Driver v1.07
Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing disabled
pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)
input: Macintosh mouse button emulation as /devices/virtual/input/input0
Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2
ide: Assuming 33MHz system bus speed for PIO modes; override with idebus=xx
ehci_hcd 0000:c8:01.2: EHCI Host Controller
ehci_hcd 0000:c8:01.2: new USB bus registered, assigned bus number 1
ehci_hcd 0000:c8:01.2: irq 85, io mem 0x400a0002000
ehci_hcd 0000:c8:01.2: USB 2.0 started, EHCI 1.00, driver 10 Dec 2004
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 5 ports detected
Unable to handle kernel paging request for data at address 0x00000050
Faulting instruction address: 0xc0000000000fa1c4
cpu 0x7: Vector: 300 (Data Access) at [c0000000d82e7a70]
pc: c0000000000fa1c4: .cache_reap+0x74/0x29c
lr: c0000000000fa198: .cache_reap+0x48/0x29c
sp: c0000000d82e7cf0
msr: 8000000000009032
dar: 50
dsisr: 40000000
current = 0xc0000000d82d85c0
paca = 0xc000000000668e00
pid = 27, comm = events/7
enter ? for help
[c0000000d82e7cf0] c00000000070be98 vmstat_update+0x0/0x18 (unreliable)
[c0000000d82e7da0] c000000000092994 .run_workqueue+0x120/0x210
[c0000000d82e7e40] c000000000093bb8 .worker_thread+0xcc/0xf0
[c0000000d82e7f00] c000000000097b70 .kthread+0x78/0xc4
[c0000000d82e7f90] c00000000002ab74 .kernel_thread+0x4c/0x68
7:mon>
...
^ permalink raw reply
* Re: [PATCH v4 0/3] OF-platform PATA driver
From: Olof Johansson @ 2008-01-15 16:40 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev, Paul Mundt, Jeff Garzik, linux-ide
In-Reply-To: <20080109190852.GA18827@localhost.localdomain>
Hi,
I've applied 1/3 and 2/3 together with my electra_ide move to pasemi.git
for-2.6.25, and will ask Paul to pull that. Kumar said he'd take 3/3.
I also added the const to the match table as spotted by Stephen.
-Olof
On Wed, Jan 09, 2008 at 10:08:52PM +0300, Anton Vorontsov wrote:
> Hi all,
>
> Here is the resend (aka v4) version of the OF-platform PATA
> driver and related patches.
>
> Changes since v3:
> - Acked-by: Paul Mundt <lethal@linux-sh.org>
> - In the powerpc specific patch: update defconfig and use
> machine_device_initcall -- this is new call found in the
> galak/powerpc.git.
>
> Changes since v2:
> - "PPC" added to PATA_PLATFORM "depends on" Kconfig entry;
> I didn't remove EMBEDDED "depends on" -- this wasn't discussed
> much and these patches should not depend on the decision.
> - cosmetic fixes;
> - "s/ioport_shift/reg_shift/g" patch dropped.
>
> Changes since v1:
> - __pata_platform_probe now accepts pio_mask argument;
> - pata-platform compatible property renamed to ata-generic;
> - pata_of_platform understands pio-mode property. It's used to pass
> pio_mask to the __pata_platform_probe. That is, in ata-generic
> context pio-mode means "pio mode the bus already configured for";
> - New optional patch that renames pata_platform_info's
> ioport_shift to reg_shift.
>
> Changes since RFC:
> - nuked drivers/ata/pata_platform.h;
> - powerpc bits: proper localbus node added.
>
> --
> Anton Vorontsov
> email: cbou@mail.ru
> backup email: ya-cbou@yandex.ru
> irc://irc.freenode.net/bd2
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* [PATCH] [POWERPC] pasemi: Move electra-ide to pata_of_platform
From: Olof Johansson @ 2008-01-15 16:40 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: linuxppc-dev, Paul Mundt, Jeff Garzik, linux-ide
In-Reply-To: <20080109190852.GA18827@localhost.localdomain>
Move electra-ide glue over to the new pata_of_platform framework, and
add the quirks needed to that driver.
---
Applied with the rest of the patches to pasemi.git for-2.6.25
arch/powerpc/platforms/pasemi/electra_ide.c | 96 ----------------------------
b/arch/powerpc/configs/pasemi_defconfig | 4 -
b/arch/powerpc/platforms/pasemi/Kconfig | 9 --
b/arch/powerpc/platforms/pasemi/Makefile | 1
b/drivers/ata/pata_of_platform.c | 20 ++++-
5 files changed, 17 insertions(+), 113 deletions(-)
diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig
index 9d21b08..797f0df 100644
--- a/arch/powerpc/configs/pasemi_defconfig
+++ b/arch/powerpc/configs/pasemi_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.24-rc6
-# Fri Dec 28 11:01:53 2007
+# Tue Jan 15 10:26:10 2008
#
CONFIG_PPC64=y
@@ -152,7 +152,6 @@ CONFIG_PPC_PASEMI=y
CONFIG_PPC_PASEMI_IOMMU=y
# CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set
CONFIG_PPC_PASEMI_MDIO=y
-CONFIG_ELECTRA_IDE=y
# CONFIG_PPC_CELLEB is not set
# CONFIG_PPC_PS3 is not set
# CONFIG_PPC_CELL is not set
@@ -663,6 +662,7 @@ CONFIG_PATA_PCMCIA=y
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set
CONFIG_PATA_PLATFORM=y
+CONFIG_PATA_OF_PLATFORM=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=y
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig
index b3458a1..348e061 100644
--- a/arch/powerpc/platforms/pasemi/Kconfig
+++ b/arch/powerpc/platforms/pasemi/Kconfig
@@ -37,13 +37,4 @@ config PPC_PASEMI_MDIO
help
Driver for MDIO via GPIO on PWRficient platforms
-config ELECTRA_IDE
- tristate "Electra IDE driver"
- default y
- depends on PPC_PASEMI && ATA
- select PATA_PLATFORM
- help
- This includes driver support for the Electra on-board IDE
- interface.
-
endmenu
diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile
index f47fcac..2cd2a4f 100644
--- a/arch/powerpc/platforms/pasemi/Makefile
+++ b/arch/powerpc/platforms/pasemi/Makefile
@@ -1,4 +1,3 @@
obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o
obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o
-obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o
obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o
diff --git a/arch/powerpc/platforms/pasemi/electra_ide.c b/arch/powerpc/platforms/pasemi/electra_ide.c
deleted file mode 100644
index 12fb0c9..0000000
--- a/arch/powerpc/platforms/pasemi/electra_ide.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2007 PA Semi, Inc
- *
- * Maintained by: Olof Johansson <olof@lixom.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/platform_device.h>
-
-#include <asm/prom.h>
-#include <asm/system.h>
-
-/* The electra IDE interface is incredibly simple: Just a device on the localbus
- * with interrupts hooked up to one of the GPIOs. The device tree contains the
- * address window and interrupt mappings already, and the pata_platform driver handles
- * the rest. We just need to hook the two up.
- */
-
-#define MAX_IFS 4 /* really, we have only one */
-
-static struct platform_device *pdevs[MAX_IFS];
-
-static int __devinit electra_ide_init(void)
-{
- struct device_node *np;
- struct resource r[3];
- int ret = 0;
- int i;
-
- np = of_find_compatible_node(NULL, "ide", "electra-ide");
- i = 0;
-
- while (np && i < MAX_IFS) {
- memset(r, 0, sizeof(r));
-
- /* pata_platform wants two address ranges: one for the base registers,
- * another for the control (altstatus). It's located at offset 0x3f6 in
- * the window, but the device tree only has one large register window
- * that covers both ranges. So we need to split it up by hand here:
- */
-
- ret = of_address_to_resource(np, 0, &r[0]);
- if (ret)
- goto out;
- ret = of_address_to_resource(np, 0, &r[1]);
- if (ret)
- goto out;
-
- r[1].start += 0x3f6;
- r[0].end = r[1].start-1;
-
- r[2].start = irq_of_parse_and_map(np, 0);
- r[2].end = irq_of_parse_and_map(np, 0);
- r[2].flags = IORESOURCE_IRQ;
-
- pr_debug("registering platform device at 0x%lx/0x%lx, irq is %ld\n",
- r[0].start, r[1].start, r[2].start);
- pdevs[i] = platform_device_register_simple("pata_platform", i, r, 3);
- if (IS_ERR(pdevs[i])) {
- ret = PTR_ERR(pdevs[i]);
- pdevs[i] = NULL;
- goto out;
- }
- np = of_find_compatible_node(np, "ide", "electra-ide");
- }
-out:
- return ret;
-}
-module_init(electra_ide_init);
-
-static void __devexit electra_ide_exit(void)
-{
- int i;
-
- for (i = 0; i < MAX_IFS; i++)
- if (pdevs[i])
- platform_device_unregister(pdevs[i]);
-}
-module_exit(electra_ide_exit);
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
-MODULE_DESCRIPTION("PA Semi Electra IDE driver");
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
index b7bc4e4..938f48a 100644
--- a/drivers/ata/pata_of_platform.c
+++ b/drivers/ata/pata_of_platform.c
@@ -34,11 +34,20 @@ static int __devinit pata_of_platform_probe(struct of_device *ofdev,
return -EINVAL;
}
- ret = of_address_to_resource(dn, 1, &ctl_res);
- if (ret) {
- dev_err(&ofdev->dev, "can't get CTL address from "
- "device tree\n");
- return -EINVAL;
+ if (of_device_is_compatible(dn, "electra-ide")) {
+ /* Altstatus is really at offset 0x3f6 from the primary window
+ * on electra-ide. Adjust ctl_res and io_res accordingly.
+ */
+ ctl_res = io_res;
+ ctl_res.start = ctl_res.start+0x3f6;
+ io_res.end = ctl_res.start-1;
+ } else {
+ ret = of_address_to_resource(dn, 1, &ctl_res);
+ if (ret) {
+ dev_err(&ofdev->dev, "can't get CTL address from "
+ "device tree\n");
+ return -EINVAL;
+ }
}
ret = of_irq_to_resource(dn, 0, &irq_res);
@@ -76,6 +85,7 @@ static int __devexit pata_of_platform_remove(struct of_device *ofdev)
static struct of_device_id pata_of_platform_match[] = {
{ .compatible = "ata-generic", },
+ { .compatible = "electra-ide", },
{},
};
MODULE_DEVICE_TABLE(of, pata_of_platform_match);
^ permalink raw reply related
* Re: [PATCH] fsl_soc: Fix get_immrbase() to use ranges, rather than reg.
From: Scott Wood @ 2008-01-15 16:40 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <BFCCA52A-85B7-4DD5-ACF4-2F3E65CFD7FD@kernel.crashing.org>
On Mon, Jan 14, 2008 at 08:37:27PM -0600, Kumar Gala wrote:
> >diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/
> >fsl_soc.c
> >index 3ace747..7502e03 100644
> >--- a/arch/powerpc/sysdev/fsl_soc.c
> >+++ b/arch/powerpc/sysdev/fsl_soc.c
> >@@ -54,10 +54,18 @@ phys_addr_t get_immrbase(void)
> > soc = of_find_node_by_type(NULL, "soc");
> > if (soc) {
> > int size;
> >- const void *prop = of_get_property(soc, "reg", &size);
> >+ u32 naddr;
> >+ const u32 *prop = of_get_property(soc, "#address-cells",
> >&size);
> >+
> >+ if (prop && size == 4)
> >+ naddr = *prop;
> >+ else
> >+ naddr = 2;
>
> Why default to two?
Because that's what the OF spec says the default is?
> >+ prop = of_get_property(soc, "ranges", &size);
> >+ if (prop && size == 12)
> >+ immrbase = of_translate_address(soc, prop + naddr);
Grr, I thought I removed the size == 12 check...
> >- if (prop)
> >- immrbase = of_translate_address(soc, prop);
>
> why not make your code an else case if we don't have reg?
Why?
> or something like, than we don't have to worry about adjust anything,
> and if you don't have any children its kinda a pointless device tree :)
It's not pointless, it's just incomplete.
> if (soc) {
> struct device_node *child = of_get_next_child(soc, NULL);
> if (child) {
> const void *prop = of_get_property(soc, "ranges",
> NULL);
> if (prop)
> immrbase = of_translate_address(child, prop);
> of_node_put(child);
> }
> of_node_put(soc);
> }
Why go out of our way to fail on a childless soc node?
-Scott
^ permalink raw reply
* Please pull pasemi.git for-2.6.25 branch
From: Olof Johansson @ 2008-01-15 17:01 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
Paul,
Please pull from 'for-2.6.25' branch of
master.kernel.org:/pub/scm/linux/kernel/git/olof/k.org.git for-2.6.25
to receive the following updates:
arch/powerpc/configs/pasemi_defconfig | 4
arch/powerpc/platforms/pasemi/Kconfig | 9 -
arch/powerpc/platforms/pasemi/Makefile | 1
arch/powerpc/platforms/pasemi/electra_ide.c | 96 ------------------
arch/powerpc/platforms/pasemi/idle.c | 5
arch/powerpc/platforms/pasemi/setup.c | 12 --
drivers/ata/Kconfig | 12 ++
drivers/ata/Makefile | 1
drivers/ata/pata_of_platform.c | 114 ++++++++++++++++++++++
drivers/ata/pata_platform.c | 144 ++++++++++++++++------------
include/linux/pata_platform.h | 9 +
11 files changed, 227 insertions(+), 180 deletions(-)
Anton Vorontsov (2):
libata: pata_platform: make probe and remove functions device type neutral
libata: pata_of_platform: OF-Platform PATA device driver
Grant Likely (1):
[POWERPC] pasemi: Use machine_*_initcall() hooks in platform code
Olof Johansson (2):
[POWERPC] pasemi: Fix NMI handling check
[POWERPC] pasemi: Move electra-ide to pata_of_platform
Thanks,
Olof
^ permalink raw reply
* Re: [DTC PATCH] libfdt: Add ft_get_next_node(), ft_get_next_prop(), and ft_getprop_offset().
From: Scott Wood @ 2008-01-15 16:52 UTC (permalink / raw)
To: jdl, linuxppc-dev
In-Reply-To: <20080115001657.GC20649@localhost.localdomain>
On Tue, Jan 15, 2008 at 11:16:57AM +1100, David Gibson wrote:
> On Mon, Jan 14, 2008 at 10:30:04AM -0600, Scott Wood wrote:
> > ft_get_next_node() enumerates children of a given node.
> > ft_get_next_prop() enumerates propreties of a given node.
> >
> > ft_getprop_offset() is like ft_getprop(), but takes a property offset rather
> > than a node offset and property name; it is primarily intended for use
> > with ft_get_next_prop().
>
> Urg... this kind of serves me right for not getting my act together on
> iterator functions yet. I really don't like this approach much. I'll
> see if I can come up with something I prefer this afternoon.
OK.
> The biggest thing I dislike is that I've deliberately avoided having
> any offsets-to-properties exposed to the library user. That's because
> the whole offsets change when you write the tree problem is worse for
> properties than nodes (in that likely idiomatic uses will be bitten by
> changes in property offsets).
We can drop the property iteration for now; I wrote it for an attempt at
node merging which I postponed.
> > + if (depth != 0)
> > + return -FDT_ERR_BADSTRUCTURE;
>
> I think this should be FDT_ERR_TRUNCATED.
I'd expect TRUNCATED when we hit totalsize without an FDT_END, not when
we hit FDT_END in an inappropriate context.
> > + return -FDT_ERR_NOTFOUND;
>
> In fact, so should this. This function should never actually reach
> the FDT_END tag.
No, it's valid if you're iterating over all nodes (node -1, depth -1).
> > +#define FDT_ERR_BADDEPTH 8
> > + /* FDT_ERR_BADDEPTH: Function was passed a negative
> > + * (or otherwise invalid) depth. */
>
> You've added this error code, but you don't actually return it
> anywhere...
Oops, it must have been from the aforementioned node merging code, and I
thought it was from fdt_get_next_node when splitting things up.
> This description is incorrect - you've copied the fdt_getprop()
> description and forgotten to update it.
/me hides in shame
-Scott
^ permalink raw reply
* Re: PPC vs POWERPC
From: Jon Loeliger @ 2008-01-15 17:01 UTC (permalink / raw)
To: Matias Sundman; +Cc: linuxppc-embedded@ozlabs.org
In-Reply-To: <478C8D38.3090602@sundmangroup.com>
On Tue, 2008-01-15 at 04:38, Matias Sundman wrote:
> >>Documentation/powerpc/booting-without-of.txt to find out what is
> >>expected in the device tree.
>
> Is there any more information on how the "of_*" ( e.g. of_node_put ,
> of_find_node_by_type ) functions should be implemented in the
> "arch/powerpc/platforms/myplatform/myboard_setup.c" file
> or is the documentation the existing "*.c" c files under
> arch/powerpc/platforms ?
>
> Since I have a 82xx board I assume that "myboard_setup.c" file shall be
> put under arch/powerpc/platforms/82xx.
Maybe. Which 82xx is it? There is a notable difference
between, say, the 824x boards and the 827x boards. If it
is the latter, perhaps the existing 82xx/ pq2 or mpc8272
parts are already sufficient?
If it is the former group, 824x, perhaps some of the parts
in embedded6xx/ are usable? Also note that I am working on
publishing an 824x StorCenter port under embedded6xx/ at
this time as well. First patches were posted to linuxppc-dev
list at ozlabs.org.
HTH,
jdl
^ permalink raw reply
* MPC5200B SPI codec error when there is a heavy ethernet traffic.
From: Txema Lopez @ 2008-01-15 16:44 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 1285 bytes --]
Hi all,
We have a MPC5200B based custom board running a 2.4.25 Denx linux
kernel. We use the PSC6 in SPI-codec mode to exchange some bytes
periodically in full-duplex with a peripheral.
In 'normal' conditions this communication runs fine. But when we start
sending packets over the Ethernet as a background activity, we see on
the oscilloscope that one of the SPI transfers is interrupted. Not only
that the SPI clock stops, something that could happen in the case that
the transmission Fifo is empty, or the reception Fifo is full, but that
the chip select actually goes high for an instant, causing the
peripheral to abort the communication.
We have reproduced the same bug in a Lite5200B using the spi-dev driver
and a user application, so it seams it's not a problem of our hardware.
The problem only arises if there is some heavy Ethernet traffic (a big
file ftp transfer or a big file copy by nfs) , so we think the error is
related with the Bestcomm activity. We have contacted freescale to check
if it's a microprocessor bug and they are looking into it. But we think
it could be also a bug in the Bestcomm programming of the FEC tasks.
Could be it possible? At this point, we really need some help. Any clue
will be welcomed.
Best regards,
Txema
[-- Attachment #2: tlopez.vcf --]
[-- Type: text/x-vcard, Size: 324 bytes --]
begin:vcard
fn:Jose Maria Lopez
n:Lopez;Jose Maria
org:Fagor Automation S. Coop.
adr:;;San Andres 19. Apdo. 144;Arrasate-Mondragon;;20500;Spain
email;internet:tlopez@aotek.es
title:Sotware engineer
tel;work:(34) 943719200
tel;fax:(34) 943791712
x-mozilla-html:FALSE
url:http://www.fagorautomation.es
version:2.1
end:vcard
^ permalink raw reply
* Re: PPC vs POWERPC
From: Scott Wood @ 2008-01-15 17:07 UTC (permalink / raw)
To: Jon Loeliger; +Cc: Matias Sundman, linuxppc-embedded@ozlabs.org
In-Reply-To: <1200416484.14540.5.camel@ld0161-tx32>
On Tue, Jan 15, 2008 at 11:01:33AM -0600, Jon Loeliger wrote:
> If it is the former group, 824x, perhaps some of the parts
> in embedded6xx/ are usable?
Not all 824x fall into that category; for example, 8248 is pq2. Someone
in marketing should be shot.
-Scott
^ permalink raw reply
* Re: [PATCH] fsl_soc: Fix get_immrbase() to use ranges, rather than reg.
From: Kumar Gala @ 2008-01-15 17:07 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <20080115164053.GA10812@ld0162-tx32.am.freescale.net>
On Jan 15, 2008, at 10:40 AM, Scott Wood wrote:
> On Mon, Jan 14, 2008 at 08:37:27PM -0600, Kumar Gala wrote:
>>> diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/
>>> fsl_soc.c
>>> index 3ace747..7502e03 100644
>>> --- a/arch/powerpc/sysdev/fsl_soc.c
>>> +++ b/arch/powerpc/sysdev/fsl_soc.c
>>> @@ -54,10 +54,18 @@ phys_addr_t get_immrbase(void)
>>> soc = of_find_node_by_type(NULL, "soc");
>>> if (soc) {
>>> int size;
>>> - const void *prop = of_get_property(soc, "reg", &size);
>>> + u32 naddr;
>>> + const u32 *prop = of_get_property(soc, "#address-cells",
>>> &size);
>>> +
>>> + if (prop && size == 4)
>>> + naddr = *prop;
>>> + else
>>> + naddr = 2;
>>
>> Why default to two?
>
> Because that's what the OF spec says the default is?
fair.
>>> + prop = of_get_property(soc, "ranges", &size);
>>> + if (prop && size == 12)
>>> + immrbase = of_translate_address(soc, prop + naddr);
>
> Grr, I thought I removed the size == 12 check...
>
>>> - if (prop)
>>> - immrbase = of_translate_address(soc, prop);
>>
>> why not make your code an else case if we don't have reg?
>
> Why?
I agree (had to think about it a bit more).
>> or something like, than we don't have to worry about adjust anything,
>> and if you don't have any children its kinda a pointless device
>> tree :)
>
> It's not pointless, it's just incomplete.
>
>> if (soc) {
>> struct device_node *child = of_get_next_child(soc, NULL);
>> if (child) {
>> const void *prop = of_get_property(soc, "ranges",
>> NULL);
>> if (prop)
>> immrbase = of_translate_address(child, prop);
>> of_node_put(child);
>> }
>> of_node_put(soc);
>> }
>
> Why go out of our way to fail on a childless soc node?
do we see any case in which we'd have a childless soc node?
I'm just concerned about make sure this works for all the various
cases of #address-cells and #size-cells.
- k
^ permalink raw reply
* Re: PPC vs POWERPC
From: Jon Loeliger @ 2008-01-15 17:14 UTC (permalink / raw)
To: Scott Wood; +Cc: Matias Sundman, linuxppc-embedded@ozlabs.org
In-Reply-To: <20080115170723.GA10988@ld0162-tx32.am.freescale.net>
On Tue, 2008-01-15 at 11:07, Scott Wood wrote:
> On Tue, Jan 15, 2008 at 11:01:33AM -0600, Jon Loeliger wrote:
> > If it is the former group, 824x, perhaps some of the parts
> > in embedded6xx/ are usable?
>
> Not all 824x fall into that category; for example, 8248 is pq2.
Gah. Of course.
> Someone in marketing should be shot.
Photos, bullets or heroin? :-)
jdl
^ permalink raw reply
* Re: [PATCH 1/4] powerpc: mv64x60 - Use early_* PCI accessors for hotswap reg
From: Mark A. Greer @ 2008-01-15 17:20 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: linuxppc-dev
In-Reply-To: <20080115101936.d186329d.sfr@canb.auug.org.au>
On Tue, Jan 15, 2008 at 10:19:36AM +1100, Stephen Rothwell wrote:
> Hi Mark,
Hi Stephen. Thanks for taking the time to review these patches.
> On Mon, 14 Jan 2008 15:51:50 -0700 "Mark A. Greer" <mgreer@mvista.com> wrote:
> >
> > +static inline struct pci_controller *mv64x60_find_hose(u32 idx)
> > +{
> > + struct device_node *phb;
> > + struct pci_controller *hose;
> > + const u32 *prop;
> > + int len;
> > +
> > + for_each_compatible_node(phb, "pci", "marvell,mv64360-pci") {
> > + prop = of_get_property(phb, "cell-index", &len);
> > + if (prop && (len == sizeof(prop)) && (*prop == idx)) {
> > + hose = pci_find_hose_for_OF_device(phb);
> > + of_node_put(phb);
> > + return hose;
> > + }
> > + }
> > +
> > + return NULL;
> > +}
>
> I would think that this is way to big to inline ...
Yeah, I suppose. I'm not sure why I made it an inline, TBH. I'll make
it a "real" routine.
Mark
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox