Re: UartLite for MontaVista - virtex4
Hello, Martin, Tim wrote: Could you tell me where exactly to get the xuartlite_serial.c ? I could not find xuartlite_serial.c in the drivers folder generated by EDK . (\ppc405_0\libsrc\linux_mvl31_v1_01_b\linux\drivers\char\xilinx_uartlite ) Here's the relevant snippet for xulite_send_handler(): /* * if(pxs-thr_chars[0] != 0) then * throttle/unthrottle character was just sent; * do not advance pgs-xmit_tail by ByteCount * in this case. */ if (pxs-thr_chars[0] == 0) { pxs-tx_int_cnt += ByteCount; if (pgs-xmit_cnt = ByteCount) { pgs-xmit_cnt -= ByteCount; pgs-xmit_tail += ByteCount; } else { pgs-xmit_tail += pgs-xmit_cnt; pgs-xmit_cnt = 0; } if (pgs-xmit_tail = SERIAL_XMIT_SIZE) pgs-xmit_tail -= SERIAL_XMIT_SIZE; } else { pxs-tx_thr_cnt += ByteCount; } This seems to be a part of the fix. IIRC the default gs_flush_buffer() method doesn't work well for UART Lite. Hence the fix we have done quite some time ago (see below). It includes the correction pointed out by Tim, and also adds custom flush_buffer(). The patch is against a custom tree, but it should be easy to make it apply to the 2.4 kernel tree Tai is using. Probably this patch was not posted here just because the linuxppc-2.4 kernel tree had been obsoleted, and there was no support for UART Lite in the kernel.org tree. Thanks, Andrei diff -Nru linux.orig/drivers/char/xilinx_uartlite/xuartlite_serial.c linux.result/drivers/char/xilinx_uartlite/xuartlite_serial.c --- linux.orig/drivers/char/xilinx_uartlite/xuartlite_serial.c 2005-02-08 13:04:27.0 +0300 +++ linux.result/drivers/char/xilinx_uartlite/xuartlite_serial.c 2005-02-08 13:37:40.0 +0300 @@ -540,15 +540,18 @@ if (pxs-thr_chars[0] == 0) { pxs-tx_int_cnt += ByteCount; - pgs-xmit_tail += ByteCount; - if (pgs-xmit_tail = SERIAL_XMIT_SIZE) { - pgs-xmit_tail -= SERIAL_XMIT_SIZE; + if (pgs-xmit_cnt = ByteCount) { + pgs-xmit_cnt -= ByteCount; + pgs-xmit_tail += ByteCount; + } else { + pgs-xmit_tail += pgs-xmit_cnt; + pgs-xmit_cnt = 0; } - pgs-xmit_cnt -= ByteCount; + if (pgs-xmit_tail = SERIAL_XMIT_SIZE) + pgs-xmit_tail -= SERIAL_XMIT_SIZE; } else { pxs-tx_thr_cnt += ByteCount; } - /* throttle/unthrottle stuff: queue a byte for transmission (if any), * indicate that there is a room for the next XON/XOFF */ pxs-thr_chars[0] = pxs-thr_chars[1]; @@ -661,6 +664,7 @@ pgs = pxs-gs_data; tty-driver_data = pgs; + tty-disc_data = pxs; pgs-tty = tty; pgs-count++; @@ -770,6 +774,35 @@ func_exit(); } +static void +xuli_flush_buffer (struct tty_struct *tty) +{ + struct gs_port *port; + struct xs_port *pxs; + unsigned long flags; + + func_enter (); + + if (!tty) return; + + port = tty-driver_data; + if (!port) return; + + pxs = tty-disc_data; + if (!pxs) + return; + del_timer_sync(pxs-tx_timer); + save_and_cli(flags); + XUartLite_DisableInterrupt(pxs-x_uart_lite); + gs_flush_buffer(tty); + XUartLite_ResetFifos(pxs-x_uart_lite); + XUartLite_Send(pxs-x_uart_lite, port-xmit_buf, 0); /* stop transmission */ + pxs-rx_enabled = 1; + pxs-tx_started = 0; + XUartLite_EnableInterrupt(pxs-x_uart_lite); + restore_flags(flags); +} + /* * Hang up the serial port */ @@ -1010,7 +1043,7 @@ xuli_driver.flush_chars = gs_flush_chars; xuli_driver.write_room = gs_write_room; xuli_driver.chars_in_buffer = gs_chars_in_buffer; - xuli_driver.flush_buffer = gs_flush_buffer; + xuli_driver.flush_buffer = xuli_flush_buffer; xuli_driver.ioctl = xuli_ioctl; xuli_driver.throttle = xuli_throttle; xuli_driver.unthrottle = xuli_unthrottle; ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
[PATCH 0/5 v2] MPC5200 and Lite5200b low power modes
Hi! Some fixes, improvements from last time: - saving/restoring of some registers inside sleep code (so bestcomm and pic patches can be dropped, yay) - improvements in FEC code for deep-sleep - set up wakeup GPIO so Efika can wake too - patch against latest u-boot (doh) Patches are based on latest mainline git tree + fec patches: Fec_MPC5200_eth_driver.patch Copy_bestcomm_support_files_into_arch_powerpc.patch Make_FEC_work_on_the_lite5200.patch This patchset includes the following patches: - [PATCH 1/5] mpc52xx suspend: UART - [PATCH 2/5] mpc52xx suspend: FEC (ethernet) - [PATCH 3/5] mpc52xx suspend: USB - [PATCH 4/5] mpc52xx suspend: deep-sleep - [PATCH] icecube/lite5200b: wakeup from low-power support - [PATCH 5/5] lite5200b suspend: low-power mode Domen ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
[PATCH 1/5] mpc52xx suspend: UART
MPC52xx uart power management. Not sure how exactly this should be written, but this seems to work, and works around a few seconds delay in resume. Signed-off-by: Domen Puncer [EMAIL PROTECTED] Index: grant.git/drivers/serial/mpc52xx_uart.c === --- grant.git.orig/drivers/serial/mpc52xx_uart.c +++ grant.git/drivers/serial/mpc52xx_uart.c @@ -418,6 +418,22 @@ mpc52xx_uart_verify_port(struct uart_por return 0; } +/* just Reenable TX and RX */ +static void mpc52xx_uart_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) +{ + struct mpc52xx_psc __iomem *psc = PSC(port); + unsigned long flags; + + /* Get the lock */ + spin_lock_irqsave(port-lock, flags); + + /* Reenable TX RX */ + out_8(psc-command,MPC52xx_PSC_TX_ENABLE); + out_8(psc-command,MPC52xx_PSC_RX_ENABLE); + + /* We're all set, release the lock */ + spin_unlock_irqrestore(port-lock, flags); +} static struct uart_ops mpc52xx_uart_ops = { .tx_empty = mpc52xx_uart_tx_empty, @@ -432,8 +448,10 @@ static struct uart_ops mpc52xx_uart_ops .startup= mpc52xx_uart_startup, .shutdown = mpc52xx_uart_shutdown, .set_termios= mpc52xx_uart_set_termios, -/* .pm = mpc52xx_uart_pm, Not supported yet */ -/* .set_wake = mpc52xx_uart_set_wake,Not supported yet */ + + .pm = mpc52xx_uart_pm, +/* .set_wake = mpc52xx_uart_set_wake,*/ + .type = mpc52xx_uart_type, .release_port = mpc52xx_uart_release_port, .request_port = mpc52xx_uart_request_port, ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
[PATCH 2/5] mpc52xx suspend: FEC (ethernet)
Suspend and resume for FEC on MPC52xx. Note that resume is a bit different for lite5200b low-power mode. Signed-off-by: Domen Puncer [EMAIL PROTECTED] --- drivers/net/fec_mpc52xx/fec.c | 60 -- drivers/net/fec_mpc52xx/fec_phy.c | 17 ++ drivers/net/fec_mpc52xx/fec_phy.h |5 +++ 3 files changed, 80 insertions(+), 2 deletions(-) Index: grant.git/drivers/net/fec_mpc52xx/fec.c === --- grant.git.orig/drivers/net/fec_mpc52xx/fec.c +++ grant.git/drivers/net/fec_mpc52xx/fec.c @@ -801,6 +801,62 @@ mpc52xx_fec_remove(struct device *dev) return 0; } +#ifdef CONFIG_PM +static int mpc52xx_fec_suspend(struct of_device *op, pm_message_t state) +{ + struct net_device *ndev = dev_get_drvdata(op-dev); + struct fec_priv *priv = ndev-priv; + struct mpc52xx_fec *fec = priv-fec; + + netif_device_detach(ndev); + + /* Disable the rx and tx tasks. */ + sdma_disable(priv-rx_sdma); + sdma_disable(priv-tx_sdma); + + fec_free_rx_buffers(priv-rx_sdma); + + /* Stop FEC */ + out_be32(fec-ecntrl, in_be32(fec-ecntrl) ~0x2); + + fec_mii_suspend(ndev); + + return 0; +} + +int mpc52xx_fec_resume(struct of_device *op) +{ + struct net_device *ndev = dev_get_drvdata(op-dev); + struct fec_priv *priv = ndev-priv; + struct mpc52xx_fec *fec = priv-fec; + + /* XXX ugly hack */ + /* not deep-sleep (but low-power), so re-init hw */ + if (*(unsigned long *)CONFIG_KERNEL_START != 0x6000) { + *(unsigned long *)CONFIG_KERNEL_START = 0x6000; // restore + fec_mii_init(ndev); + fec_hw_init(ndev); + } else + fec_mii_resume(ndev); + + /* Restart the DMA tasks */ + sdma_fec_rx_init(priv-rx_sdma, priv-rx_fifo, FEC_RX_BUFFER_SIZE); + sdma_fec_tx_init(priv-tx_sdma, priv-tx_fifo); + + /* Start FEC */ + out_be32(fec-ecntrl, in_be32(fec-ecntrl) | 0x2); + + netif_device_attach(ndev); + + if (priv-sequence_done) { /* redo the fec_open() */ + fec_free_rx_buffers(priv-rx_sdma); + fec_open(ndev); + } + + return 0; +} +#endif + #if defined(CONFIG_PPC_MERGE) static struct of_device_id mpc52xx_fec_of_match[] = { { .compatible = mpc5200-ethernet, }, @@ -815,8 +871,8 @@ static struct of_platform_driver mpc52xx .probe = mpc52xx_fec_probe, .remove = mpc52xx_fec_remove, #ifdef CONFIG_PM -/* .suspend = mpc52xx_fec_suspend, TODO */ -/* .resume = mpc52xx_fec_resume, TODO */ + .suspend = mpc52xx_fec_suspend, + .resume = mpc52xx_fec_resume, #endif .driver = { .name = DRIVER_NAME, Index: grant.git/drivers/net/fec_mpc52xx/fec_phy.c === --- grant.git.orig/drivers/net/fec_mpc52xx/fec_phy.c +++ grant.git/drivers/net/fec_mpc52xx/fec_phy.c @@ -527,6 +527,23 @@ int fec_mii_wait(struct net_device *dev) return 0; } +#ifdef CONFIG_PM +phy_cmd_t phy_cmd_off[] = { { mk_mii_write(MII_BMCR, BMCR_PDOWN), NULL }, + { mk_mii_end, } }; +phy_cmd_t phy_cmd_on[] = { { mk_mii_write(MII_BMCR, 0), NULL }, + { mk_mii_end, } }; + +void fec_mii_suspend(struct net_device *dev) +{ + mii_do_cmd(dev, phy_cmd_off); +} + +void fec_mii_resume(struct net_device *dev) +{ + mii_do_cmd(dev, phy_cmd_on); +} +#endif + MODULE_LICENSE(GPL); MODULE_AUTHOR(Dale Farnsworth); MODULE_DESCRIPTION(PHY driver for Motorola MPC52xx FEC); Index: grant.git/drivers/net/fec_mpc52xx/fec_phy.h === --- grant.git.orig/drivers/net/fec_mpc52xx/fec_phy.h +++ grant.git/drivers/net/fec_mpc52xx/fec_phy.h @@ -71,3 +71,8 @@ extern int fec_mii_wait(struct net_devic extern void fec_mii(struct net_device *dev); extern int fec_ioctl(struct net_device *, struct ifreq *rq, int cmd); + +#ifdef CONFIG_PM +extern void fec_mii_suspend(struct net_device *dev); +extern void fec_mii_resume(struct net_device *dev); +#endif ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
[PATCH 4/5] mpc52xx suspend: deep-sleep
Implement deep-sleep on MPC52xx. SDRAM is put into self-refresh with help of SRAM code (alternatives would be code in FLASH, I-cache). Interrupt code must also not be in SDRAM, so put it in I-cache. MPC52xx core is static, so contents will remain intact even with clocks turned off. Signed-off-by: Domen Puncer [EMAIL PROTECTED] --- arch/powerpc/platforms/52xx/Makefile|2 arch/powerpc/platforms/52xx/mpc52xx_pm.c| 124 arch/powerpc/platforms/52xx/mpc52xx_sleep.S | 277 3 files changed, 403 insertions(+) Index: grant.git/arch/powerpc/platforms/52xx/Makefile === --- grant.git.orig/arch/powerpc/platforms/52xx/Makefile +++ grant.git/arch/powerpc/platforms/52xx/Makefile @@ -10,3 +10,5 @@ endif obj-$(CONFIG_PPC_EFIKA)+= efika.o obj-$(CONFIG_PPC_LITE5200) += lite5200.o + +obj-$(CONFIG_PM) += mpc52xx_sleep.o mpc52xx_pm.o Index: grant.git/arch/powerpc/platforms/52xx/mpc52xx_pm.c === --- /dev/null +++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_pm.c @@ -0,0 +1,124 @@ +#include linux/init.h +#include linux/pm.h +#include linux/io.h +#include asm/mpc52xx.h +#include bestcomm.h +#include mpc52xx_pic.h + +extern void mpc52xx_deep_sleep(void *, void *); + +static void __iomem *mbar; + +static int mpc52xx_pm_valid(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + return 1; + default: + return 0; + } +} + +/* you will want to change this, to match your board gpios, rtc or whatever */ +static void mpc52xx_set_wakeup_mode(void) +{ + struct mpc52xx_gpio_wkup __iomem *gpiow; + struct mpc52xx_intr __iomem *intr; +#ifdef CONFIG_PPC_LITE5200 + int pin = 1; /* GPIO_WKUP_1 (GPIO_PSC2_4) */ + int level_low = 1; /* wakeup on low level */ +#elif defined CONFIG_PPC_EFIKA + int pin = 4; /* GPIO_WKUP_4 (GPIO_PSC6_0 - IRDA_RX) */ + int level_low = 0; /* wakeup on high level */ + /* IOW. to wake it up, short pins 1 and 3 on IRDA connector */ +#else +#warning define how would you like your board to wake +#endif + u16 tmp; + + gpiow = mbar + 0xc00; + intr = mbar + 0x500; + + /* enable gpio */ + out_8(gpiow-wkup_gpioe, in_8(gpiow-wkup_gpioe) | (1 pin)); + /* set as input */ + out_8(gpiow-wkup_ddr, in_8(gpiow-wkup_ddr) ~(1 pin)); + /* enable deep sleep interrupt */ + out_8(gpiow-wkup_inten, in_8(gpiow-wkup_inten) | (1 pin)); + /* low/high level creates wakeup interrupt */ + tmp = in_be16(gpiow-wkup_itype); + tmp = (level_low + 1) (pin * 2); + tmp |= (level_low + 1) (pin * 2); + out_be16(gpiow-wkup_itype, tmp); + /* master enable */ + out_8(gpiow-wkup_maste, 1); + + /* enable wakeup gpio interrupt in PIC */ + out_be32(intr-main_mask, in_be32(intr-main_mask) ~(1 8)); +} + +int mpc52xx_pm_prepare(suspend_state_t state) +{ + if (state != PM_SUSPEND_STANDBY) + return -EINVAL; + + /* map registers */ + mbar = ioremap_nocache(0xf000, 0x8000); + if (!mbar) { + printk(KERN_ERR %s:%i Error mapping registers\n, __func__, __LINE__); + return -ENOSYS; + } + + mpc52xx_set_wakeup_mode(); + + return 0; +} + +char saved_sram[0x4000]; +int mpc52xx_pm_enter(suspend_state_t state) +{ + static struct mpc52xx_cdm __iomem *cdm; + u32 clk_enables; + cdm = mbar + 0x200; + + memcpy(saved_sram, sdma.sram, sdma.sram_size); + + out_8(cdm-ccs_sleep_enable, 1); + out_8(cdm-osc_sleep_enable, 1); + out_8(cdm-ccs_qreq_test, 1); + + /* disable all but SDRAM, bestcomm (SRAM) and timer clocks */ + clk_enables = in_be32(cdm-clk_enables); + out_be32(cdm-clk_enables, clk_enables 0x00088002); + + mpc52xx_deep_sleep(sdma.sram, mbar); + + out_be32(cdm-clk_enables, clk_enables); + out_8(cdm-ccs_sleep_enable, 0); + out_8(cdm-osc_sleep_enable, 0); + + memcpy(sdma.sram, saved_sram, sdma.sram_size); + + iounmap(mbar); + return 0; +} + +static int mpc52xx_pm_finish(suspend_state_t state) +{ + return 0; +} + +static struct pm_ops mpc52xx_pm_ops = { + .valid = mpc52xx_pm_valid, + .prepare= mpc52xx_pm_prepare, + .enter = mpc52xx_pm_enter, + .finish = mpc52xx_pm_finish, +}; + +static int __init mpc52xx_pm_init(void) +{ + pm_set_ops(mpc52xx_pm_ops); + return 0; +} + +arch_initcall(mpc52xx_pm_init); Index: grant.git/arch/powerpc/platforms/52xx/mpc52xx_sleep.S === --- /dev/null +++ grant.git/arch/powerpc/platforms/52xx/mpc52xx_sleep.S @@ -0,0 +1,277 @@ +#include asm/reg.h +#include asm/ppc_asm.h +#include
[PATCH] icecube/lite5200b: wakeup from low-power support
U-Boot part of Lite5200b low power mode support. Puts SDRAM out of self-refresh and transfers control to address saved at physical 0x0. --- board/icecube/icecube.c | 50 1 file changed, 50 insertions(+) Index: u-boot.git/board/icecube/icecube.c === --- u-boot.git.orig/board/icecube/icecube.c +++ u-boot.git/board/icecube/icecube.c @@ -42,6 +42,54 @@ #include mt48lc16m16a2-75.h # endif #endif + +#ifdef CONFIG_LITE5200B +/* u-boot part of low-power mode implementation */ +#define SAVED_ADDR (*(void **)0x) +#define PSC2_4 0x02 + +void lite5200b_wakeup(void) +{ + unsigned char wakeup_pin; + void (*linux_wakeup)(void); + + /* check PSC2_4, if it's down QT is signaling we have a wakeup +* from low power mode */ + *(vu_char *)MPC5XXX_WU_GPIO_ENABLE = PSC2_4; + __asm__ volatile (sync); + + wakeup_pin = *(vu_char *)MPC5XXX_WU_GPIO_DATA_I; + if (wakeup_pin PSC2_4) + return; + + /* acknowledge to QT +* by holding pin at 1 for 10 uS */ + *(vu_char *)MPC5XXX_WU_GPIO_DIR = PSC2_4; + __asm__ volatile (sync); + *(vu_char *)MPC5XXX_WU_GPIO_DATA_O = PSC2_4; + __asm__ volatile (sync); + udelay(10); + + /* put ram out of self-refresh */ + *(vu_long *)MPC5XXX_SDRAM_CTRL |= 0x8000; // mode_en + __asm__ volatile (sync); + *(vu_long *)MPC5XXX_SDRAM_CTRL |= 0x5000; // cke ref_en + __asm__ volatile (sync); + *(vu_long *)MPC5XXX_SDRAM_CTRL = ~0x8000; // !mode_en + __asm__ volatile (sync); + udelay(10); /* wait a bit */ + + /* jump back to linux kernel code */ + linux_wakeup = SAVED_ADDR; + printf(\n\nLooks like we just woke, transferring control to 0x%08lx\n, + linux_wakeup); + linux_wakeup(); +} +#else +#define lite5200b_wakeup() +#endif + + #ifndef CFG_RAMBOOT static void sdram_start (int hi_addr) { @@ -208,6 +256,8 @@ long int initdram (int board_type) __asm__ volatile (sync); } + lite5200b_wakeup(); + return dramsize + dramsize2; } ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
[PATCH 5/5] lite5200b suspend: low-power mode
Low-power mode implementation for Lite5200b. Some I/O registers are also saved here. A patch to U-Boot that wakes up SDRAM, and transfers control to address saved at physical 0x0 is needed. Signed-off-by: Domen Puncer [EMAIL PROTECTED] --- arch/powerpc/platforms/52xx/Makefile |3 arch/powerpc/platforms/52xx/lite5200_pm.c| 125 arch/powerpc/platforms/52xx/lite5200_sleep.S | 419 +++ 3 files changed, 547 insertions(+) Index: grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c === --- /dev/null +++ grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c @@ -0,0 +1,125 @@ +#include linux/init.h +#include linux/delay.h +#include linux/pm.h +#include asm/io.h +#include asm/mpc52xx.h +#include mpc52xx_pic.h +#include bestcomm.h + +extern void lite5200_low_power(void *sram, void *mbar); +extern int mpc52xx_pm_enter(suspend_state_t); +extern int mpc52xx_pm_prepare(suspend_state_t); + +static void __iomem *mbar; + +static int lite5200_pm_valid(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + return 1; + default: + return 0; + } +} + +static int lite5200_pm_prepare(suspend_state_t state) +{ + /* deep sleep? let mpc52xx code handle that */ + if (state == PM_SUSPEND_STANDBY) + return mpc52xx_pm_prepare(state); + + if (state != PM_SUSPEND_MEM) + return -EINVAL; + + /* map registers */ + mbar = ioremap_nocache(0xf000, 0x8000); + if (!mbar) { + printk(KERN_ERR %s:%i Error mapping registers\n, __func__, __LINE__); + return -ENOSYS; + } + + return 0; +} + +/* save and restore registers not bound to any real devices */ +static struct mpc52xx_cdm __iomem *cdm; +static struct mpc52xx_cdm scdm; +static struct mpc52xx_intr __iomem *pic; +static struct mpc52xx_intr spic; +static struct mpc52xx_sdma __iomem *bes; +static struct mpc52xx_sdma sbes; +static struct mpc52xx_xlb __iomem *xlb; +static struct mpc52xx_xlb sxlb; +static struct mpc52xx_gpio __iomem *gps; +static struct mpc52xx_gpio sgps; +static struct mpc52xx_gpio_wkup __iomem *gpw; +static struct mpc52xx_gpio_wkup sgpw; +extern char saved_sram[0x4000]; + +static void lite5200_save_regs(void) +{ + _memcpy_fromio(sbes, bes, sizeof(*bes)); + _memcpy_fromio(spic, pic, sizeof(*pic)); + _memcpy_fromio(scdm, cdm, sizeof(*cdm)); + _memcpy_fromio(sxlb, xlb, sizeof(*xlb)); + _memcpy_fromio(sgps, gps, sizeof(*gps)); + _memcpy_fromio(sgpw, gpw, sizeof(*gpw)); + + memcpy(saved_sram, sdma.sram, sdma.sram_size); +} + +static void lite5200_restore_regs(void) +{ + memcpy(sdma.sram, saved_sram, sdma.sram_size); + + _memcpy_toio(gpw, sgpw, sizeof(*gpw)); + _memcpy_toio(gps, sgps, sizeof(*gps)); + _memcpy_toio(xlb, sxlb, sizeof(*xlb)); + _memcpy_toio(cdm, scdm, sizeof(*cdm)); + _memcpy_toio(pic, spic, sizeof(*pic)); + _memcpy_toio(bes, sbes, sizeof(*bes)); +} + +static int lite5200_pm_enter(suspend_state_t state) +{ + /* deep sleep? let mpc52xx code handle that */ + if (state == PM_SUSPEND_STANDBY) { + return mpc52xx_pm_enter(state); + } + + cdm = mbar + 0x200; + pic = mbar + 0x500; + gps = mbar + 0xb00; + gpw = mbar + 0xc00; + bes = mbar + 0x1200; + xlb = mbar + 0x1f00; + lite5200_save_regs(); + + lite5200_low_power(sdma.sram, mbar); + + lite5200_restore_regs(); + + iounmap(mbar); + return 0; +} + +static int lite5200_pm_finish(suspend_state_t state) +{ + return 0; +} + +static struct pm_ops lite5200_pm_ops = { + .valid = lite5200_pm_valid, + .prepare= lite5200_pm_prepare, + .enter = lite5200_pm_enter, + .finish = lite5200_pm_finish, +}; + +static int __init lite5200_pm_init(void) +{ + pm_set_ops(lite5200_pm_ops); + return 0; +} + +arch_initcall(lite5200_pm_init); Index: grant.git/arch/powerpc/platforms/52xx/lite5200_sleep.S === --- /dev/null +++ grant.git/arch/powerpc/platforms/52xx/lite5200_sleep.S @@ -0,0 +1,419 @@ +#include asm/reg.h +#include asm/ppc_asm.h +#include asm/processor.h +#include asm/cache.h + + +#define SDRAM_MODE 0x100 +#define SDRAM_CTRL 0x104 +#define SC_MODE_EN (131) +#define SC_CKE (130) +#define SC_REF_EN (128) +#define SC_SOFT_PRE(11) + +#define GPIOW_GPIOE0xc00 +#define GPIOW_ODE 0xc04 +#define GPIOW_DDR 0xc08 +#define GPIOW_DVO 0xc0c +#define GPIOW_INTEN0xc10 + +#define CDM_CE 0x214 +#define CDM_SDRAM (13) + + +// about 2000 cpu cycles for one sdram cycle here +// just increase, to be on the safe side? +#define TCK5000 + + +#define DONT_DEBUG 1 + +//
Re: [PATCH 3/5] mpc52xx suspend: USB
On 3/15/07, Domen Puncer [EMAIL PROTECTED] wrote: Trivial suspend and resume OF OHCI. On MPC52xx turn off and on power to ports. Signed-off-by: Domen Puncer [EMAIL PROTECTED] Nak; see below Index: grant.git/drivers/usb/host/ohci-ppc-of.c === --- grant.git.orig/drivers/usb/host/ohci-ppc-of.c +++ grant.git/drivers/usb/host/ohci-ppc-of.c @@ -214,6 +214,32 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_ #endif +#ifdef CONFIG_PM +static u32 descr_a; +static int ohci_hcd_ppc_soc_drv_suspend(struct of_device *op, + pm_message_t state) +{ + struct usb_hcd *hcd = dev_get_drvdata(op-dev); +#ifdef CONFIG_PPC_MPC52xx + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + + descr_a = in_be32(ohci-regs-roothub.a); + out_be32(ohci-regs-roothub.a, (descr_a ~0x200) | 0x100); +#endif + return 0; +} #ifdef blocks are a bad idea. It is now possible to boot one kernel image on multiple platforms. Chip model should be determined ahead of time from the device tree and choose the code path accordingly at runtime. -- Grant Likely, B.Sc. P.Eng. Secret Lab Technologies Ltd. [EMAIL PROTECTED] (403) 399-0195 ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Re: [PATCH 5/5] lite5200b suspend: low-power mode
On 3/15/07, Domen Puncer [EMAIL PROTECTED] wrote: Low-power mode implementation for Lite5200b. Some I/O registers are also saved here. A patch to U-Boot that wakes up SDRAM, and transfers control to address saved at physical 0x0 is needed. I don't see any structural problems with this code, but I have a few comments below. I'm also concerned about the blind register save/restore by memcpy_to/fromio. I haven't looked at the chip documentation, but it looks scary. Is it safe to restore those registers in that manner? Cheers, g. Signed-off-by: Domen Puncer [EMAIL PROTECTED] --- arch/powerpc/platforms/52xx/Makefile |3 arch/powerpc/platforms/52xx/lite5200_pm.c| 125 arch/powerpc/platforms/52xx/lite5200_sleep.S | 419 +++ 3 files changed, 547 insertions(+) Index: grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c === --- /dev/null +++ grant.git/arch/powerpc/platforms/52xx/lite5200_pm.c @@ -0,0 +1,125 @@ snip +static int lite5200_pm_prepare(suspend_state_t state) +{ + /* deep sleep? let mpc52xx code handle that */ + if (state == PM_SUSPEND_STANDBY) + return mpc52xx_pm_prepare(state); + + if (state != PM_SUSPEND_MEM) + return -EINVAL; + + /* map registers */ + mbar = ioremap_nocache(0xf000, 0x8000); Magic numbers? Really? This should be retrieved from the device tree. There is always the possibility of mbar getting moved. +static void lite5200_save_regs(void) +{ + _memcpy_fromio(sbes, bes, sizeof(*bes)); + _memcpy_fromio(spic, pic, sizeof(*pic)); + _memcpy_fromio(scdm, cdm, sizeof(*cdm)); + _memcpy_fromio(sxlb, xlb, sizeof(*xlb)); + _memcpy_fromio(sgps, gps, sizeof(*gps)); + _memcpy_fromio(sgpw, gpw, sizeof(*gpw)); Hmmm. I have not dug into this deeply, but blind save/restore to blocks of registers scares me. + + memcpy(saved_sram, sdma.sram, sdma.sram_size); +} + +static void lite5200_restore_regs(void) +{ + memcpy(sdma.sram, saved_sram, sdma.sram_size); + + _memcpy_toio(gpw, sgpw, sizeof(*gpw)); + _memcpy_toio(gps, sgps, sizeof(*gps)); + _memcpy_toio(xlb, sxlb, sizeof(*xlb)); + _memcpy_toio(cdm, scdm, sizeof(*cdm)); + _memcpy_toio(pic, spic, sizeof(*pic)); + _memcpy_toio(bes, sbes, sizeof(*bes)); +} + +static int lite5200_pm_enter(suspend_state_t state) +{ + /* deep sleep? let mpc52xx code handle that */ + if (state == PM_SUSPEND_STANDBY) { + return mpc52xx_pm_enter(state); + } + + cdm = mbar + 0x200; + pic = mbar + 0x500; + gps = mbar + 0xb00; + gpw = mbar + 0xc00; + bes = mbar + 0x1200; + xlb = mbar + 0x1f00; Again, magic numbers Index: grant.git/arch/powerpc/platforms/52xx/lite5200_sleep.S === --- /dev/null +++ grant.git/arch/powerpc/platforms/52xx/lite5200_sleep.S @@ -0,0 +1,419 @@ +#include asm/reg.h +#include asm/ppc_asm.h +#include asm/processor.h +#include asm/cache.h + + +#define SDRAM_MODE 0x100 +#define SDRAM_CTRL 0x104 +#define SC_MODE_EN (131) +#define SC_CKE (130) +#define SC_REF_EN (128) +#define SC_SOFT_PRE(11) + +#define GPIOW_GPIOE0xc00 +#define GPIOW_ODE 0xc04 +#define GPIOW_DDR 0xc08 +#define GPIOW_DVO 0xc0c +#define GPIOW_INTEN0xc10 + +#define CDM_CE 0x214 +#define CDM_SDRAM (13) + + +// about 2000 cpu cycles for one sdram cycle here +// just increase, to be on the safe side? +#define TCK5000 Please avoid c++ comments + + +#define DONT_DEBUG 1 Convention is to #define DEBUG to enable debugging (as opposed to #defining something to disable it) +restore_regs: + lis r4, [EMAIL PROTECTED] + ori r4, r4, [EMAIL PROTECTED] +#ifdef DONT_DEBUG should be #if !defined(DEBUG) -- Grant Likely, B.Sc. P.Eng. Secret Lab Technologies Ltd. [EMAIL PROTECTED] (403) 399-0195 ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Exception in kernel mode
I have a PPC8241 which does an Oops: Exception in kernel mode, sig: 4 [#1] PREEMPT NIP: 0900 LR: C00E579C CTR: 3A55 When doing a 'tar -xvzf'. The NIP is pointing at the decrementer interrupt, I believe. As I understand the decrementer, this is basically the timer tick in the ppc and goes off every n ms continuously. A tar is going to be concerned with date/time stamps on files, so it has some interaction with the clock algorithms. It seems to me that the decrementer should be able to go off at any time during kernel operation, so maybe the Exception in kernel mode is pointing us in an unusual direction. So, with that said: What might be the causes of such an exception from the decrementer in a 2.6.17.11 ppc8241 kernel? Where should one concentrate ones efforts in figuring this out? Charles ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Re: Exception in kernel mode
Hello. Charles Krinke wrote: I have a PPC8241 which does an Oops: Exception in kernel mode, sig: 4 [#1] PREEMPT NIP: 0900 LR: C00E579C CTR: 3A55 When doing a 'tar -xvzf'. The NIP is pointing at the decrementer interrupt, I believe. As I understand the decrementer, this is basically the timer tick in the ppc and goes off every n ms continuously. A tar is going to be concerned with date/time stamps on files, so it has some interaction with the clock algorithms. It seems to me that the decrementer should be able to go off at any time during kernel operation, so maybe the Exception in kernel mode is pointing us in an unusual direction. Obviously, you've got an exception in the decrementer exception handler itself -- and this was something like program check exception, judging on the signal you've got (SIGILL). So, with that said: What might be the causes of such an exception from the decrementer in a 2.6.17.11 ppc8241 kernel? Where should one concentrate ones efforts in figuring this out? Hrm, looks like some CPU errata maybe... WBR, Sergei ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Re: [PATCH 5/5] lite5200b suspend: low-power mode
On 15/03/07 08:09 -0600, Grant Likely wrote: On 3/15/07, Domen Puncer [EMAIL PROTECTED] wrote: Low-power mode implementation for Lite5200b. Some I/O registers are also saved here. A patch to U-Boot that wakes up SDRAM, and transfers control to address saved at physical 0x0 is needed. I don't see any structural problems with this code, but I have a few comments below. I'm also concerned about the blind register save/restore by memcpy_to/fromio. I haven't looked at the chip documentation, but it looks scary. Is it safe to restore those registers in that manner? ... + /* map registers */ + mbar = ioremap_nocache(0xf000, 0x8000); Magic numbers? Really? This should be retrieved from the device tree. There is always the possibility of mbar getting moved. ... + gpw = mbar + 0xc00; + bes = mbar + 0x1200; + xlb = mbar + 0x1f00; Again, magic numbers Well... the code is only applicable for Lite5200b/mpc5200 and numbers are from specs. And it's shorter than mpc52xx_find_and_map() lines. I guess I could rewrite it. + _memcpy_fromio(scdm, cdm, sizeof(*cdm)); + _memcpy_fromio(sxlb, xlb, sizeof(*xlb)); + _memcpy_fromio(sgps, gps, sizeof(*gps)); + _memcpy_fromio(sgpw, gpw, sizeof(*gpw)); Hmmm. I have not dug into this deeply, but blind save/restore to blocks of registers scares me. Seems to work (tm), I'll look at datasheet. +// about 2000 cpu cycles for one sdram cycle here +// just increase, to be on the safe side? +#define TCK5000 Please avoid c++ comments // are in ANSI C99 too, but ok, I know kernel folks don't like them :-) +#define DONT_DEBUG 1 Convention is to #define DEBUG to enable debugging (as opposed to #defining something to disable it) Yeah, makes sense. Domen ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Re: U-boot with flat device tree
On Wed, 2007-03-14 at 16:42, Benedict, Michael wrote: dtc- development snapshot dtc-20060419.tar.gz and recent git sources U-boot - 1.2.0, git sources from denx.de, and git sources from freescale Kernel - 2.6.20.1, 2.6.20.2, and freescale git sources Do yourself a favor and get an updated DTC at some point: http://www.jdl.com/git_repos/ http://www.jdl.com/software/dtc-20070216.tgz Though the latter should have its Maintainer update it too. :-) Thanks, jdl ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
RE: Exception in kernel mode
Obviously, you've got an exception in the decrementer exception handler itself -- and this was something like program check exception, judging on the signal you've got (SIGILL). So, with that said: What might be the causes of such an exception from the decrementer in a 2.6.17.11 ppc8241 kernel? Where should one concentrate ones efforts in figuring this out? Hrm, looks like some CPU errata maybe... WBR, Sergei Thank you very much for the great hint. I have a follow-up question. I can see from arch/ppc/kernel/head.S that the EXCEPTION_PROLOG macro is the first instruction in the decrementer ISR and it says (amongst other things): mtspr SPRN_SPRG0, r10 mtspr SPRN_SPRG1, r11 Which is, I believe, moving r10 to SPRG0 and r11 to SPRG1. So, how do we know that r10 and r11 are always valid in an interrupt context? Are we setting aside r10 and r11 somewhere else in initialization for this purpose? I have looked at the -ffixed-r2 in the CFLAGS and see it is set aside, but it doesn't appear the build process sets r10 r11 aside for the exclusive use of interrupt routines. Is there a shadow register set in the 8241 I havent appreciated yet? I have to admit that I am only modestly familiar with the ppc family but would appreciate any insight to understand how this interrupt code works. Charles ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
RE: Exception in kernel mode
mtspr SPRN_SPRG0, r10 mtspr SPRN_SPRG1, r11 Which is, I believe, moving r10 to SPRG0 and r11 to SPRG1. So, how do we know that r10 and r11 are always valid in an interrupt context? Are we setting aside r10 and r11 somewhere else in That doesn't matter to kernel at all -- they are just *saved* in SPRG regs to avoid being trashed by the exception handler. WBR, Sergei Well, unfortunately, now I am more confused. The original Oops was at an NIP of 0900, which I think means it faulted on the first mtspr from r10. I suppose one could argue that pipeline issues might make it fault on the second one and appear to be the first. But, maybe I am confusing myself here. Would I be correct in assuming that some further instruction in the ISR at 0x900 is the culprit? Could there possibly be some user versus supervisor mode thing going on? My key assumption is that the timer_tick (aka Decrementer) has worked for many hundreds of thousands of interrupts and only when running some particular user application, like tar is there a side effect from either a mode or some register value, race condition, or other. Charles ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Re: Exception in kernel mode
On Mar 15, 2007, at 1:55 PM, Charles Krinke wrote: mtspr SPRN_SPRG0, r10 mtspr SPRN_SPRG1, r11 Which is, I believe, moving r10 to SPRG0 and r11 to SPRG1. So, how do we know that r10 and r11 are always valid in an interrupt context? Are we setting aside r10 and r11 somewhere else in That doesn't matter to kernel at all -- they are just *saved* in SPRG regs to avoid being trashed by the exception handler. WBR, Sergei Well, unfortunately, now I am more confused. The original Oops was at an NIP of 0900, which I think means it faulted on the first mtspr from r10. I suppose one could argue that pipeline issues might make it fault on the second one and appear to be the first. But, maybe I am confusing myself here. Would I be correct in assuming that some further instruction in the ISR at 0x900 is the culprit? Could there possibly be some user versus supervisor mode thing going on? My key assumption is that the timer_tick (aka Decrementer) has worked for many hundreds of thousands of interrupts and only when running some particular user application, like tar is there a side effect from either a mode or some register value, race condition, or other. Can you post the oops that you are seeing, what you need to find out is what instruction image that is causing the illegal instruction exception. Once you have that it will be easier to figure out what's going on. - k ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
RE: Exception in kernel mode
Can you post the oops that you are seeing, what you need to find out is what instruction image that is causing the illegal instruction exception. Once you have that it will be easier to figure out what's going on. - k Dear Kumar: Here is the Oops, and thank you for looking at this. Things have come to a halt here until I can figure this one out as about 6 engineers are going We cannot use an unreliable 2.6 kernel, fix it immediately, Mr. Kernel Guy. Basically, what was happening was a 'tar -xvzf' was underway whose source was an nfs mount (root = /dev/nfs) and whose destination was formatted NAND flash (flash_eraseall -q -j /dev/mtd3, then mounted with 'mount -t jffs2 /dev/mtdblockx /mnt/mtdblockx'). Since I sent the last exchange, I see in the kernel source something about ALTIVEC??. It isnt possible that ALTIVEC needs to be defined for the 8241 is it? Charles rootfs/sbin/fsck.ext3 Oops: Exception in kernel mode, sig: 4 [#1] PREEMPT NIP: 0900 LR: C00E579C CTR: 3A55 REGS: c37f3b00 TRAP: 0700 Not tainted (2.6.17.11) MSR: 00081000 ME CR: 24022484 XER: TASK = c3eaf810[940] 'tar' THREAD: c37f2000 GPR00: 3FFF C37F3BB0 C3EAF810 C40216BC FFFE C4022D64 8000 GPR08: C4000A74 C40316BC C4000980 C40216BC C400 10045C90 C37F3CE0 C01D3B68 GPR16: C3ECC5A0 C37F3C50 2200 C2A9E000 C200 1000 GPR24: C01D C200 C37F3C58 0002 C400 Call Trace: [C37F3BB0] [C00E5764] (unreliable) [C37F3BD0] [C00C93C4] [C37F3BF0] [C00B988C] [C37F3C40] [C00C0644] [C37F3C90] [C00BBA94] [C37F3CD0] [C003B8A8] [C37F3D90] [C003C270] [C37F3E20] [C003C320] [C37F3EC0] [C003C470] [C37F3EF0] [C0055F80] [C37F3F10] [C00560C0] [C37F3F40] [C00041A0] Instruction dump: ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Re: generation of system tick on 8xx
In message [EMAIL PROTECTED] you wrote: Anyone knows which device is used to generate the system tick on 8xx processor? DEC Best regards, Wolfgang Denk -- DENX Software Engineering GmbH, HRB 165235 Munich, CEO: Wolfgang Denk Office: Kirchenstr. 5, D-82194 Groebenzell,Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: [EMAIL PROTECTED] The software required `Windows 95 or better', so I installed Linux. ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Re: Exception in kernel mode
On Mar 15, 2007, at 4:17 PM, Charles Krinke wrote: I ran a couple of more tests and the system did not Oops in the timer_interupt except for the first test this morning. The last two times, the NIP was Oops: Exception in kernel mode, sig: 4 [#1] PREEMPT NIP: C002CE68 LR: C002CEC8 CTR: 3B25 REGS: c3119a00 TRAP: 0700 Not tainted (2.6.17.11) MSR: 00081032 ME,IR,DR CR: 88022484 XER: TASK = c3ecd870[920] 'tar' THREAD: c3118000 And Oops: Exception in kernel mode, sig: 4 [#1] PREEMPT NIP: C00DEE18 LR: C00DEDD8 CTR: REGS: c299dbc0 TRAP: 0700 Not tainted (2.6.17.11) MSR: 00081032 ME,IR,DR CR: 84022488 XER: 2000 TASK = c3e2b7d0[925] 'tar' THREAD: c299c000 For comparision, this is the original one from this morning Oops: Exception in kernel mode, sig: 4 [#1] PREEMPT NIP: 0900 LR: C00E579C CTR: 3A55 REGS: c37f3b00 TRAP: 0700 Not tainted (2.6.17.11) MSR: 00081000 ME CR: 24022484 XER: TASK = c3eaf810[940] 'tar' THREAD: c37f2000 I have to conclude this is not necessarily a timer_interrupt problem. Also, commenting out the innards of the timer_interrupt causes the kernel to hang in its boot right after the message Memory: xxxK available So a properly functioning timer_interrupt is essential to the the kernel booting. But, ... At this point, I really don't know which way to jump. It this a system you are just bringing up or one that's been running for a while. It really seems like memory corruption of some form. I'd suggest checking memory controller settings. Also, what happens if you disassemble the kernel image and look at the addresses pointed to by NIP: C00DEE18 C002CE68. - k ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded
Re: Howto read I2C on MPC5200 Lite
Hello Domen, * Domen Puncer [EMAIL PROTECTED] [15-03-07 10:57]: Can you please try following patch. ok, I patched the kernel now and was able to read the ic2 chip 100 times successfully. I will run the programm the next 20 hours and give then a shot feedback. But the first impression is good. Best regards, Matthias -- Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. -- Rich Cook ___ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded