* [PATCH 0/5] powerpc: feature fixup updates
From: Benjamin Herrenschmidt @ 2006-10-13 8:04 UTC (permalink / raw)
To: linuxppc-dev list
Here's a new batch of the feature fixup updates.
Changes since last time:
- moves identify_cpu() to C code (removes more assembly gunk)
- works on 32 bits :)
- invert use of nested in MFTB for the cell fixup
- adds a patch for fixup in modules support
- the fixup code does 2 loops as suggested by Olof
The bulk could be merged if you want, except the cell TB fix which still
needs to change to the new workaround method. I haven't had time to
finish that today.
^ permalink raw reply
* Re: Recently removed io accessors
From: Benjamin Herrenschmidt @ 2006-10-13 7:31 UTC (permalink / raw)
To: Peter Korsgaard; +Cc: sfr, linuxppc-dev
In-Reply-To: <87iriovh3x.fsf@sleipner.barco.com>
On Fri, 2006-10-13 at 08:56 +0200, Peter Korsgaard wrote:
> >>>>> "BH" == Benjamin Herrenschmidt <benh@kernel.crashing.org> writes:
>
> Hi,
>
> >> Any chance of getting them back or should I implement a (slower)
> >> loop myself before submitting the patch?
>
> BH> Well, a "packet buffer" should have no endian. When streaming in
> BH> our out a fifo, you basically stream bytes that happen to come out
> BH> 2 at a time. So unless somebody wired the hardware backward, you
> BH> should do no swapping when using the fifo.
>
> I agree in principle, but the issue gets complicated by the fact that
> the chip works in chunks of 32bit, but the 911{5..7} chips only have a
> 16bit interface to lower costs, and that the chip has a builtin endian
> swap feature (which works for all direct registers, but apparently not
> for the packet buffers).
>
> The memory controller automatically translates a 32bit access to two
> 16 bit accesses.
Well, that is not necessarily broken :)
> You could be right that the hw people screwed something up, but that
> doesn't help much once there's units in the field :/
Well, I still don't see it. It all depends how the HW has been wired I
suppose but you should not need byteswap regardless of the 32 bits being
broken in packs of 2x16 bits or whatever... If the chip has a HW
byteswap for registers and not for the packet buffer, that makes it even
more clear that such swapping should not be necessary.
Unless the chip has been wired backward on the processor bus (in which
case, btw, DMA will not work either unless you have one of those
magically swapping dma controllers)..
So I still claim that you should not need them and if you do, then the
chip has probably been incorrect wired to your CPU bus. In which case,
you can either grab an old copy of the functions and put them in your
driver for your platform or add a cpu_to_leXX() loop to byteswap the
data in/out, but it's probably not the right thing to do in the generic
driver since it would be a problem specific to your board.
Unless I'm missing something ... It would be useful to have more details
about your setup.
Cheers.
Ben.
^ permalink raw reply
* Re: [PATCH] Xilinx UART Lite 2.6.18 driver
From: Peter Korsgaard @ 2006-10-13 7:22 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <452F3A82.7070803@dlasys.net>
>>>>> "David" == David H Lynch <dhlii@dlasys.net> writes:
Hi,
David> Nobody has given me a reason yet why the UartLite should
David> init different from the 8250, and absent a reason, I would
David> mimic the 8250. I do not think there is reason for a different
David> routing name. The ml403 8250 init code deals with multiple
David> 8250's, I did the same with UartLite.
8250 is not the only serial driver. I think the reason why 8250 uses
it's own struct is simple that it's a really old driver. Newer drivers
like atmel_serial.c also uses the platform bus.
David> I am not sure I did nto follow everything on linux-serial -
David> but I think Peter was asked to remove support for additional
David> uarts. I am not sure why.
Remove support? I don't remember anything about that.
--
Bye, Peter Korsgaard
^ permalink raw reply
* Re: [PATCH] Xilinx UART Lite 2.6.18 driver
From: Peter Korsgaard @ 2006-10-13 7:15 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <452F36AE.6040205@dlasys.net>
>>>>> "David" == David H Lynch <dhlii@dlasys.net> writes:
Hi,
David> Peter's driver uses the IORESOURCE requests to pull platform
David> data. Most other serial platformdevices pull a uart_port
David> object. My limited understanding of IORESOURCE is that it is
David> not sufficiently deep to support the parameters that are needed
David> to support UartLite such as a DCR flag and a regoffset.
I'm still not convinced that DCR access and variable register offsets
are needed - But it can always be added (through a seperate struct in
platform_data) - Patches are welcome.
The same with interrupt-less support if the changes are not too
intrusive.
David> You are welcome to do that. I already patched his driver to
David> work with my early console support as well as adding the
David> boot-bash stuff similar to yours. But I gave up actually using
David> it when I could not get it to work.
Which is odd as I've gotten positive feedback from others.
David> Next time I get an opportunity I am going to try to setup an
David> ml403 to atleast verify that Peter's driver is working there.
Great.
--
Bye, Peter Korsgaard
^ permalink raw reply
* Re: [PATCH] Xilinx UART Lite 2.6.18 driver
From: Peter Korsgaard @ 2006-10-13 7:11 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <609d5c8e0610122221i7c5e5049n4db5fcf3f61bd132@mail.gmail.com>
>>>>> "David" == David Bolcsfoldi <dbolcsfoldi@gmail.com> writes:
David> Here's an initial patch based on a modified uartlite (by Peter
David> Korsgaard), it's by no means ment to be final and any feedback
David> would be appreciated.
Could you make it relative to my driver so the changes are easier to
see?
David> - readb/writeb to in_be32/out_be32.
David> For some reason on my board the readb and writeb don't behave
David> correctly when reading and writing to the uartlite device. I
David> haven't looked into it but if this is unacceptable I will try
David> to revert to readb/writeb.
The PPC is big endian - Did you remember to add 3 to your base
address?
--
Bye, Peter Korsgaard
^ permalink raw reply
* Re: [PATCH] Xilinx UART Lite 2.6.18 driver
From: David H. Lynch Jr. @ 2006-10-13 7:04 UTC (permalink / raw)
To: David Bolcsfoldi; +Cc: linuxppc-embedded
In-Reply-To: <609d5c8e0610122221i7c5e5049n4db5fcf3f61bd132@mail.gmail.com>
David Bolcsfoldi wrote:
> Here's an initial patch based on a modified uartlite (by Peter
> Korsgaard), it's by no means ment to be final and any feedback would
> be appreciated.
>
> What I have changed:
>
> - Early console support.
>
> Since the platform bus isn't initialized by the time the first printk
> comes I've added a call 'early_uart_get_pdev' fashioned after the CPM
> serial driver.
>
If you want to mess with this my recomendation would be to switch to
passing a uart_port
like the 8250 does. You can find 8250 early serial init code in
xilinx_ml403.c
I beleive the init routine is called early_console_init().
Nobody has given me a reason yet why the UartLite should init
different from the 8250,
and absent a reason, I would mimic the 8250. I do not think there is
reason for a different routing name.
The ml403 8250 init code deals with multiple 8250's, I did the same
with UartLite.
I am not sure I did nto follow everything on linux-serial - but I
think Peter was asked to remove support
for additional uarts. I am not sure why.
> - Platform device.
>
> The 'uartlite' is now a platform device although I am not entirely
> happy how this is done since there's only one VIRTEX_UARTLITE device
> with id of 0 although there might be several more described by the
> plafrom_data. Maybe the additional devices can be added to the
> platform bus in the probe call or would it be better to add these
> devices at compile time to the list of platform_devices in virtex.c?
>
> - readb/writeb to in_be32/out_be32.
>
> For some reason on my board the readb and writeb don't behave
> correctly when reading and writing to the uartlite device. I haven't
> looked into it but if this is unacceptable I will try to revert to
> readb/writeb.
>
I would appreciate some further elaboration. I think they were
working for me when I tried Peter's driver.
I even think that is one change I made to my own driver based on
Peter's.
But maybe I am wrong and that has something to do with my inability
to get Peter's driver working on my hardware.
> - Embedded boot serial support.
>
> There's now support for embedded boot serial I/O over uartlite device 0.
>
> - uartlite.h
>
To be consistent with other uarts I think it should be
include/linux/serial_uartlite.h
> A shared header file between the embedded boot serial driver and the
> real one with all the reg offsets and such. I don't know if the
> location for this file is ok though.
>
Finally, I think that this really needs submitted to linux-serial if
you are looking to get it in.
> diff -urN 2.6.18/arch/ppc/boot/common/misc-common.c
> patched-uartlite/arch/ppc/boot/common/misc-common.c
> --- 2.6.18/arch/ppc/boot/common/misc-common.c 2006-10-04
> 14:31:15.000000000 -0700
> +++ patched-uartlite/arch/ppc/boot/common/misc-common.c 2006-10-12
> 12:47:31.000000000 -0700
> @@ -57,7 +57,8 @
>
Just a minor nit, but you can make the patches simpler by adding
SERIAL_UARTLITE_CONSOLE into the middle of the list instead of the end.
> #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
> || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
> - || defined(CONFIG_SERIAL_MPSC_CONSOLE)
> + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
> + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
> extern unsigned long com_port;
>
> extern int serial_tstc(unsigned long com_port);
> @@ -80,7 +81,8 @@
> {
> #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
> || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
> - || defined(CONFIG_SERIAL_MPSC_CONSOLE)
> + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
> + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
> if(keyb_present)
> return (CRT_tstc() || serial_tstc(com_port));
> else
> @@ -95,7 +97,8 @@
> while (1) {
> #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
> || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
> - || defined(CONFIG_SERIAL_MPSC_CONSOLE)
> + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
> + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
> if (serial_tstc(com_port))
> return (serial_getc(com_port));
> #endif /* serial console */
> @@ -112,7 +115,8 @@
>
> #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
> || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
> - || defined(CONFIG_SERIAL_MPSC_CONSOLE)
> + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
> + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
> serial_putc(com_port, c);
> if ( c == '\n' )
> serial_putc(com_port, '\r');
> @@ -161,7 +165,8 @@
> while ( ( c = *s++ ) != '\0' ) {
> #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
> || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
> - || defined(CONFIG_SERIAL_MPSC_CONSOLE)
> + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
> + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
> serial_putc(com_port, c);
> if ( c == '\n' ) serial_putc(com_port, '\r');
> #endif /* serial console */
> diff -urN 2.6.18/arch/ppc/boot/simple/Makefile
> patched-uartlite/arch/ppc/boot/simple/Makefile
> --- 2.6.18/arch/ppc/boot/simple/Makefile 2006-10-04 14:31:15.000000000 -0700
> +++ patched-uartlite/arch/ppc/boot/simple/Makefile 2006-10-12
> 12:45:53.000000000 -0700
> @@ -205,6 +205,7 @@
> endif
> boot-$(CONFIG_SERIAL_MPC52xx_CONSOLE) += mpc52xx_tty.o
> boot-$(CONFIG_SERIAL_MPSC_CONSOLE) += mv64x60_tty.o
> +boot-$(CONFIG_SERIAL_UARTLITE_CONSOLE) += uartlite_tty.o
>
> LIBS := $(common)/lib.a $(bootlib)/lib.a
> ifeq ($(CONFIG_PPC_PREP),y)
> diff -urN 2.6.18/arch/ppc/boot/simple/misc.c
> patched-uartlite/arch/ppc/boot/simple/misc.c
> --- 2.6.18/arch/ppc/boot/simple/misc.c 2006-10-04 14:31:15.000000000 -0700
> +++ patched-uartlite/arch/ppc/boot/simple/misc.c 2006-10-12
> 12:48:01.000000000 -0700
> @@ -48,7 +48,8 @@
> #if (defined(CONFIG_SERIAL_8250_CONSOLE) \
> || defined(CONFIG_VGA_CONSOLE) \
> || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
> - || defined(CONFIG_SERIAL_MPSC_CONSOLE)) \
> + || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
> + || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)) \
> && !defined(CONFIG_GEMINI)
> #define INTERACTIVE_CONSOLE 1
> #endif
> diff -urN 2.6.18/arch/ppc/boot/simple/uartlite_tty.c
> patched-uartlite/arch/ppc/boot/simple/uartlite_tty.c
> --- 2.6.18/arch/ppc/boot/simple/uartlite_tty.c 1969-12-31
> 16:00:00.000000000 -0800
> +++ patched-uartlite/arch/ppc/boot/simple/uartlite_tty.c 2006-10-12
> 22:10:44.000000000 -0700
> @@ -0,0 +1,69 @@
> +/*
> + * Xilinx UART Lite support.
> + * Right now it only works over UART0 and none other.
> + *
> + * Copyright (C) 2006 David Bolcsfoldi <dbolcsfoldi@gmail.com>
> + *
> + * 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.
> + */
> +
> +#include <asm/io.h>
> +#include <asm/uartlite.h>
> +#include <platforms/4xx/xparameters/xparameters.h>
> +
> +static inline int is_xmit_full(unsigned int address)
> +{
> + return ((in_be32((volatile unsigned *) (address + ULITE_STATUS)) &
> ULITE_STATUS_TXFULL) == ULITE_STATUS_TXFULL);
> +}
> +
> +static inline int is_recv_empty(unsigned int address)
> +{
> + return ((in_be32((volatile unsigned *) (address + ULITE_STATUS)) &
> ULITE_STATUS_RXVALID) != ULITE_STATUS_RXVALID);
> +}
> +
> +unsigned long serial_init(int chan, void *ignored)
> +{
> + switch (chan) {
> + #ifdef XPAR_XUL_UART_0_BASEADDR
> + case 0:
> + return XPAR_XUL_UART_0_BASEADDR;
> + #endif
> + #ifdef XPAR_XUL_UART_1_BASEADDR
> + case 1:
> + return XPAR_XUL_UART_1_BASEADDR;
> + #endif
> + #ifdef XPAR_XUL_UART_2_BASEADDR
> + case 2:
> + return XPAR_XUL_UART_2_BASEADDR;
> + #endif
> + #ifdef XPAR_XUL_UART_3_BASEADDR
> + case 3:
> + return XPAR_XUL_UART_3_BASEADDR;
> + #endif
> + default:
> + goto out;
> + }
> +
> +out:
> + return -1;
> +}
> +
> +void serial_putc(unsigned long com_port, unsigned char c)
> +{
> + while(is_xmit_full(XPAR_XUL_UART_0_BASEADDR));
> + out_be32((volatile unsigned *) (XPAR_XUL_UART_0_BASEADDR + ULITE_TX), c);
> +}
> +
> +unsigned char serial_getc(unsigned long com_port)
> +{
> + while(is_recv_empty(XPAR_XUL_UART_0_BASEADDR));
> + return in_be32((volatile unsigned *) (XPAR_XUL_UART_0_BASEADDR + ULITE_RX));
> +}
> +
> +int serial_tstc(unsigned long com_port)
> +{
> + return !(is_recv_empty(XPAR_XUL_UART_0_BASEADDR));
> +}
> +
> Binary files 2.6.18/arch/ppc/boot/simple/.uartlite_tty.c.swp and
> patched-uartlite/arch/ppc/boot/simple/.uartlite_tty.c.swp differ
> diff -urN 2.6.18/arch/ppc/platforms/4xx/virtex.c
> patched-uartlite/arch/ppc/platforms/4xx/virtex.c
> --- 2.6.18/arch/ppc/platforms/4xx/virtex.c 2006-10-04 14:31:15.000000000 -0700
> +++ patched-uartlite/arch/ppc/platforms/4xx/virtex.c 2006-10-12
> 16:37:23.000000000 -0700
> @@ -46,11 +46,71 @@
> { }, /* terminated by empty record */
> };
>
> +#define XPAR_UARTLITE(num) { \
> + .mapbase = XPAR_XUL_UART_##num##_BASEADDR, \
> + .irq = XPAR_INTC_0_XUL_UART_##num##_VEC_ID, \
> + .size = (XPAR_XUL_UART_##num##_HIGHADDR -
> XPAR_XUL_UART_##num##_BASEADDR) + 1, \
> + .baud = XPAR_XUL_UART_##num##_BAUDRATE, \
> + .bits = XPAR_XUL_UART_##num##_DATA_BITS, \
> + .parity = XPAR_XUL_UART_##num##_USE_PARITY, \
> + .odd_parity = XPAR_XUL_UART_##num##_ODD_PARITY, \
> +}
> +
> +struct plat_uartlite_port uartlite_platform_data[] = {
> +#ifdef XPAR_XUL_UART_0_BASEADDR
> + XPAR_UARTLITE(0),
> +#endif
> +#ifdef XPAR_XUL_UART_1_BASEADDR
> + XPAR_UARTLITE(1),
> +#endif
> +#ifdef XPAR_XUL_UART_2_BASEADDR
> + XPAR_UARTLITE(2),
> +#endif
> +#ifdef XPAR_XUL_UART_3_BASEADDR
> + XPAR_UARTLITE(3),
> +#endif
> + { }, /* terminated by empty record */
> +};
> +
> struct platform_device ppc_sys_platform_devices[] = {
> [VIRTEX_UART] = {
> .name = "serial8250",
> .id = 0,
> .dev.platform_data = serial_platform_data,
> },
> +
> + [VIRTEX_UARTLITE] = {
> + .name = "uartlite",
> + .id = 0,
> + .dev.platform_data = uartlite_platform_data,
> +#ifdef XPAR_XUL_UART_0_BASEADDR
> + .num_resources = 2,
> + .resource = (struct resource[]) {
> + {
> + .start = XPAR_XUL_UART_0_BASEADDR,
> + .end = XPAR_XUL_UART_0_HIGHADDR,
> + .flags = IORESOURCE_MEM,
> + },
> + {
> + .start = XPAR_INTC_0_XUL_UART_0_VEC_ID,
> + .end = XPAR_INTC_0_XUL_UART_0_VEC_ID,
> + .flags = IORESOURCE_IRQ,
> + },
> + },
> +#endif /* XPAR_XUL_UART_0_BASEADDR */
> + },
> };
>
> +/* For early console on the uartlite serial port some way of
> + * getting to the platform_device is needed */
> +
> +struct platform_device* early_uart_get_pdev(int dev)
> +{
> + if (dev < 0 ||
> + dev >= NUM_PPC_SYS_DEVS) {
> + return NULL;
> + }
> +
> + return &ppc_sys_platform_devices[dev];
> +}
> +
> diff -urN 2.6.18/arch/ppc/platforms/4xx/virtex.h
> patched-uartlite/arch/ppc/platforms/4xx/virtex.h
> --- 2.6.18/arch/ppc/platforms/4xx/virtex.h 2006-10-04 14:31:15.000000000 -0700
> +++ patched-uartlite/arch/ppc/platforms/4xx/virtex.h 2006-10-12
> 16:37:41.000000000 -0700
> @@ -27,8 +27,21 @@
> /* Device type enumeration for platform bus definitions */
> #ifndef __ASSEMBLY__
> enum ppc_sys_devices {
> - VIRTEX_UART, NUM_PPC_SYS_DEVS,
> + VIRTEX_UART,
> + VIRTEX_UARTLITE,
> + NUM_PPC_SYS_DEVS,
> };
> +
> +struct plat_uartlite_port {
> + unsigned int mapbase;
> + unsigned int irq;
> + unsigned int size;
> + unsigned int baud;
> + unsigned char bits;
> + unsigned char parity;
> + unsigned char odd_parity;
> +};
> +
> #endif
>
> #endif /* __ASM_VIRTEX_H__ */
> diff -urN 2.6.18/arch/ppc/platforms/4xx/xilinx_ml403.c
> patched-uartlite/arch/ppc/platforms/4xx/xilinx_ml403.c
> --- 2.6.18/arch/ppc/platforms/4xx/xilinx_ml403.c 2006-10-04
> 14:31:15.000000000 -0700
> +++ patched-uartlite/arch/ppc/platforms/4xx/xilinx_ml403.c 2006-10-12
> 13:15:36.000000000 -0700
> @@ -65,10 +65,11 @@
> .ppc_sys_name = "Xilinx ML403 Reference Design",
> .mask = 0x00000000,
> .value = 0x00000000,
> - .num_devices = 1,
> + .num_devices = 2,
> .device_list = (enum ppc_sys_devices[])
> {
> VIRTEX_UART,
> + VIRTEX_UARTLITE,
> },
> },
> };
> diff -urN 2.6.18/drivers/serial/Kconfig patched-uartlite/drivers/serial/Kconfig
> --- 2.6.18/drivers/serial/Kconfig 2006-10-04 14:31:18.000000000 -0700
> +++ patched-uartlite/drivers/serial/Kconfig 2006-10-12 12:15:32.000000000 -0700
> @@ -511,6 +511,25 @@
> your boot loader (lilo or loadlin) about how to pass options to the
> kernel at boot time.)
>
> +config SERIAL_UARTLITE
> + tristate "Xilinx uartlite serial port support"
> + depends on PPC32
> + select SERIAL_CORE
> + help
> + Say Y here if you want to use the Xilinx uartlite serial controller.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called uartlite.ko.
> +
> +config SERIAL_UARTLITE_CONSOLE
> + bool "Support for console on Xilinx uartlite serial port"
> + depends on SERIAL_UARTLITE=y
> + select SERIAL_CORE_CONSOLE
> + help
> + Say Y here if you wish to use a Xilinx uartlite as the system
> + console (the system console is the device which receives all kernel
> + messages and warnings and which allows logins in single user mode).
> +
> config SERIAL_SUNCORE
> bool
> depends on SPARC
> diff -urN 2.6.18/drivers/serial/Makefile
> patched-uartlite/drivers/serial/Makefile
> --- 2.6.18/drivers/serial/Makefile 2006-10-04 14:31:18.000000000 -0700
> +++ patched-uartlite/drivers/serial/Makefile 2006-10-12 12:15:32.000000000 -0700
> @@ -55,4 +55,5 @@
> obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
> obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
> obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
> +obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
> obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
> diff -urN 2.6.18/drivers/serial/uartlite.c
> patched-uartlite/drivers/serial/uartlite.c
> --- 2.6.18/drivers/serial/uartlite.c 1969-12-31 16:00:00.000000000 -0800
> +++ patched-uartlite/drivers/serial/uartlite.c 2006-10-12
> 22:10:57.000000000 -0700
> @@ -0,0 +1,551 @@
> +/*
> + * uartlite.c: Serial driver for Xilinx uartlite serial controller
> + *
> + * Peter Korsgaard <jacmet@sunsite.dk>
> + *
> + * 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.
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/console.h>
> +#include <linux/serial.h>
> +#include <linux/serial_core.h>
> +#include <linux/tty.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <asm/io.h>
> +#include <asm/uartlite.h>
> +
> +#define ULITE_MAJOR 204
> +#define ULITE_MINOR 187
> +#define ULITE_NR_UARTS 4
> +
> +static struct uart_port ports[ULITE_NR_UARTS];
> +
> +/* Place-holder for board-specific stuff */
> +struct platform_device* __attribute__ ((weak)) __init
> +early_uart_get_pdev(int index)
> +{
> + return NULL;
> +}
> +
> +static int ulite_receive(struct uart_port *port, int stat)
> +{
> + struct tty_struct *tty = port->info->tty;
> + unsigned char ch = 0;
> + char flag = TTY_NORMAL;
> +
> + if ((stat & (ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
> + | ULITE_STATUS_FRAME)) == 0)
> + return 0;
> +
> + /* stats */
> + if (stat & ULITE_STATUS_RXVALID) {
> + port->icount.rx++;
> + ch = in_be32((unsigned volatile *) (port->membase + ULITE_RX));
> +
> + if (stat & ULITE_STATUS_PARITY)
> + port->icount.parity++;
> + }
> +
> + if (stat & ULITE_STATUS_OVERRUN)
> + port->icount.overrun++;
> +
> + if (stat & ULITE_STATUS_FRAME)
> + port->icount.frame++;
> +
> +
> + /* drop byte with parity error if IGNPAR specificed */
> + if (stat & port->ignore_status_mask & ULITE_STATUS_PARITY)
> + stat &= ~ULITE_STATUS_RXVALID;
> +
> + stat &= port->read_status_mask;
> +
> + if (stat & ULITE_STATUS_PARITY)
> + flag = TTY_PARITY;
> +
> +
> + stat &= ~port->ignore_status_mask;
> +
> + if (stat & ULITE_STATUS_RXVALID)
> + tty_insert_flip_char(tty, ch, flag);
> +
> + if (stat & ULITE_STATUS_FRAME)
> + tty_insert_flip_char(tty, 0, TTY_FRAME);
> +
> + if (stat & ULITE_STATUS_OVERRUN)
> + tty_insert_flip_char(tty, 0, TTY_OVERRUN);
> +
> + return 1;
> +}
> +
> +static int ulite_transmit(struct uart_port *port, int stat)
> +{
> + struct circ_buf *xmit = &port->info->xmit;
> +
> + if (stat & ULITE_STATUS_TXFULL)
> + return 0;
> +
> + if (port->x_char) {
> + out_be32((unsigned volatile *) (port->membase + ULITE_TX), port->x_char);
> + port->x_char = 0;
> + port->icount.tx++;
> + return 1;
> + }
> +
> + if (uart_circ_empty(xmit) || uart_tx_stopped(port))
> + return 0;
> +
> + out_be32((unsigned volatile *) (port->membase + ULITE_TX),
> xmit->buf[xmit->tail]);
> + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
> + port->icount.tx++;
> +
> + /* wake up */
> + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
> + uart_write_wakeup(port);
> +
> + return 1;
> +}
> +
> +static irqreturn_t ulite_isr(int irq, void *dev_id, struct pt_regs *regs)
> +{
> + struct uart_port *port = (struct uart_port *)dev_id;
> + int busy;
> +
> + spin_lock(&port->lock); /* Lock the port in case of printk */
> +
> + do {
> + int stat = in_be32((unsigned volatile *) (port->membase + ULITE_STATUS));
> + busy = ulite_receive(port, stat);
> + busy |= ulite_transmit(port, stat);
> + } while (busy);
> +
> + spin_unlock(&port->lock);
> +
> + tty_flip_buffer_push(port->info->tty);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static unsigned int ulite_tx_empty(struct uart_port *port)
> +{
> + unsigned long flags;
> + unsigned int ret;
> +
> + spin_lock_irqsave(&port->lock, flags);
> + ret = in_be32((unsigned volatile *) (port->membase + ULITE_STATUS));
> + spin_unlock_irqrestore(&port->lock, flags);
> +
> + return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
> +}
> +
> +static unsigned int ulite_get_mctrl(struct uart_port *port)
> +{
> + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
> +}
> +
> +static void ulite_set_mctrl(struct uart_port *port, unsigned int mctrl)
> +{
> + /* N/A */
> +}
> +
> +static void ulite_stop_tx(struct uart_port *port)
> +{
> + /* N/A */
> +}
> +
> +static void ulite_start_tx(struct uart_port *port)
> +{
> + ulite_transmit(port, in_be32((unsigned volatile *) (port->membase +
> ULITE_STATUS)));
> +}
> +
> +static void ulite_stop_rx(struct uart_port *port)
> +{
> + /* don't forward any more data (like !CREAD) */
> + port->ignore_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY
> + | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
> +}
> +
> +static void ulite_enable_ms(struct uart_port *port)
> +{
> + /* N/A */
> +}
> +
> +static void ulite_break_ctl(struct uart_port *port, int ctl)
> +{
> + /* N/A */
> +}
> +
> +static int ulite_startup(struct uart_port *port)
> +{
> + int ret;
> +
> + ret = request_irq(port->irq, ulite_isr,
> + IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "uartlite", port);
> + if (ret)
> + return ret;
> +
> + out_be32((unsigned volatile *) (port->membase + ULITE_CONTROL),
> ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
> + out_be32((unsigned volatile *) (port->membase + ULITE_CONTROL),
> ULITE_CONTROL_IE);
> +
> + return 0;
> +}
> +
> +static void ulite_shutdown(struct uart_port *port)
> +{
> + writeb(0, port->membase + ULITE_CONTROL);
> + free_irq(port->irq, port);
> +}
> +
> +static void ulite_set_termios(struct uart_port *port, struct termios *termios,
> + struct termios *old)
> +{
> + struct plat_uartlite_port *uport;
> + unsigned long flags;
> + unsigned int baud;
> +
> + spin_lock_irqsave(&port->lock, flags);
> +
> + port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
> + | ULITE_STATUS_TXFULL;
> +
> + if (termios->c_iflag & INPCK)
> + port->read_status_mask |=
> + ULITE_STATUS_PARITY | ULITE_STATUS_FRAME;
> +
> + port->ignore_status_mask = 0;
> + if (termios->c_iflag & IGNPAR)
> + port->ignore_status_mask |= ULITE_STATUS_PARITY
> + | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
> +
> + /* ignore all characters if CREAD is not set */
> + if ((termios->c_cflag & CREAD) == 0)
> + port->ignore_status_mask |=
> + ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY
> + | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
> +
> + /* update timeout */
> + uport = &((struct plat_uartlite_port *)port->dev->platform_data)[port->line];
> +
> + baud = uart_get_baud_rate(port, termios, old, uport->baud, uport->baud);
> + uart_update_timeout(port, termios->c_cflag, baud);
> +
> + spin_unlock_irqrestore(&port->lock, flags);
> +}
> +
> +static const char *ulite_type(struct uart_port *port)
> +{
> + return port->type == PORT_UARTLITE ? "uartlite" : NULL;
> +}
> +
> +static void ulite_release_port(struct uart_port *port)
> +{
> + release_mem_region(port->mapbase, ULITE_REGION);
> + iounmap(port->membase);
> + port->membase = 0;
> +}
> +
> +static int ulite_request_port(struct uart_port *port)
> +{
> + if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) {
> + dev_err(port->dev, "Memory region busy\n");
> + return -EBUSY;
> + }
> +
> + if (port->flags & UPF_IOREMAP) {
> + port->membase = ioremap(port->mapbase, ULITE_REGION);
> + }
> +
> + if (!port->membase) {
> + dev_err(port->dev, "Unable to map registers\n");
> + release_mem_region(port->mapbase, ULITE_REGION);
> + return -EBUSY;
> + }
> +
> + return 0;
> +}
> +
> +static void ulite_config_port(struct uart_port *port, int flags)
> +{
> + ulite_request_port(port);
> + port->type = PORT_UARTLITE;
> +}
> +
> +static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser)
> +{
> + /* we don't want the core code to modify any port params */
> + return -EINVAL;
> +}
> +
> +static struct uart_ops ulite_ops = {
> + .tx_empty = ulite_tx_empty,
> + .set_mctrl = ulite_set_mctrl,
> + .get_mctrl = ulite_get_mctrl,
> + .stop_tx = ulite_stop_tx,
> + .start_tx = ulite_start_tx,
> + .stop_rx = ulite_stop_rx,
> + .enable_ms = ulite_enable_ms,
> + .break_ctl = ulite_break_ctl,
> + .startup = ulite_startup,
> + .shutdown = ulite_shutdown,
> + .set_termios = ulite_set_termios,
> + .type = ulite_type,
> + .release_port = ulite_release_port,
> + .request_port = ulite_request_port,
> + .config_port = ulite_config_port,
> + .verify_port = ulite_verify_port
> +};
> +
> +static inline void ulite_init_port(struct uart_port *port)
> +{
> + port->uartclk = 0;
> + port->membase = 0;
> + port->fifosize = 16;
> + port->regshift = 2;
> + port->iobase = 1; /* Mark port in use */
> + port->iotype = UPIO_MEM;
> + port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
> + port->ops = &ulite_ops;
> + port->type = PORT_UNKNOWN;
> +}
> +
> +#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
> +static void ulite_console_wait_tx(struct uart_port *port)
> +{
> + int i;
> +
> + /* wait up to 10ms for the character(s) to be sent */
> + for (i=0; i<10000; i++) {
> + if (in_be32((unsigned volatile *) (port->membase + ULITE_STATUS)) &
> ULITE_STATUS_TXEMPTY)
> + break;
> + udelay(1);
> + }
> +}
> +
> +static void ulite_console_putchar(struct uart_port *port, int ch)
> +{
> + ulite_console_wait_tx(port);
> + out_be32((unsigned volatile *) (port->membase + ULITE_TX), ch);
> +}
> +
> +static void ulite_console_write(struct console *co, const char *s,
> + unsigned int count)
> +{
> + struct uart_port *port = &ports[co->index];
> + unsigned long flags;
> + unsigned int ier;
> + int locked = 1;
> +
> + if (oops_in_progress) {
> + locked = spin_trylock_irqsave(&port->lock, flags);
> + } else
> + spin_lock_irqsave(&port->lock, flags);
> +
> + /* save and disable interrupt */
> + ier = in_be32((unsigned volatile *) (port->membase + ULITE_STATUS))
> & ULITE_STATUS_IE;
> +
> + //writeb(0, port->membase + ULITE_CONTROL);
> + out_be32((unsigned volatile *) (port->membase + ULITE_CONTROL), 0);
> +
> + uart_console_write(port, s, count, ulite_console_putchar);
> +
> + ulite_console_wait_tx(port);
> +
> + /* restore interrupt state */
> + if (ier)
> + out_be32((unsigned volatile *) (port->membase + ULITE_CONTROL),
> ULITE_CONTROL_IE);
> +
> + if (locked)
> + spin_unlock_irqrestore(&port->lock, flags);
> +}
> +
> +static int __init ulite_console_setup(struct console *co, char *options)
> +{
> + int i;
> + struct uart_port *port;
> + struct platform_device *pdev;
> + struct plat_uartlite_port *uport;
> +
> + if (co->index < 0 || co->index >= ULITE_NR_UARTS)
> + return -EINVAL;
> +
> + port = &ports[co->index];
> +
> + /* not initialized yet? */
> + if (!port->membase) {
> + /* We might be early console */
> + pdev = early_uart_get_pdev(VIRTEX_UARTLITE);
> +
> + if (pdev == NULL) {
> + return -ENODEV;
> + }
> +
> + uport = pdev->dev.platform_data;
> +
> + for (i = 0; i <= co->index; ++i) {
> + /* We need to count the number of ports available */
> + /* List of ports is terminated by a 0 record */
> +
> + if (uport[i].baud == 0) {
> + return -ENODEV;
> + }
> + }
> +
> + ulite_init_port(port);
> +
> + port->irq = uport[co->index].irq;
> + port->mapbase = uport[co->index].mapbase;
> + port->line = co->index;
> + spin_lock_init(&port->lock);
> + port->membase = ioremap(port->mapbase, ULITE_REGION);
> +
> + if(port->membase == NULL) {
> + port->iobase = 0;
> + return -EINVAL;
> + }
> +
> + /* Clear ioremap since this port has been mapped already */
> + port->flags &= ~UPF_IOREMAP;
> + }
> +
> + return 0;
> +}
> +
> +static struct uart_driver ulite_uart_driver;
> +
> +static struct console ulite_console = {
> + .name = "ttyUL",
> + .write = ulite_console_write,
> + .device = uart_console_device,
> + .setup = ulite_console_setup,
> + .flags = CON_PRINTBUFFER,
> + .index = -1, /* Specified on the cmdline (e.g. console=ttyUL0 ) */
> + .data = &ulite_uart_driver,
> +};
> +
> +static int __init ulite_console_init(void)
> +{
> + register_console(&ulite_console);
> + return 0;
> +}
> +
> +console_initcall(ulite_console_init);
> +
> +#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
> +
> +static struct uart_driver ulite_uart_driver = {
> + .owner = THIS_MODULE,
> + .driver_name = "uartlite",
> + .dev_name = "ttyUL",
> + .major = ULITE_MAJOR,
> + .minor = ULITE_MINOR,
> + .nr = ULITE_NR_UARTS,
> +#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
> + .cons = &ulite_console,
> +#endif
> +};
> +
> +static int __devinit ulite_probe(struct platform_device *pdev)
> +{
> + struct resource *res, *res2;
> + struct uart_port *port;
> + int ret;
> +
> + if (pdev->id < 0 || pdev->id >= ULITE_NR_UARTS)
> + return -EINVAL;
> +
> + if (ports[pdev->id].membase) {
> + if (ports[pdev->id].flags & UPF_IOREMAP) {
> + return -EBUSY; /* Port is busy */
> + }
> +
> + else {
> + /* This port as be remapped so it must have been an early console */
> + port = &ports[pdev->id];
> + goto add_port;
> + }
> + }
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> + if (!res)
> + return -ENODEV;
> +
> + res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +
> + if (!res2)
> + return -ENODEV;
> +
> + port = &ports[pdev->id];
> +
> + ulite_init_port(port);
> +
> + port->mapbase = res->start;
> + port->irq = res2->start;
> + port->line = pdev->id;
> +
> +add_port:
> + port->dev = &pdev->dev;
> +
> + ret = uart_add_one_port(&ulite_uart_driver, port);
> +
> + if(ret == 0)
> + platform_set_drvdata(pdev, port);
> +
> + return ret;
> +}
> +
> +static int ulite_remove(struct platform_device *pdev)
> +{
> + struct uart_port *port = platform_get_drvdata(pdev);
> +
> + platform_set_drvdata(pdev, NULL);
> +
> + if (port)
> + uart_remove_one_port(&ulite_uart_driver, port);
> +
> + /* mark port as free */
> + port->membase = 0;
> +
> + return 0;
> +}
> +
> +static struct platform_driver ulite_platform_driver = {
> + .probe = ulite_probe,
> + .remove = ulite_remove,
> + .driver = {
> + .owner = THIS_MODULE,
> + .name = "uartlite",
> + },
> +};
> +
> +int __init ulite_init(void)
> +{
> + int ret;
> +
> + ret = uart_register_driver(&ulite_uart_driver);
> + if (ret)
> + return ret;
> +
> + ret = platform_driver_register(&ulite_platform_driver);
> + if (ret)
> + uart_unregister_driver(&ulite_uart_driver);
> +
> + return ret;
> +}
> +
> +void __exit ulite_exit(void)
> +{
> + platform_driver_unregister(&ulite_platform_driver);
> + uart_unregister_driver(&ulite_uart_driver);
> +}
> +
> +module_init(ulite_init);
> +module_exit(ulite_exit);
> +
> +MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
> +MODULE_DESCRIPTION("Xilinx uartlite serial driver");
> +MODULE_LICENSE("GPL");
> Binary files 2.6.18/drivers/serial/.uartlite.c.swp and
> patched-uartlite/drivers/serial/.uartlite.c.swp differ
> diff -urN 2.6.18/include/asm-ppc/uartlite.h
> patched-uartlite/include/asm-ppc/uartlite.h
> --- 2.6.18/include/asm-ppc/uartlite.h 1969-12-31 16:00:00.000000000 -0800
> +++ patched-uartlite/include/asm-ppc/uartlite.h 2006-10-12
> 21:53:00.000000000 -0700
> @@ -0,0 +1,28 @@
> +#ifndef __ASM_UARTLITE_H__
> +#define __ASM_UARTLITE_H__
> +
> +/* For register details see datasheet:
> + http://www.xilinx.com/bvdocs/ipcenter/data_sheet/opb_uartlite.pdf
> +*/
> +#define ULITE_RX 0x00
> +#define ULITE_TX 0x04
> +#define ULITE_STATUS 0x08
> +#define ULITE_CONTROL 0x0c
> +
> +#define ULITE_REGION 16
> +
> +#define ULITE_STATUS_RXVALID 0x01
> +#define ULITE_STATUS_RXFULL 0x02
> +#define ULITE_STATUS_TXEMPTY 0x04
> +#define ULITE_STATUS_TXFULL 0x08
> +#define ULITE_STATUS_IE 0x10
> +#define ULITE_STATUS_OVERRUN 0x20
> +#define ULITE_STATUS_FRAME 0x40
> +#define ULITE_STATUS_PARITY 0x80
> +
> +#define ULITE_CONTROL_RST_TX 0x01
> +#define ULITE_CONTROL_RST_RX 0x02
> +#define ULITE_CONTROL_IE 0x10
> +
> +#endif /* __ASM_UARTLITE_H__ */
> +
> diff -urN 2.6.18/include/linux/serial_core.h
> patched-uartlite/include/linux/serial_core.h
> --- 2.6.18/include/linux/serial_core.h 2006-10-04 14:31:19.000000000 -0700
> +++ patched-uartlite/include/linux/serial_core.h 2006-10-12
> 12:15:32.000000000 -0700
> @@ -132,6 +132,8 @@
>
> #define PORT_S3C2412 73
>
> +/* Xilinx uartlite */
> +#define PORT_UARTLITE 74
>
> #ifdef __KERNEL__
>
> diff -urN 2.6.18/MAINTAINERS patched-uartlite/MAINTAINERS
> --- 2.6.18/MAINTAINERS 2006-10-04 14:31:14.000000000 -0700
> +++ patched-uartlite/MAINTAINERS 2006-10-12 12:15:32.000000000 -0700
> @@ -3311,6 +3311,12 @@
> T: git git://oss.sgi.com:8090/xfs/xfs-2.6
> S: Supported
>
> +XILINX UARTLITE SERIAL DRIVER
> +P: Peter Korsgaard
> +M: jacmet@sunsite.dk
> +L: linux-serial@vger.kernel.org
> +S: Maintained
> +
> X86 3-LEVEL PAGING (PAE) SUPPORT
> P: Ingo Molnar
> M: mingo@redhat.com
> --
>
> Cheers,
> David
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
--
Dave Lynch DLA Systems
Software Development: Embedded Linux
717.627.3770 dhlii@dlasys.net http://www.dlasys.net
fax: 1.253.369.9244 Cell: 1.717.587.7774
Over 25 years' experience in platforms, languages, and technologies too numerous to list.
"Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction."
Albert Einstein
^ permalink raw reply
* Re: [PATCH] Xilinx UART Lite 2.6.18 driver
From: Peter Korsgaard @ 2006-10-13 7:08 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <609d5c8e0610121412o1288ef6i667b908597bf3d76@mail.gmail.com>
>>>>> "David" == David Bolcsfoldi <dbolcsfoldi@gmail.com> writes:
Hi,
David> No I did not know that unfortunately, it could have saved me
David> some work. You are of course right and I'd much prefer to make
David> changes to your driver instead of writing another one.
It unfortunately happens all the time - Googling a bit around before
writing code often pays off ;)
David> I've noticed that in the probe function it tries to get some
David> resources from the platform_device structure but it looks like
David> that this operation will always fail unless I add a 'uartlite'
David> platform device or have I completely misunderstood how platform
David> devices work?
Yes, you need a platform device with the info, E.G. something like:
#include <linux/platform_device.h>
static struct resource myuartlite_resources[] = {
[0] = {
.start = 0xa1000003,
.end = 0xa1000012,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 2,
.end = 2,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device my_uartlite = {
.name = "uartlite",
.id = 0,
.num_resources = ARRAY_SIZE(myuartlite_resources),
.resource = myuartlite_resources,
.dev.platform_data = 0,
};
Which you then add to the platform bus (platform_add_devices).
David> But yes, I will try to add support for the things I need to
David> this driver instead, most importantly early console support and
David> move the #defines for register offsets and such into a separate
David> header file per Grants comment.
Great!
--
Bye, Peter Korsgaard
^ permalink raw reply
* unresolved symbol on target ... while insmod
From: kwkang @ 2006-10-13 6:49 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 518 bytes --]
Hi Srideep,
Can anyone show me how I can overcome below problem?
I have searched mailing list but I can not find any answer for that problem.
[test ~]#insmod linux-kernel-bde.o
Using linux-kernel-bde.o
Using linux-kernel-bde.o
insmod: Warning: kernel-module version mismatch
linux-kernel-bde.o was compiled for kernel version 2.4.20_dev
while this kernel is version 2.4.21-pre5
insmod: unresolved symbol devfs_register
insmod: unresolved symbol devfs_unregister
Thanks.
William.
[-- Attachment #2: Type: text/html, Size: 5638 bytes --]
^ permalink raw reply
* Re: Recently removed io accessors
From: Peter Korsgaard @ 2006-10-13 6:56 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: sfr, linuxppc-dev
In-Reply-To: <1160697861.4792.177.camel@localhost.localdomain>
>>>>> "BH" == Benjamin Herrenschmidt <benh@kernel.crashing.org> writes:
Hi,
>> Any chance of getting them back or should I implement a (slower)
>> loop myself before submitting the patch?
BH> Well, a "packet buffer" should have no endian. When streaming in
BH> our out a fifo, you basically stream bytes that happen to come out
BH> 2 at a time. So unless somebody wired the hardware backward, you
BH> should do no swapping when using the fifo.
I agree in principle, but the issue gets complicated by the fact that
the chip works in chunks of 32bit, but the 911{5..7} chips only have a
16bit interface to lower costs, and that the chip has a builtin endian
swap feature (which works for all direct registers, but apparently not
for the packet buffers).
The memory controller automatically translates a 32bit access to two
16 bit accesses.
You could be right that the hw people screwed something up, but that
doesn't help much once there's units in the field :/
--
Bye, Peter Korsgaard
^ permalink raw reply
* Re: [PATCH] Xilinx UART Lite 2.6.18 driver
From: David H. Lynch Jr. @ 2006-10-13 6:48 UTC (permalink / raw)
To: David Bolcsfoldi; +Cc: linuxppc-embedded
In-Reply-To: <609d5c8e0610121412o1288ef6i667b908597bf3d76@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 3876 bytes --]
David Bolcsfoldi wrote:
> No I did not know that unfortunately, it could have saved me some work.
> You are of course right and I'd much prefer to make changes to your driver
> instead of writing another one.
>
I am sorry you put so much effort in. However, you could have
checked the archives.
I think there are atleast 3 different UartLite drivers posted since
January.
It would be really nice if we could all standardize on one driver.
But I would not sweat this too much.
Peter ignored the fact that my driver was posted here in January,
too and went off and wrote his own
which does not have early serial port - yours and mine do.
and does not have polled support - mine does.
and does not have DCR support - there is another one out there that
has DCR support.
and I can not get to work on my hardware - the only Xilinx V4 based
product that actually defaults to a UartLite
> I've noticed that in the probe function it tries to get some resources
> from the platform_device structure but it looks like that this
> operation will always fail unless I add a 'uartlite' platform device
> or have I completely misunderstood how platform devices work?
>
Peter's driver uses the IORESOURCE requests to pull platform data.
Most other serial platformdevices pull a uart_port object.
My limited understanding of IORESOURCE is that it is not
sufficiently deep to support
the parameters that are needed to support UartLite such as a DCR
flag and a regoffset.
Counting yours that is 4.
> But yes, I will try to add support for the things I need to this
> driver instead, most importantly early console support and move the
> #defines for register offsets and such into a separate header file per
> Grants comments
>
You are welcome to do that. I already patched his driver to work
with my early console support as well as adding the boot-bash stuff
similar to yours. But I gave up actually using it when I could not
get it to work.
Next time I get an opportunity I am going to try to setup an ml403
to atleast verify that Peter's driver is working there.
> Cheers,
> David
>
> On 10/12/06, Peter Korsgaard <jacmet@sunsite.dk> wrote:
>
>>>>>>> "David" == David Bolcsfoldi <dbolcsfoldi@gmail.com> writes:
>>>>>>>
>> Hi David,
>>
>> David> here's a set of patches that adds support for Xilinx UART lite
>> David> devices. It has been tested on an ML403-FX using xapp902
>> David> (ml403_ppc_plb_temac) using a 2.6.18 kernel and a BusyBox
>> David> userspace.
>>
>> I guess you didn't know, but there already exists a uartlite driver!
>> It unfortunately didn't made it into 2.6.19-rc1 because Russell
>> stopped maintaining serial stuff, but it's in -mm.
>>
>> It also has an official lanana.org assigned set of device nodes.
>>
>> I didn't look at your patch yet, but I think it would be more useful
>> to add any features missing to my driver than writing yet another
>> driver (I think we're up to 3 now).
>>
>> --
>> Bye, Peter Korsgaard
>> _______________________________________________
>> Linuxppc-embedded mailing list
>> Linuxppc-embedded@ozlabs.org
>> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>>
>>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
--
Dave Lynch DLA Systems
Software Development: Embedded Linux
717.627.3770 dhlii@dlasys.net http://www.dlasys.net
fax: 1.253.369.9244 Cell: 1.717.587.7774
Over 25 years' experience in platforms, languages, and technologies too numerous to list.
"Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction."
Albert Einstein
[-- Attachment #2: Type: text/html, Size: 5960 bytes --]
^ permalink raw reply
* Re: [PATCH] Xilinx UART Lite 2.6.18 driver
From: David Bolcsfoldi @ 2006-10-13 5:21 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <609d5c8e0610121412o1288ef6i667b908597bf3d76@mail.gmail.com>
Here's an initial patch based on a modified uartlite (by Peter
Korsgaard), it's by no means ment to be final and any feedback would
be appreciated.
What I have changed:
- Early console support.
Since the platform bus isn't initialized by the time the first printk
comes I've added a call 'early_uart_get_pdev' fashioned after the CPM
serial driver.
- Platform device.
The 'uartlite' is now a platform device although I am not entirely
happy how this is done since there's only one VIRTEX_UARTLITE device
with id of 0 although there might be several more described by the
plafrom_data. Maybe the additional devices can be added to the
platform bus in the probe call or would it be better to add these
devices at compile time to the list of platform_devices in virtex.c?
- readb/writeb to in_be32/out_be32.
For some reason on my board the readb and writeb don't behave
correctly when reading and writing to the uartlite device. I haven't
looked into it but if this is unacceptable I will try to revert to
readb/writeb.
- Embedded boot serial support.
There's now support for embedded boot serial I/O over uartlite device 0.
- uartlite.h
A shared header file between the embedded boot serial driver and the
real one with all the reg offsets and such. I don't know if the
location for this file is ok though.
diff -urN 2.6.18/arch/ppc/boot/common/misc-common.c
patched-uartlite/arch/ppc/boot/common/misc-common.c
--- 2.6.18/arch/ppc/boot/common/misc-common.c 2006-10-04
14:31:15.000000000 -0700
+++ patched-uartlite/arch/ppc/boot/common/misc-common.c 2006-10-12
12:47:31.000000000 -0700
@@ -57,7 +57,8 @@
#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
- || defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
+ || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
extern unsigned long com_port;
extern int serial_tstc(unsigned long com_port);
@@ -80,7 +81,8 @@
{
#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
- || defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
+ || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
if(keyb_present)
return (CRT_tstc() || serial_tstc(com_port));
else
@@ -95,7 +97,8 @@
while (1) {
#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
- || defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
+ || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
if (serial_tstc(com_port))
return (serial_getc(com_port));
#endif /* serial console */
@@ -112,7 +115,8 @@
#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
- || defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
+ || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
serial_putc(com_port, c);
if ( c == '\n' )
serial_putc(com_port, '\r');
@@ -161,7 +165,8 @@
while ( ( c = *s++ ) != '\0' ) {
#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
- || defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
+ || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
serial_putc(com_port, c);
if ( c == '\n' ) serial_putc(com_port, '\r');
#endif /* serial console */
diff -urN 2.6.18/arch/ppc/boot/simple/Makefile
patched-uartlite/arch/ppc/boot/simple/Makefile
--- 2.6.18/arch/ppc/boot/simple/Makefile 2006-10-04 14:31:15.000000000 -0700
+++ patched-uartlite/arch/ppc/boot/simple/Makefile 2006-10-12
12:45:53.000000000 -0700
@@ -205,6 +205,7 @@
endif
boot-$(CONFIG_SERIAL_MPC52xx_CONSOLE) += mpc52xx_tty.o
boot-$(CONFIG_SERIAL_MPSC_CONSOLE) += mv64x60_tty.o
+boot-$(CONFIG_SERIAL_UARTLITE_CONSOLE) += uartlite_tty.o
LIBS := $(common)/lib.a $(bootlib)/lib.a
ifeq ($(CONFIG_PPC_PREP),y)
diff -urN 2.6.18/arch/ppc/boot/simple/misc.c
patched-uartlite/arch/ppc/boot/simple/misc.c
--- 2.6.18/arch/ppc/boot/simple/misc.c 2006-10-04 14:31:15.000000000 -0700
+++ patched-uartlite/arch/ppc/boot/simple/misc.c 2006-10-12
12:48:01.000000000 -0700
@@ -48,7 +48,8 @@
#if (defined(CONFIG_SERIAL_8250_CONSOLE) \
|| defined(CONFIG_VGA_CONSOLE) \
|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
- || defined(CONFIG_SERIAL_MPSC_CONSOLE)) \
+ || defined(CONFIG_SERIAL_MPSC_CONSOLE) \
+ || defined(CONFIG_SERIAL_UARTLITE_CONSOLE)) \
&& !defined(CONFIG_GEMINI)
#define INTERACTIVE_CONSOLE 1
#endif
diff -urN 2.6.18/arch/ppc/boot/simple/uartlite_tty.c
patched-uartlite/arch/ppc/boot/simple/uartlite_tty.c
--- 2.6.18/arch/ppc/boot/simple/uartlite_tty.c 1969-12-31
16:00:00.000000000 -0800
+++ patched-uartlite/arch/ppc/boot/simple/uartlite_tty.c 2006-10-12
22:10:44.000000000 -0700
@@ -0,0 +1,69 @@
+/*
+ * Xilinx UART Lite support.
+ * Right now it only works over UART0 and none other.
+ *
+ * Copyright (C) 2006 David Bolcsfoldi <dbolcsfoldi@gmail.com>
+ *
+ * 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.
+ */
+
+#include <asm/io.h>
+#include <asm/uartlite.h>
+#include <platforms/4xx/xparameters/xparameters.h>
+
+static inline int is_xmit_full(unsigned int address)
+{
+ return ((in_be32((volatile unsigned *) (address + ULITE_STATUS)) &
ULITE_STATUS_TXFULL) == ULITE_STATUS_TXFULL);
+}
+
+static inline int is_recv_empty(unsigned int address)
+{
+ return ((in_be32((volatile unsigned *) (address + ULITE_STATUS)) &
ULITE_STATUS_RXVALID) != ULITE_STATUS_RXVALID);
+}
+
+unsigned long serial_init(int chan, void *ignored)
+{
+ switch (chan) {
+ #ifdef XPAR_XUL_UART_0_BASEADDR
+ case 0:
+ return XPAR_XUL_UART_0_BASEADDR;
+ #endif
+ #ifdef XPAR_XUL_UART_1_BASEADDR
+ case 1:
+ return XPAR_XUL_UART_1_BASEADDR;
+ #endif
+ #ifdef XPAR_XUL_UART_2_BASEADDR
+ case 2:
+ return XPAR_XUL_UART_2_BASEADDR;
+ #endif
+ #ifdef XPAR_XUL_UART_3_BASEADDR
+ case 3:
+ return XPAR_XUL_UART_3_BASEADDR;
+ #endif
+ default:
+ goto out;
+ }
+
+out:
+ return -1;
+}
+
+void serial_putc(unsigned long com_port, unsigned char c)
+{
+ while(is_xmit_full(XPAR_XUL_UART_0_BASEADDR));
+ out_be32((volatile unsigned *) (XPAR_XUL_UART_0_BASEADDR + ULITE_TX), c);
+}
+
+unsigned char serial_getc(unsigned long com_port)
+{
+ while(is_recv_empty(XPAR_XUL_UART_0_BASEADDR));
+ return in_be32((volatile unsigned *) (XPAR_XUL_UART_0_BASEADDR + ULITE_RX));
+}
+
+int serial_tstc(unsigned long com_port)
+{
+ return !(is_recv_empty(XPAR_XUL_UART_0_BASEADDR));
+}
+
Binary files 2.6.18/arch/ppc/boot/simple/.uartlite_tty.c.swp and
patched-uartlite/arch/ppc/boot/simple/.uartlite_tty.c.swp differ
diff -urN 2.6.18/arch/ppc/platforms/4xx/virtex.c
patched-uartlite/arch/ppc/platforms/4xx/virtex.c
--- 2.6.18/arch/ppc/platforms/4xx/virtex.c 2006-10-04 14:31:15.000000000 -0700
+++ patched-uartlite/arch/ppc/platforms/4xx/virtex.c 2006-10-12
16:37:23.000000000 -0700
@@ -46,11 +46,71 @@
{ }, /* terminated by empty record */
};
+#define XPAR_UARTLITE(num) { \
+ .mapbase = XPAR_XUL_UART_##num##_BASEADDR, \
+ .irq = XPAR_INTC_0_XUL_UART_##num##_VEC_ID, \
+ .size = (XPAR_XUL_UART_##num##_HIGHADDR -
XPAR_XUL_UART_##num##_BASEADDR) + 1, \
+ .baud = XPAR_XUL_UART_##num##_BAUDRATE, \
+ .bits = XPAR_XUL_UART_##num##_DATA_BITS, \
+ .parity = XPAR_XUL_UART_##num##_USE_PARITY, \
+ .odd_parity = XPAR_XUL_UART_##num##_ODD_PARITY, \
+}
+
+struct plat_uartlite_port uartlite_platform_data[] = {
+#ifdef XPAR_XUL_UART_0_BASEADDR
+ XPAR_UARTLITE(0),
+#endif
+#ifdef XPAR_XUL_UART_1_BASEADDR
+ XPAR_UARTLITE(1),
+#endif
+#ifdef XPAR_XUL_UART_2_BASEADDR
+ XPAR_UARTLITE(2),
+#endif
+#ifdef XPAR_XUL_UART_3_BASEADDR
+ XPAR_UARTLITE(3),
+#endif
+ { }, /* terminated by empty record */
+};
+
struct platform_device ppc_sys_platform_devices[] = {
[VIRTEX_UART] = {
.name = "serial8250",
.id = 0,
.dev.platform_data = serial_platform_data,
},
+
+ [VIRTEX_UARTLITE] = {
+ .name = "uartlite",
+ .id = 0,
+ .dev.platform_data = uartlite_platform_data,
+#ifdef XPAR_XUL_UART_0_BASEADDR
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = XPAR_XUL_UART_0_BASEADDR,
+ .end = XPAR_XUL_UART_0_HIGHADDR,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = XPAR_INTC_0_XUL_UART_0_VEC_ID,
+ .end = XPAR_INTC_0_XUL_UART_0_VEC_ID,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+#endif /* XPAR_XUL_UART_0_BASEADDR */
+ },
};
+/* For early console on the uartlite serial port some way of
+ * getting to the platform_device is needed */
+
+struct platform_device* early_uart_get_pdev(int dev)
+{
+ if (dev < 0 ||
+ dev >= NUM_PPC_SYS_DEVS) {
+ return NULL;
+ }
+
+ return &ppc_sys_platform_devices[dev];
+}
+
diff -urN 2.6.18/arch/ppc/platforms/4xx/virtex.h
patched-uartlite/arch/ppc/platforms/4xx/virtex.h
--- 2.6.18/arch/ppc/platforms/4xx/virtex.h 2006-10-04 14:31:15.000000000 -0700
+++ patched-uartlite/arch/ppc/platforms/4xx/virtex.h 2006-10-12
16:37:41.000000000 -0700
@@ -27,8 +27,21 @@
/* Device type enumeration for platform bus definitions */
#ifndef __ASSEMBLY__
enum ppc_sys_devices {
- VIRTEX_UART, NUM_PPC_SYS_DEVS,
+ VIRTEX_UART,
+ VIRTEX_UARTLITE,
+ NUM_PPC_SYS_DEVS,
};
+
+struct plat_uartlite_port {
+ unsigned int mapbase;
+ unsigned int irq;
+ unsigned int size;
+ unsigned int baud;
+ unsigned char bits;
+ unsigned char parity;
+ unsigned char odd_parity;
+};
+
#endif
#endif /* __ASM_VIRTEX_H__ */
diff -urN 2.6.18/arch/ppc/platforms/4xx/xilinx_ml403.c
patched-uartlite/arch/ppc/platforms/4xx/xilinx_ml403.c
--- 2.6.18/arch/ppc/platforms/4xx/xilinx_ml403.c 2006-10-04
14:31:15.000000000 -0700
+++ patched-uartlite/arch/ppc/platforms/4xx/xilinx_ml403.c 2006-10-12
13:15:36.000000000 -0700
@@ -65,10 +65,11 @@
.ppc_sys_name = "Xilinx ML403 Reference Design",
.mask = 0x00000000,
.value = 0x00000000,
- .num_devices = 1,
+ .num_devices = 2,
.device_list = (enum ppc_sys_devices[])
{
VIRTEX_UART,
+ VIRTEX_UARTLITE,
},
},
};
diff -urN 2.6.18/drivers/serial/Kconfig patched-uartlite/drivers/serial/Kconfig
--- 2.6.18/drivers/serial/Kconfig 2006-10-04 14:31:18.000000000 -0700
+++ patched-uartlite/drivers/serial/Kconfig 2006-10-12 12:15:32.000000000 -0700
@@ -511,6 +511,25 @@
your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.)
+config SERIAL_UARTLITE
+ tristate "Xilinx uartlite serial port support"
+ depends on PPC32
+ select SERIAL_CORE
+ help
+ Say Y here if you want to use the Xilinx uartlite serial controller.
+
+ To compile this driver as a module, choose M here: the
+ module will be called uartlite.ko.
+
+config SERIAL_UARTLITE_CONSOLE
+ bool "Support for console on Xilinx uartlite serial port"
+ depends on SERIAL_UARTLITE=y
+ select SERIAL_CORE_CONSOLE
+ help
+ Say Y here if you wish to use a Xilinx uartlite as the system
+ console (the system console is the device which receives all kernel
+ messages and warnings and which allows logins in single user mode).
+
config SERIAL_SUNCORE
bool
depends on SPARC
diff -urN 2.6.18/drivers/serial/Makefile
patched-uartlite/drivers/serial/Makefile
--- 2.6.18/drivers/serial/Makefile 2006-10-04 14:31:18.000000000 -0700
+++ patched-uartlite/drivers/serial/Makefile 2006-10-12 12:15:32.000000000 -0700
@@ -55,4 +55,5 @@
obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
+obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
diff -urN 2.6.18/drivers/serial/uartlite.c
patched-uartlite/drivers/serial/uartlite.c
--- 2.6.18/drivers/serial/uartlite.c 1969-12-31 16:00:00.000000000 -0800
+++ patched-uartlite/drivers/serial/uartlite.c 2006-10-12
22:10:57.000000000 -0700
@@ -0,0 +1,551 @@
+/*
+ * uartlite.c: Serial driver for Xilinx uartlite serial controller
+ *
+ * Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/tty.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/uartlite.h>
+
+#define ULITE_MAJOR 204
+#define ULITE_MINOR 187
+#define ULITE_NR_UARTS 4
+
+static struct uart_port ports[ULITE_NR_UARTS];
+
+/* Place-holder for board-specific stuff */
+struct platform_device* __attribute__ ((weak)) __init
+early_uart_get_pdev(int index)
+{
+ return NULL;
+}
+
+static int ulite_receive(struct uart_port *port, int stat)
+{
+ struct tty_struct *tty = port->info->tty;
+ unsigned char ch = 0;
+ char flag = TTY_NORMAL;
+
+ if ((stat & (ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
+ | ULITE_STATUS_FRAME)) == 0)
+ return 0;
+
+ /* stats */
+ if (stat & ULITE_STATUS_RXVALID) {
+ port->icount.rx++;
+ ch = in_be32((unsigned volatile *) (port->membase + ULITE_RX));
+
+ if (stat & ULITE_STATUS_PARITY)
+ port->icount.parity++;
+ }
+
+ if (stat & ULITE_STATUS_OVERRUN)
+ port->icount.overrun++;
+
+ if (stat & ULITE_STATUS_FRAME)
+ port->icount.frame++;
+
+
+ /* drop byte with parity error if IGNPAR specificed */
+ if (stat & port->ignore_status_mask & ULITE_STATUS_PARITY)
+ stat &= ~ULITE_STATUS_RXVALID;
+
+ stat &= port->read_status_mask;
+
+ if (stat & ULITE_STATUS_PARITY)
+ flag = TTY_PARITY;
+
+
+ stat &= ~port->ignore_status_mask;
+
+ if (stat & ULITE_STATUS_RXVALID)
+ tty_insert_flip_char(tty, ch, flag);
+
+ if (stat & ULITE_STATUS_FRAME)
+ tty_insert_flip_char(tty, 0, TTY_FRAME);
+
+ if (stat & ULITE_STATUS_OVERRUN)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+
+ return 1;
+}
+
+static int ulite_transmit(struct uart_port *port, int stat)
+{
+ struct circ_buf *xmit = &port->info->xmit;
+
+ if (stat & ULITE_STATUS_TXFULL)
+ return 0;
+
+ if (port->x_char) {
+ out_be32((unsigned volatile *) (port->membase + ULITE_TX), port->x_char);
+ port->x_char = 0;
+ port->icount.tx++;
+ return 1;
+ }
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port))
+ return 0;
+
+ out_be32((unsigned volatile *) (port->membase + ULITE_TX),
xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
+ port->icount.tx++;
+
+ /* wake up */
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ return 1;
+}
+
+static irqreturn_t ulite_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct uart_port *port = (struct uart_port *)dev_id;
+ int busy;
+
+ spin_lock(&port->lock); /* Lock the port in case of printk */
+
+ do {
+ int stat = in_be32((unsigned volatile *) (port->membase + ULITE_STATUS));
+ busy = ulite_receive(port, stat);
+ busy |= ulite_transmit(port, stat);
+ } while (busy);
+
+ spin_unlock(&port->lock);
+
+ tty_flip_buffer_push(port->info->tty);
+
+ return IRQ_HANDLED;
+}
+
+static unsigned int ulite_tx_empty(struct uart_port *port)
+{
+ unsigned long flags;
+ unsigned int ret;
+
+ spin_lock_irqsave(&port->lock, flags);
+ ret = in_be32((unsigned volatile *) (port->membase + ULITE_STATUS));
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
+}
+
+static unsigned int ulite_get_mctrl(struct uart_port *port)
+{
+ return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+}
+
+static void ulite_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ /* N/A */
+}
+
+static void ulite_stop_tx(struct uart_port *port)
+{
+ /* N/A */
+}
+
+static void ulite_start_tx(struct uart_port *port)
+{
+ ulite_transmit(port, in_be32((unsigned volatile *) (port->membase +
ULITE_STATUS)));
+}
+
+static void ulite_stop_rx(struct uart_port *port)
+{
+ /* don't forward any more data (like !CREAD) */
+ port->ignore_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY
+ | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
+}
+
+static void ulite_enable_ms(struct uart_port *port)
+{
+ /* N/A */
+}
+
+static void ulite_break_ctl(struct uart_port *port, int ctl)
+{
+ /* N/A */
+}
+
+static int ulite_startup(struct uart_port *port)
+{
+ int ret;
+
+ ret = request_irq(port->irq, ulite_isr,
+ IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "uartlite", port);
+ if (ret)
+ return ret;
+
+ out_be32((unsigned volatile *) (port->membase + ULITE_CONTROL),
ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
+ out_be32((unsigned volatile *) (port->membase + ULITE_CONTROL),
ULITE_CONTROL_IE);
+
+ return 0;
+}
+
+static void ulite_shutdown(struct uart_port *port)
+{
+ writeb(0, port->membase + ULITE_CONTROL);
+ free_irq(port->irq, port);
+}
+
+static void ulite_set_termios(struct uart_port *port, struct termios *termios,
+ struct termios *old)
+{
+ struct plat_uartlite_port *uport;
+ unsigned long flags;
+ unsigned int baud;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
+ | ULITE_STATUS_TXFULL;
+
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |=
+ ULITE_STATUS_PARITY | ULITE_STATUS_FRAME;
+
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= ULITE_STATUS_PARITY
+ | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
+
+ /* ignore all characters if CREAD is not set */
+ if ((termios->c_cflag & CREAD) == 0)
+ port->ignore_status_mask |=
+ ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY
+ | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN;
+
+ /* update timeout */
+ uport = &((struct plat_uartlite_port *)port->dev->platform_data)[port->line];
+
+ baud = uart_get_baud_rate(port, termios, old, uport->baud, uport->baud);
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *ulite_type(struct uart_port *port)
+{
+ return port->type == PORT_UARTLITE ? "uartlite" : NULL;
+}
+
+static void ulite_release_port(struct uart_port *port)
+{
+ release_mem_region(port->mapbase, ULITE_REGION);
+ iounmap(port->membase);
+ port->membase = 0;
+}
+
+static int ulite_request_port(struct uart_port *port)
+{
+ if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) {
+ dev_err(port->dev, "Memory region busy\n");
+ return -EBUSY;
+ }
+
+ if (port->flags & UPF_IOREMAP) {
+ port->membase = ioremap(port->mapbase, ULITE_REGION);
+ }
+
+ if (!port->membase) {
+ dev_err(port->dev, "Unable to map registers\n");
+ release_mem_region(port->mapbase, ULITE_REGION);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static void ulite_config_port(struct uart_port *port, int flags)
+{
+ ulite_request_port(port);
+ port->type = PORT_UARTLITE;
+}
+
+static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ /* we don't want the core code to modify any port params */
+ return -EINVAL;
+}
+
+static struct uart_ops ulite_ops = {
+ .tx_empty = ulite_tx_empty,
+ .set_mctrl = ulite_set_mctrl,
+ .get_mctrl = ulite_get_mctrl,
+ .stop_tx = ulite_stop_tx,
+ .start_tx = ulite_start_tx,
+ .stop_rx = ulite_stop_rx,
+ .enable_ms = ulite_enable_ms,
+ .break_ctl = ulite_break_ctl,
+ .startup = ulite_startup,
+ .shutdown = ulite_shutdown,
+ .set_termios = ulite_set_termios,
+ .type = ulite_type,
+ .release_port = ulite_release_port,
+ .request_port = ulite_request_port,
+ .config_port = ulite_config_port,
+ .verify_port = ulite_verify_port
+};
+
+static inline void ulite_init_port(struct uart_port *port)
+{
+ port->uartclk = 0;
+ port->membase = 0;
+ port->fifosize = 16;
+ port->regshift = 2;
+ port->iobase = 1; /* Mark port in use */
+ port->iotype = UPIO_MEM;
+ port->flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
+ port->ops = &ulite_ops;
+ port->type = PORT_UNKNOWN;
+}
+
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+static void ulite_console_wait_tx(struct uart_port *port)
+{
+ int i;
+
+ /* wait up to 10ms for the character(s) to be sent */
+ for (i=0; i<10000; i++) {
+ if (in_be32((unsigned volatile *) (port->membase + ULITE_STATUS)) &
ULITE_STATUS_TXEMPTY)
+ break;
+ udelay(1);
+ }
+}
+
+static void ulite_console_putchar(struct uart_port *port, int ch)
+{
+ ulite_console_wait_tx(port);
+ out_be32((unsigned volatile *) (port->membase + ULITE_TX), ch);
+}
+
+static void ulite_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct uart_port *port = &ports[co->index];
+ unsigned long flags;
+ unsigned int ier;
+ int locked = 1;
+
+ if (oops_in_progress) {
+ locked = spin_trylock_irqsave(&port->lock, flags);
+ } else
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* save and disable interrupt */
+ ier = in_be32((unsigned volatile *) (port->membase + ULITE_STATUS))
& ULITE_STATUS_IE;
+
+ //writeb(0, port->membase + ULITE_CONTROL);
+ out_be32((unsigned volatile *) (port->membase + ULITE_CONTROL), 0);
+
+ uart_console_write(port, s, count, ulite_console_putchar);
+
+ ulite_console_wait_tx(port);
+
+ /* restore interrupt state */
+ if (ier)
+ out_be32((unsigned volatile *) (port->membase + ULITE_CONTROL),
ULITE_CONTROL_IE);
+
+ if (locked)
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int __init ulite_console_setup(struct console *co, char *options)
+{
+ int i;
+ struct uart_port *port;
+ struct platform_device *pdev;
+ struct plat_uartlite_port *uport;
+
+ if (co->index < 0 || co->index >= ULITE_NR_UARTS)
+ return -EINVAL;
+
+ port = &ports[co->index];
+
+ /* not initialized yet? */
+ if (!port->membase) {
+ /* We might be early console */
+ pdev = early_uart_get_pdev(VIRTEX_UARTLITE);
+
+ if (pdev == NULL) {
+ return -ENODEV;
+ }
+
+ uport = pdev->dev.platform_data;
+
+ for (i = 0; i <= co->index; ++i) {
+ /* We need to count the number of ports available */
+ /* List of ports is terminated by a 0 record */
+
+ if (uport[i].baud == 0) {
+ return -ENODEV;
+ }
+ }
+
+ ulite_init_port(port);
+
+ port->irq = uport[co->index].irq;
+ port->mapbase = uport[co->index].mapbase;
+ port->line = co->index;
+ spin_lock_init(&port->lock);
+ port->membase = ioremap(port->mapbase, ULITE_REGION);
+
+ if(port->membase == NULL) {
+ port->iobase = 0;
+ return -EINVAL;
+ }
+
+ /* Clear ioremap since this port has been mapped already */
+ port->flags &= ~UPF_IOREMAP;
+ }
+
+ return 0;
+}
+
+static struct uart_driver ulite_uart_driver;
+
+static struct console ulite_console = {
+ .name = "ttyUL",
+ .write = ulite_console_write,
+ .device = uart_console_device,
+ .setup = ulite_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1, /* Specified on the cmdline (e.g. console=ttyUL0 ) */
+ .data = &ulite_uart_driver,
+};
+
+static int __init ulite_console_init(void)
+{
+ register_console(&ulite_console);
+ return 0;
+}
+
+console_initcall(ulite_console_init);
+
+#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
+
+static struct uart_driver ulite_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = "uartlite",
+ .dev_name = "ttyUL",
+ .major = ULITE_MAJOR,
+ .minor = ULITE_MINOR,
+ .nr = ULITE_NR_UARTS,
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+ .cons = &ulite_console,
+#endif
+};
+
+static int __devinit ulite_probe(struct platform_device *pdev)
+{
+ struct resource *res, *res2;
+ struct uart_port *port;
+ int ret;
+
+ if (pdev->id < 0 || pdev->id >= ULITE_NR_UARTS)
+ return -EINVAL;
+
+ if (ports[pdev->id].membase) {
+ if (ports[pdev->id].flags & UPF_IOREMAP) {
+ return -EBUSY; /* Port is busy */
+ }
+
+ else {
+ /* This port as be remapped so it must have been an early console */
+ port = &ports[pdev->id];
+ goto add_port;
+ }
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res)
+ return -ENODEV;
+
+ res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (!res2)
+ return -ENODEV;
+
+ port = &ports[pdev->id];
+
+ ulite_init_port(port);
+
+ port->mapbase = res->start;
+ port->irq = res2->start;
+ port->line = pdev->id;
+
+add_port:
+ port->dev = &pdev->dev;
+
+ ret = uart_add_one_port(&ulite_uart_driver, port);
+
+ if(ret == 0)
+ platform_set_drvdata(pdev, port);
+
+ return ret;
+}
+
+static int ulite_remove(struct platform_device *pdev)
+{
+ struct uart_port *port = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ if (port)
+ uart_remove_one_port(&ulite_uart_driver, port);
+
+ /* mark port as free */
+ port->membase = 0;
+
+ return 0;
+}
+
+static struct platform_driver ulite_platform_driver = {
+ .probe = ulite_probe,
+ .remove = ulite_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "uartlite",
+ },
+};
+
+int __init ulite_init(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&ulite_uart_driver);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&ulite_platform_driver);
+ if (ret)
+ uart_unregister_driver(&ulite_uart_driver);
+
+ return ret;
+}
+
+void __exit ulite_exit(void)
+{
+ platform_driver_unregister(&ulite_platform_driver);
+ uart_unregister_driver(&ulite_uart_driver);
+}
+
+module_init(ulite_init);
+module_exit(ulite_exit);
+
+MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
+MODULE_DESCRIPTION("Xilinx uartlite serial driver");
+MODULE_LICENSE("GPL");
Binary files 2.6.18/drivers/serial/.uartlite.c.swp and
patched-uartlite/drivers/serial/.uartlite.c.swp differ
diff -urN 2.6.18/include/asm-ppc/uartlite.h
patched-uartlite/include/asm-ppc/uartlite.h
--- 2.6.18/include/asm-ppc/uartlite.h 1969-12-31 16:00:00.000000000 -0800
+++ patched-uartlite/include/asm-ppc/uartlite.h 2006-10-12
21:53:00.000000000 -0700
@@ -0,0 +1,28 @@
+#ifndef __ASM_UARTLITE_H__
+#define __ASM_UARTLITE_H__
+
+/* For register details see datasheet:
+ http://www.xilinx.com/bvdocs/ipcenter/data_sheet/opb_uartlite.pdf
+*/
+#define ULITE_RX 0x00
+#define ULITE_TX 0x04
+#define ULITE_STATUS 0x08
+#define ULITE_CONTROL 0x0c
+
+#define ULITE_REGION 16
+
+#define ULITE_STATUS_RXVALID 0x01
+#define ULITE_STATUS_RXFULL 0x02
+#define ULITE_STATUS_TXEMPTY 0x04
+#define ULITE_STATUS_TXFULL 0x08
+#define ULITE_STATUS_IE 0x10
+#define ULITE_STATUS_OVERRUN 0x20
+#define ULITE_STATUS_FRAME 0x40
+#define ULITE_STATUS_PARITY 0x80
+
+#define ULITE_CONTROL_RST_TX 0x01
+#define ULITE_CONTROL_RST_RX 0x02
+#define ULITE_CONTROL_IE 0x10
+
+#endif /* __ASM_UARTLITE_H__ */
+
diff -urN 2.6.18/include/linux/serial_core.h
patched-uartlite/include/linux/serial_core.h
--- 2.6.18/include/linux/serial_core.h 2006-10-04 14:31:19.000000000 -0700
+++ patched-uartlite/include/linux/serial_core.h 2006-10-12
12:15:32.000000000 -0700
@@ -132,6 +132,8 @@
#define PORT_S3C2412 73
+/* Xilinx uartlite */
+#define PORT_UARTLITE 74
#ifdef __KERNEL__
diff -urN 2.6.18/MAINTAINERS patched-uartlite/MAINTAINERS
--- 2.6.18/MAINTAINERS 2006-10-04 14:31:14.000000000 -0700
+++ patched-uartlite/MAINTAINERS 2006-10-12 12:15:32.000000000 -0700
@@ -3311,6 +3311,12 @@
T: git git://oss.sgi.com:8090/xfs/xfs-2.6
S: Supported
+XILINX UARTLITE SERIAL DRIVER
+P: Peter Korsgaard
+M: jacmet@sunsite.dk
+L: linux-serial@vger.kernel.org
+S: Maintained
+
X86 3-LEVEL PAGING (PAE) SUPPORT
P: Ingo Molnar
M: mingo@redhat.com
--
Cheers,
David
^ permalink raw reply
* [PATCH] powerpc: change bad ptr handling in simple_alloc
From: Mark A. Greer @ 2006-10-13 3:59 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20061012013544.GE9143@mag.az.mvista.com>
Some minor changes to simple_alloc.c:
- Make simple_realloc return NULL if the ptr passed to it wasn't from a
previous simple_malloc or simple_realloc.
- Change tracking of base of unused memory.
Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---
simple_alloc.c | 19 ++++++++++---------
1 files changed, 10 insertions(+), 9 deletions(-)
---
diff --git a/arch/powerpc/boot/simple_alloc.c b/arch/powerpc/boot/simple_alloc.c
index 478a381..7cc3389 100644
--- a/arch/powerpc/boot/simple_alloc.c
+++ b/arch/powerpc/boot/simple_alloc.c
@@ -26,6 +26,7 @@ static struct alloc_info {
static u32 tbl_entries;
static u32 alloc_min;
+static u32 next_base;
static u32 space_left;
/*
@@ -36,20 +37,20 @@ static u32 space_left;
static void *simple_malloc(u32 size)
{
u32 i;
- struct alloc_info *p = alloc_tbl, *prevp = NULL;
+ struct alloc_info *p = alloc_tbl;
if (size == 0)
goto err_out;
size = _ALIGN_UP(size, alloc_min);
- for (i=0; i<tbl_entries; i++) {
+ for (i=0; i<tbl_entries; i++, p++)
if (!(p->flags & ENTRY_BEEN_USED)) { /* never been used */
if (size <= space_left) {
- if (i > 0)
- p->base = prevp->base + prevp->size;
+ p->base = next_base;
p->size = size;
p->flags = ENTRY_BEEN_USED | ENTRY_IN_USE;
+ next_base += size;
space_left -= size;
return (void *)p->base;
}
@@ -60,8 +61,6 @@ static void *simple_malloc(u32 size)
p->flags |= ENTRY_IN_USE;
return (void *)p->base;
}
- prevp = p++;
- }
err_out:
return NULL;
}
@@ -103,10 +102,12 @@ static void *simple_realloc(void *ptr, u
return NULL;
}
- /* also malloc if ptr didn't come from simple_malloc/realloc */
- if ((ptr == NULL) || ((p = simple_find_entry(ptr)) == NULL))
+ if (ptr == NULL)
return simple_malloc(size);
+ p = simple_find_entry(ptr);
+ if (p == NULL) /* ptr not from simple_malloc/simple_realloc */
+ return NULL;
if (size <= p->size) /* fits in current block */
return ptr;
@@ -136,7 +137,7 @@ void *simple_alloc_init(char *base, u32
heap_base = _ALIGN_UP((u32)alloc_tbl + tbl_size, alloc_min);
- alloc_tbl[0].base = heap_base;
+ next_base = heap_base;
space_left = heap_size;
platform_ops.malloc = simple_malloc;
^ permalink raw reply related
* [PATCH] powerpc: realloc & other bug fixes for flatdevtree
From: Mark A. Greer @ 2006-10-13 3:57 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20061012013427.GC9143@mag.az.mvista.com>
Fix some bugs in flatdevtree.c:
- ft_reorder should update cxt->p.
- ft_make_space didn't follow realloc() semantics properly and
accessed freed memory.
- Fix some other bugs in ft_make_space.
- Don't set cxt->isordered in ft_open to force an ft_reorder the first
time ft_make_space is called. Required so that a malloc is used to
get a pointer that the the realloc in ft_make_space can validly use
later.
- Make ft_end_tree only call adjust_string_offsets if the offsets changed.
Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---
flatdevtree.c | 22 +++++++++++++---------
1 files changed, 13 insertions(+), 9 deletions(-)
---
diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c
index 0d24f50..c76c194 100644
--- a/arch/powerpc/boot/flatdevtree.c
+++ b/arch/powerpc/boot/flatdevtree.c
@@ -176,6 +176,7 @@ static int ft_reorder(struct ft_cxt *cxt
memcpy(p, cxt->rgn[FT_STRUCT].start, cxt->rgn[FT_STRUCT].size);
ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
p - cxt->rgn[FT_STRUCT].start);
+ cxt->p += p - cxt->rgn[FT_STRUCT].start;
cxt->rgn[FT_STRUCT].start = p;
p = pend - cxt->rgn[FT_STRINGS].size;
@@ -281,7 +282,7 @@ static int ft_make_space(struct ft_cxt *
/* cast is to shut gcc up; we know nextra >= 0 */
if (tot < (unsigned int)nextra) {
/* have to reallocate */
- char *newp, *oldp, *new_start;
+ char *newp, *new_start;
int shift;
if (!cxt->realloc)
@@ -291,21 +292,18 @@ static int ft_make_space(struct ft_cxt *
if (!newp)
return 0;
cxt->max_size = size;
- oldp = (char *)cxt->bph;
- shift = newp - oldp;
+ shift = newp - (char *)cxt->bph;
- if (shift != 0) { /* realloc can return same addr */
+ if (shift) { /* realloc can return same addr */
cxt->bph = (struct boot_param_header *)newp;
- memmove(newp, oldp, sizeof(struct boot_param_header));
ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
shift);
- for (r = FT_RSVMAP; r <= FT_STRUCT; ++r) {
+ for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
new_start = cxt->rgn[r].start + shift;
- memmove(new_start, cxt->rgn[r].start,
- cxt->rgn[r].size);
cxt->rgn[r].start = new_start;
}
*pp += shift;
+ cxt->str_anchor += shift;
}
/* move strings up to the end */
@@ -561,7 +559,10 @@ int ft_open(struct ft_cxt *cxt, void *bl
cxt->rgn[FT_STRUCT].size = struct_size(cxt);
cxt->rgn[FT_STRINGS].start = blob + be32_to_cpu(bph->off_dt_strings);
cxt->rgn[FT_STRINGS].size = be32_to_cpu(bph->dt_strings_size);
+ /* Leave as '0' to force first ft_make_space call to do a ft_reorder
+ * and move dt to an area allocated by realloc.
cxt->isordered = ft_ordered(cxt);
+ */
cxt->p = cxt->rgn[FT_STRUCT].start;
cxt->str_anchor = cxt->rgn[FT_STRINGS].start;
@@ -597,13 +598,16 @@ void ft_end_tree(struct ft_cxt *cxt)
struct boot_param_header *bph = cxt->bph;
char *p, *oldstr, *str, *endp;
unsigned long ssize;
+ int adj;
if (!cxt->isordered)
return; /* we haven't touched anything */
/* adjust string offsets */
oldstr = cxt->rgn[FT_STRINGS].start;
- adjust_string_offsets(cxt, cxt->str_anchor - oldstr);
+ adj = cxt->str_anchor - oldstr;
+ if (adj)
+ adjust_string_offsets(cxt, adj);
/* make strings end on 8-byte boundary */
ssize = cxt->rgn[FT_STRINGS].size;
^ permalink raw reply related
* Re: [PATCH 1/2] Add support for stopping spus from xmon
From: Luke Browning @ 2006-10-13 3:18 UTC (permalink / raw)
To: Michael Ellerman
Cc: linuxppc-dev, linuxppc-dev-bounces+lukebrowning=us.ibm.com,
Arnd Bergmann, cbe-oss-dev
In-Reply-To: <20061012120310.6B5A967BD5@ozlabs.org>
[-- Attachment #1: Type: text/plain, Size: 7685 bytes --]
linuxppc-dev-bounces+lukebrowning=us.ibm.com@ozlabs.org wrote on
10/12/2006 09:03:08 AM:
> This patch adds support for stopping, and restarting, spus
> from xmon. We use the spu master runcntl bit to stop execution,
> this is apparently the "right" way to control spu execution and
> spufs will be changed in the future to use this bit.
>
> Testing has shown that to restart execution we have to turn the
> master runcntl bit on and also rewrite the spu runcntl bit, even
> if it is already set to 1 (running).
>
> Stopping spus is triggered by the xmon command 'ss' - "spus stop"
> perhaps. Restarting them is triggered via 'sr'. Restart doesn't
> start execution on spus unless they were running prior to being
> stopped by xmon.
>
> Walking the spu->full_list in xmon after a panic, would mean
> corruption of any spu struct would make all the others
> inaccessible. To avoid this, and also to make the next patch
> easier, we cache pointers to all spus during boot.
The spe affinity code drop created an array of spu pointers that
is indexed by spu->number. We have a couple of other fields in
there that are needed for multiple spu scheduling operations.
Maybe, you can use this array. The name of the arry is lspu[]
for logical spus.
>
> We attempt to catch and recover from errors while stopping and
> restarting the spus, but as with most xmon functionality there are
> no guarantees that performing these operations won't crash xmon
> itself.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> ---
>
> arch/powerpc/platforms/cell/spu_base.c | 4
> arch/powerpc/xmon/xmon.c | 142
> ++++++++++++++++++++++++++++++++-
> include/asm-powerpc/xmon.h | 2
> 3 files changed, 146 insertions(+), 2 deletions(-)
>
> Index: to-merge/arch/powerpc/platforms/cell/spu_base.c
> ===================================================================
> --- to-merge.orig/arch/powerpc/platforms/cell/spu_base.c
> +++ to-merge/arch/powerpc/platforms/cell/spu_base.c
> @@ -38,6 +38,7 @@
> #include <asm/spu.h>
> #include <asm/spu_priv1.h>
> #include <asm/mmu_context.h>
> +#include <asm/xmon.h>
>
> #include "interrupt.h"
>
> @@ -914,6 +915,9 @@ static int __init init_spu_base(void)
> break;
> }
> }
> +
> + xmon_register_spus(&spu_full_list);
> +
> return ret;
> }
> module_init(init_spu_base);
> Index: to-merge/arch/powerpc/xmon/xmon.c
> ===================================================================
> --- to-merge.orig/arch/powerpc/xmon/xmon.c
> +++ to-merge/arch/powerpc/xmon/xmon.c
> @@ -35,6 +35,8 @@
> #include <asm/rtas.h>
> #include <asm/sstep.h>
> #include <asm/bug.h>
> +#include <asm/spu.h>
> +#include <asm/spu_priv1.h>
>
> #ifdef CONFIG_PPC64
> #include <asm/hvcall.h>
> @@ -145,6 +147,8 @@ static void xmon_print_symbol(unsigned l
> const char *after);
> static const char *getvecname(unsigned long vec);
>
> +static int do_spu_cmd(void);
> +
> int xmon_no_auto_backtrace;
>
> extern int print_insn_powerpc(unsigned long, unsigned long, int);
> @@ -207,8 +211,12 @@ Commands:\n\
> mi show information about memory allocation\n\
> p call a procedure\n\
> r print registers\n\
> - s single step\n\
> - S print special registers\n\
> + s single step\n"
> +#ifdef CONFIG_PPC_CELL
> +" ss stop execution on all spus\n\
> + sr restore execution on stopped spus\n"
> +#endif
> +" S print special registers\n\
> t print backtrace\n\
> x exit monitor and recover\n\
> X exit monitor and dont recover\n"
> @@ -516,6 +524,7 @@ int xmon(struct pt_regs *excp)
> xmon_save_regs(®s);
> excp = ®s;
> }
> +
> return xmon_core(excp, 0);
> }
> EXPORT_SYMBOL(xmon);
> @@ -808,6 +817,8 @@ cmds(struct pt_regs *excp)
> cacheflush();
> break;
> case 's':
> + if (do_spu_cmd() == 0)
> + break;
> if (do_step(excp))
> return cmd;
> break;
> @@ -2630,3 +2641,130 @@ void __init xmon_setup(void)
> if (xmon_early)
> debugger(NULL);
> }
> +
> +#ifdef CONFIG_PPC_CELL
> +
> +struct spu_info {
> + struct spu *spu;
> + u64 saved_mfc_sr1_RW;
> + u32 saved_spu_runcntl_RW;
> + u8 stopped_ok;
> +};
> +
> +#define XMON_NUM_SPUS 16 /* Enough for current hardware */
> +
> +static struct spu_info spu_info[XMON_NUM_SPUS];
> +
> +void xmon_register_spus(struct list_head *list)
> +{
> + struct spu *spu;
> +
> + list_for_each_entry(spu, list, full_list) {
> + if (spu->number >= XMON_NUM_SPUS) {
> + WARN_ON(1);
> + continue;
> + }
> +
> + spu_info[spu->number].spu = spu;
> + spu_info[spu->number].stopped_ok = 0;
> + }
> +}
> +
> +static void stop_spus(void)
> +{
> + struct spu *spu;
> + int i;
> + u64 tmp;
> +
> + for (i = 0; i < XMON_NUM_SPUS; i++) {
> + if (!spu_info[i].spu)
> + continue;
> +
> + if (setjmp(bus_error_jmp) == 0) {
> + catch_memory_errors = 1;
> + sync();
> +
> + spu = spu_info[i].spu;
> +
> + spu_info[i].saved_spu_runcntl_RW =
> + in_be32(&spu->problem->spu_runcntl_RW);
> +
> + tmp = spu_mfc_sr1_get(spu);
> + spu_info[i].saved_mfc_sr1_RW = tmp;
> +
> + tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
> + spu_mfc_sr1_set(spu, tmp);
> +
> + sync();
> + __delay(200);
> +
> + spu_info[i].stopped_ok = 1;
> + printf("Stopped spu %.2d\n", i);
> + } else {
> + catch_memory_errors = 0;
> + printf("*** Error stopping spu %.2d\n", i);
> + }
> + catch_memory_errors = 0;
> + }
> +}
> +
> +static void restart_spus(void)
> +{
> + struct spu *spu;
> + int i;
> +
> + for (i = 0; i < XMON_NUM_SPUS; i++) {
> + if (!spu_info[i].spu)
> + continue;
> +
> + if (!spu_info[i].stopped_ok) {
> + printf("*** Error, spu %d was not successfully stopped"
> + ", not restarting\n", i);
> + continue;
> + }
> +
> + if (setjmp(bus_error_jmp) == 0) {
> + catch_memory_errors = 1;
> + sync();
> +
> + spu = spu_info[i].spu;
> + spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
> + out_be32(&spu->problem->spu_runcntl_RW,
> + spu_info[i].saved_spu_runcntl_RW);
> +
> + sync();
> + __delay(200);
> +
> + printf("Restarted spu %.2d\n", i);
> + } else {
> + catch_memory_errors = 0;
> + printf("*** Error restarting spu %.2d\n", i);
> + }
> + catch_memory_errors = 0;
> + }
> +}
> +
> +static int do_spu_cmd(void)
> +{
> + int cmd;
> +
> + cmd = inchar();
> + switch (cmd) {
> + case 's':
> + stop_spus();
> + break;
> + case 'r':
> + restart_spus();
> + break;
> + default:
> + return -1;
> + }
> +
> + return 0;
> +}
> +#else /* ! CONFIG_PPC_CELL */
> +static int do_spu_cmd(void)
> +{
> + return -1;
> +}
> +#endif
> Index: to-merge/include/asm-powerpc/xmon.h
> ===================================================================
> --- to-merge.orig/include/asm-powerpc/xmon.h
> +++ to-merge/include/asm-powerpc/xmon.h
> @@ -14,8 +14,10 @@
>
> #ifdef CONFIG_XMON
> extern void xmon_setup(void);
> +extern void xmon_register_spus(struct list_head *list);
> #else
> static inline void xmon_setup(void) { };
> +static inline void xmon_register_spus(struct list_head *list) { };
> #endif
>
> #endif /* __KERNEL __ */
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
[-- Attachment #2: Type: text/html, Size: 11975 bytes --]
^ permalink raw reply
* Re: [PATCH 1/2] Add support for stopping spus from xmon
From: Haren Myneni @ 2006-10-13 3:10 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, Arnd Bergmann, cbe-oss-dev
In-Reply-To: <20061012120310.6B5A967BD5@ozlabs.org>
Michael Ellerman wrote:
>This patch adds support for stopping, and restarting, spus
>from xmon. We use the spu master runcntl bit to stop execution,
>this is apparently the "right" way to control spu execution and
>spufs will be changed in the future to use this bit.
>
>Testing has shown that to restart execution we have to turn the
>master runcntl bit on and also rewrite the spu runcntl bit, even
>if it is already set to 1 (running).
>
>Stopping spus is triggered by the xmon command 'ss' - "spus stop"
>perhaps. Restarting them is triggered via 'sr'. Restart doesn't
>start execution on spus unless they were running prior to being
>stopped by xmon.
>
>Walking the spu->full_list in xmon after a panic, would mean
>corruption of any spu struct would make all the others
>inaccessible. To avoid this, and also to make the next patch
>easier, we cache pointers to all spus during boot.
>
>We attempt to catch and recover from errors while stopping and
>restarting the spus, but as with most xmon functionality there are
>no guarantees that performing these operations won't crash xmon
>itself.
>
>
>
I think, kdump also need stop_spus() functionality when the dump support
is included on cell. If so, how about both stop_spus() and start_spus()
in platforms/cell/.
Thanks
Haren
^ permalink raw reply
* [PATCH] Check for offline nodes in pci NUMA code
From: Anton Blanchard @ 2006-10-13 2:26 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
During boot we bring up all memory and cpu nodes. Normally a PCI device
will be in one of these online nodes, however in some weird setups it
may not.
We have only seen this in the lab but we may as well check for the case
and fallback to -1 (all nodes).
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: build/arch/powerpc/kernel/pci_64.c
===================================================================
--- build.orig/arch/powerpc/kernel/pci_64.c 2006-10-08 01:18:30.000000000 +1000
+++ build/arch/powerpc/kernel/pci_64.c 2006-10-08 01:23:05.000000000 +1000
@@ -199,8 +199,14 @@ struct pci_controller * pcibios_alloc_co
pci_setup_pci_controller(phb);
phb->arch_data = dev;
phb->is_dynamic = mem_init_done;
- if (dev)
- PHB_SET_NODE(phb, of_node_to_nid(dev));
+ if (dev) {
+ int nid = of_node_to_nid(dev);
+
+ if (nid < 0 || !node_online(nid))
+ nid = -1;
+
+ PHB_SET_NODE(phb, nid);
+ }
return phb;
}
^ permalink raw reply
* [PATCH] Better check in show_instructions
From: Anton Blanchard @ 2006-10-13 2:17 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
Instead of just checking that an address is in the right range, use the
provided __kernel_text_address() helper which covers both the kernel and
module text sections.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: build/arch/powerpc/kernel/process.c
===================================================================
--- build.orig/arch/powerpc/kernel/process.c 2006-07-01 20:27:57.000000000 +1000
+++ build/arch/powerpc/kernel/process.c 2006-09-22 20:01:22.000000000 +1000
@@ -341,13 +341,6 @@ struct task_struct *__switch_to(struct t
static int instructions_to_print = 16;
-#ifdef CONFIG_PPC64
-#define BAD_PC(pc) ((REGION_ID(pc) != KERNEL_REGION_ID) && \
- (REGION_ID(pc) != VMALLOC_REGION_ID))
-#else
-#define BAD_PC(pc) ((pc) < KERNELBASE)
-#endif
-
static void show_instructions(struct pt_regs *regs)
{
int i;
@@ -366,7 +359,8 @@ static void show_instructions(struct pt_
* bad address because the pc *should* only be a
* kernel address.
*/
- if (BAD_PC(pc) || __get_user(instr, (unsigned int __user *)pc)) {
+ if (!__kernel_text_address(pc) ||
+ __get_user(instr, (unsigned int __user *)pc)) {
printk("XXXXXXXX ");
} else {
if (regs->nip == pc)
^ permalink raw reply
* [PATCH] POWER6 has 6 PMCs
From: Anton Blanchard @ 2006-10-13 2:13 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
Change ->num_pmcs to match the number of PMCs in POWER6.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: build/arch/powerpc/kernel/cputable.c
===================================================================
--- build.orig/arch/powerpc/kernel/cputable.c 2006-09-22 19:04:56.000000000 +1000
+++ build/arch/powerpc/kernel/cputable.c 2006-09-22 19:24:11.000000000 +1000
@@ -268,7 +268,7 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER_POWER6,
.icache_bsize = 128,
.dcache_bsize = 128,
- .num_pmcs = 8,
+ .num_pmcs = 6,
.oprofile_cpu_type = "ppc64/power6",
.oprofile_type = PPC_OPROFILE_POWER4,
.oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
^ permalink raw reply
* [PATCH] Never panic when taking altivec exceptions from userspace
From: Anton Blanchard @ 2006-10-13 1:41 UTC (permalink / raw)
To: linuxppc-dev; +Cc: paulus
At the moment we rely on a cpu feature bit or a firmware property to
detect altivec. If we dont have either of these and the cpu does in fact
support altivec we can cause a panic from userspace.
It seems safer to always send a signal if we manage to get an 0xf20
exception from userspace.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index d9f10f2..5ed4c2c 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -900,14 +900,13 @@ void kernel_fp_unavailable_exception(str
void altivec_unavailable_exception(struct pt_regs *regs)
{
-#if !defined(CONFIG_ALTIVEC)
if (user_mode(regs)) {
/* A user program has executed an altivec instruction,
but this kernel doesn't support altivec. */
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
return;
}
-#endif
+
printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception "
"%lx at %lx\n", regs->trap, regs->nip);
die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
^ permalink raw reply related
* RE: plb_temac, ML403, linux 2.4.26, EDK 7.1
From: Pradeep Sampath @ 2006-10-13 0:18 UTC (permalink / raw)
To: Ming Liu; +Cc: linuxppc-embedded
In-Reply-To: <BAY110-F29333102EBA79FA70A2873B2140@phx.gbl>
[-- Attachment #1: Type: text/plain, Size: 1226 bytes --]
Guys,
I need your help on this, i am stuck for over a week now. I am currently using
ML403 Virtex-4 FX12 board, linux kernel 2.6.17.1, EDK 8.1.2i, and Ameet's sysace and TEMAC driver patch. With your help I was able to get the Kernel to boot on the ML403 board. But kernel crashes at xsysace_init function call.
[ 3.995416] Call Trace:
[ 4.024581] [C04A1D20] [FFFFFFFF] 0xffffffff (unreliable)
[ 4.089156] [C04A1D40] [C021D358] xsysace_init+0x50/0x330
[ 4.153726] [C04A1F90] [C0002448] init+0xa4/0x27c
[ 4.209968] [C04A1FF0] [C000509C] kernel_thread+0x44/0x60
Since I am using 8.1.2i to generate the BSP, i suspect that the xparamater_ml300.h file the EDK generates for the ML403 board is not compatible with the sysace driver patch. I suspect that if i include a xparameters_ml300.h file that was generated using EDK 7.1 it would run.
Ming, would it be possible for you to send me a xparameters.h file using EDK 7.1 (or the version you are using) with very basic IP cores that will work with the sysace and TEMAC drivers. Thanks in advance.
I need to get the sysace driver and TEMAC driver's up and running for the project. Any suggestions will be very helpful...
-Pradeep
[-- Attachment #2: Type: text/html, Size: 1480 bytes --]
^ permalink raw reply
* RE: plb_temac, ML403, linux 2.4.26, EDK 7.1
From: Pradeep Sampath @ 2006-10-13 0:18 UTC (permalink / raw)
To: Ming Liu; +Cc: linuxppc-embedded
In-Reply-To: <BAY110-F29333102EBA79FA70A2873B2140@phx.gbl>
[-- Attachment #1: Type: text/plain, Size: 1226 bytes --]
Guys,
I need your help on this, i am stuck for over a week now. I am currently using
ML403 Virtex-4 FX12 board, linux kernel 2.6.17.1, EDK 8.1.2i, and Ameet's sysace and TEMAC driver patch. With your help I was able to get the Kernel to boot on the ML403 board. But kernel crashes at xsysace_init function call.
[ 3.995416] Call Trace:
[ 4.024581] [C04A1D20] [FFFFFFFF] 0xffffffff (unreliable)
[ 4.089156] [C04A1D40] [C021D358] xsysace_init+0x50/0x330
[ 4.153726] [C04A1F90] [C0002448] init+0xa4/0x27c
[ 4.209968] [C04A1FF0] [C000509C] kernel_thread+0x44/0x60
Since I am using 8.1.2i to generate the BSP, i suspect that the xparamater_ml300.h file the EDK generates for the ML403 board is not compatible with the sysace driver patch. I suspect that if i include a xparameters_ml300.h file that was generated using EDK 7.1 it would run.
Ming, would it be possible for you to send me a xparameters.h file using EDK 7.1 (or the version you are using) with very basic IP cores that will work with the sysace and TEMAC drivers. Thanks in advance.
I need to get the sysace driver and TEMAC driver's up and running for the project. Any suggestions will be very helpful...
-Pradeep
[-- Attachment #2: Type: text/html, Size: 1480 bytes --]
^ permalink raw reply
* Re: Recently removed io accessors
From: Benjamin Herrenschmidt @ 2006-10-13 0:04 UTC (permalink / raw)
To: Peter Korsgaard; +Cc: sfr, linuxppc-dev
In-Reply-To: <873b9twnbb.fsf@sleipner.barco.com>
On Thu, 2006-10-12 at 17:44 +0200, Peter Korsgaard wrote:
> Hi,
>
> Commit 661f1cdb8b3e3c2c44e97df122c1d5643c054ce8 ([POWERPC] remove
> unused asm routines) removed the _insl / _outsl routines for 32bit
> copies with byteswap.
>
> I've been working on adding ppc support to drivers/net/smc911x.c, and
> I was unfortunately using those routines (The ethernet controller can
> be configured for big endian mode, but the contents of the internal
> packet buffers is still little endian, so you need to byteswap in the
> tx/rx routines).
>
> Any chance of getting them back or should I implement a (slower) loop
> myself before submitting the patch?
Well, a "packet buffer" should have no endian. When streaming in our out
a fifo, you basically stream bytes that happen to come out 2 at a time.
So unless somebody wired the hardware backward, you should do no
swapping when using the fifo.
Ben.
^ permalink raw reply
* [PATCH] Fix IO Window Updates on P2P bridges.
From: Randy Vinson @ 2006-10-12 20:36 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 238 bytes --]
Greetings,
When update_bridge_base() updates the IO window on a PCI-to-PCI bridge, it fails to zero the upper 16 bits of the base and limit registers if the window size is less than 64K. The attached patch corrects this.
Randy Vinson
[-- Attachment #2: pci_update_IO.patch --]
[-- Type: text/plain, Size: 1594 bytes --]
Fix IO Window Updates on P2P bridges.
When updating the I/O window of a PCI-to-PCI bridge, update_bridge_base()
fails to zero the upper 16 bits of the IO base and limit registers if the
new I/O window is under 64k in size.
Signed-off-by: Randy Vinson <rvinson@mvista.com>
---
commit 46be7a52bb42e3323644f4d15bd1e93f14632a60
tree 3e5b1c12c04255d59647f6660cd6b0e3f39d1cc5
parent 10270613fb4d5a44c335cfa13e9626bf5743c01d
author Randy Vinson <rvinson@linuxbox.(none)> Thu, 12 Oct 2006 13:25:46 -0700
committer Randy Vinson <rvinson@linuxbox.(none)> Thu, 12 Oct 2006 13:25:46 -0700
arch/powerpc/kernel/pci_32.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 9b49f86..0d9ff72 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -441,14 +441,14 @@ update_bridge_base(struct pci_bus *bus,
end = res->end - off;
io_base_lo = (start >> 8) & PCI_IO_RANGE_MASK;
io_limit_lo = (end >> 8) & PCI_IO_RANGE_MASK;
- if (end > 0xffff) {
- pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
- start >> 16);
- pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
- end >> 16);
+ if (end > 0xffff)
io_base_lo |= PCI_IO_RANGE_TYPE_32;
- } else
+ else
io_base_lo |= PCI_IO_RANGE_TYPE_16;
+ pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
+ start >> 16);
+ pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
+ end >> 16);
pci_write_config_byte(dev, PCI_IO_BASE, io_base_lo);
pci_write_config_byte(dev, PCI_IO_LIMIT, io_limit_lo);
^ permalink raw reply related
* Re: [PATCH] Xilinx UART Lite 2.6.18 driver
From: David Bolcsfoldi @ 2006-10-12 21:12 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <87ac41esap.fsf@sleipner.barco.com>
No I did not know that unfortunately, it could have saved me some work.
You are of course right and I'd much prefer to make changes to your driver
instead of writing another one.
I've noticed that in the probe function it tries to get some resources
from the platform_device structure but it looks like that this
operation will always fail unless I add a 'uartlite' platform device
or have I completely misunderstood how platform devices work?
But yes, I will try to add support for the things I need to this
driver instead, most importantly early console support and move the
#defines for register offsets and such into a separate header file per
Grants comment.
Cheers,
David
On 10/12/06, Peter Korsgaard <jacmet@sunsite.dk> wrote:
> >>>>> "David" == David Bolcsfoldi <dbolcsfoldi@gmail.com> writes:
>
> Hi David,
>
> David> here's a set of patches that adds support for Xilinx UART lite
> David> devices. It has been tested on an ML403-FX using xapp902
> David> (ml403_ppc_plb_temac) using a 2.6.18 kernel and a BusyBox
> David> userspace.
>
> I guess you didn't know, but there already exists a uartlite driver!
> It unfortunately didn't made it into 2.6.19-rc1 because Russell
> stopped maintaining serial stuff, but it's in -mm.
>
> It also has an official lanana.org assigned set of device nodes.
>
> I didn't look at your patch yet, but I think it would be more useful
> to add any features missing to my driver than writing yet another
> driver (I think we're up to 3 now).
>
> --
> Bye, Peter Korsgaard
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
^ permalink raw reply
* Re: Handling machine check exception
From: Segher Boessenkool @ 2006-10-12 20:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: ganesh subramonian, linuxppc-dev
In-Reply-To: <1160664666.4792.151.camel@localhost.localdomain>
>> The G2 core definitely has a DAR register (SPR 19).
>>
>> Look on the Freescale site for G2CORERM.pdf - this is
>> your reference manual, not the one specifically for the
>> 8247.
>
> Is DAR set for a machine check ?
Not on these old cores.
Segher
^ 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