From Jon.Povey at racelogic.co.uk Wed Sep 1 02:40:23 2010 From: Jon.Povey at racelogic.co.uk (Jon Povey) Date: Wed, 1 Sep 2010 08:40:23 +0100 Subject: UBI crashes / fixing NAND subpage writes Message-ID: <70E876B0EA86DD4BAF101844BC814DFE0903E02F56@Cloud.RL.local> I have been playing with UBI/UBIFS on 2KB page NAND, on TI DaVinci DM355 and having crashes due to subpage write problems. ubiattach with -O 2048 avoids the problem, but I want to fix it, and use the flash more efficiently in space and time. The DaVinci family generate 10 bytes of ECC in hardware for each 512 bytes of data; on 2KB page NAND the 4x10 bytes of ECC are concatenated together at the end of a page. The problem is that the ECC generated for an all-FFs page is not all-FFs, and subpage writes are handled by nand_do_write_ops() by writing a full page with FFs in the unset data areas. When UBI attaches it detects the subpage size as 512 bytes and tries to do two subpage writes, which results in two writes of (different) non-FF ECC data, causing corrupt ECC. An ubiattach, ubidetach, ubiattach sequence puts the kernel into a loop torturing the same block over and over, repeating these lines: UBI error: ubi_io_read: error -74 while reading 512 bytes from PEB 2:512, read 512 bytes UBI error: ubi_io_read: error -74 while reading 512 bytes from PEB 263:512, read 512 bytes UBI: run torture test for PEB 263 UBI: PEB 263 passed torture test, do not mark it a bad I hacked around this as a proof-of-concept by checking for an all-FF subpage in nand_write_page_hwecc() and setting that subpage's ECC to all-FFs, which works - I can attach, detatch, reattach, mount, write files, etc. Of course this is not a very good solution. The right thing to do would seem to be make nand_do_write_ops() properly subpage aware and either add start and end offsets to the nand_write_page* family of functions, or add a nand_write_subpage* family of functions. I don't mind having a go at some of this but am not confident to start such major overhaul of nand_base.c without at least seeking comment from others, so: This email. Maybe there's already something being worked on? Comments welcome... -- Jon Povey jon.povey at racelogic.co.uk Racelogic is a limited company registered in England. Registered number 2743719 . Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB . The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network From sshtylyov at mvista.com Wed Sep 1 04:32:36 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Wed, 01 Sep 2010 13:32:36 +0400 Subject: [PATCH] hawkboard v_2 In-Reply-To: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> References: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> Message-ID: <4C7E1DB4.3070208@mvista.com> Victor Rodriguez wrote: > Basic support for Hawkboard OMAPL138 just UART cominication is included > Signed-off-by: Victor Rodriguez > Notes: This patch deletes empty lines and typo mistakes from previous version These notes belong to the space under the --- tear line, not to the patch description. > This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 from > Kernel development tree for TI DaVinci family of processors > This patch works with basic da8xx_omapl_defconfig, it just have basic support > for UART console > This patch just works with UART 2 for argo file system > Signed-off-by: Victor Rodriguez [...] > diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig > index 2bf03e9..fd8a11c 100644 > --- a/arch/arm/mach-davinci/Kconfig > +++ b/arch/arm/mach-davinci/Kconfig > @@ -185,6 +185,15 @@ config MACH_TNETV107X > help > Say Y here to select the TI TNETV107X Evaluation Module. > > +config MACH_OMAPL138_HAWKBOARD > + bool "TI DA850/OMAP-L138/AM18xx Hawkboard(.org) Platform" > + default ARCH_DAVINCI_DA850 As I've already said, only EVM boards are enabled by default. [...] > diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c > new file mode 100644 > index 0000000..4a7f2da > --- /dev/null > +++ b/arch/arm/mach-davinci/board-da850-hawk.c > @@ -0,0 +1,67 @@ > +/* > + * Hawkboard.org based on TI's OMAP-L138 Platform > + * > + * Initial code: Syed Mohammed Khasim > + * > + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com > + * > + * Derived from: arch/arm/mach-davinci/board-da830-hawk.c > + * Original Copyrights follow: > + * > + * 2007, 2009 (c) MontaVista Software, Inc. This file is licensed under As I said, the original copyright is invalid. WBR, Sergei From caglarakyuz at gmail.com Wed Sep 1 05:01:38 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Wed, 1 Sep 2010 13:01:38 +0300 Subject: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering In-Reply-To: References: <1270504278-15088-1-git-send-email-martin@ti.com> <1270504278-15088-2-git-send-email-martin@ti.com> Message-ID: <201009011301.38767.caglarakyuz@gmail.com> On Tuesday 06 April 2010 12:54:59 am Ambrose, Martin wrote: > This work includes the following: > . Implement handler for FBIO_WAITFORVSYNC ioctl. > > . Allocate the data and palette buffers separately. > A consequence of this is that the palette and data loading is now > done in different phases. And that the LCD must be disabled > temporarily after the palette is loaded but this will only happen > once after init and each time the palette is changed. I think this > is OK. > > . Allocate two (ping and pong) framebuffers from memory. > > . Add pan_display handler which toggles the LCDC DMA registers between > the ping and pong buffers. > Hello, This patch breaks driver for a VGA display. After reverting this patch, display works as expected. Do you have any idea what may be the cause? I'm testing it on L-138 based Hawkboard. Best Regards, Caglar > Signed-off-by: Martin Ambrose > --- > drivers/video/da8xx-fb.c | 301 > +++++++++++++++++++++++++++++++++++---------- include/video/da8xx-fb.h | > 1 + > 2 files changed, 235 insertions(+), 67 deletions(-) > > diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c > index 8d244ba..cad7d45 100644 > --- a/drivers/video/da8xx-fb.c > +++ b/drivers/video/da8xx-fb.c > @@ -36,7 +36,9 @@ > #define DRIVER_NAME "da8xx_lcdc" > > /* LCD Status Register */ > +#define LCD_END_OF_FRAME1 BIT(9) > #define LCD_END_OF_FRAME0 BIT(8) > +#define LCD_PL_LOAD_DONE BIT(6) > #define LCD_FIFO_UNDERFLOW BIT(5) > #define LCD_SYNC_LOST BIT(2) > > @@ -58,11 +60,13 @@ > #define LCD_PALETTE_LOAD_MODE(x) ((x) << 20) > #define PALETTE_AND_DATA 0x00 > #define PALETTE_ONLY 0x01 > +#define DATA_ONLY 0x02 > > #define LCD_MONO_8BIT_MODE BIT(9) > #define LCD_RASTER_ORDER BIT(8) > #define LCD_TFT_MODE BIT(7) > #define LCD_UNDERFLOW_INT_ENA BIT(6) > +#define LCD_PL_ENABLE BIT(4) > #define LCD_MONOCHROME_MODE BIT(1) > #define LCD_RASTER_ENABLE BIT(0) > #define LCD_TFT_ALT_ENABLE BIT(23) > @@ -87,6 +91,10 @@ > #define LCD_DMA_CTRL_REG 0x40 > #define LCD_DMA_FRM_BUF_BASE_ADDR_0_REG 0x44 > #define LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG 0x48 > +#define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C > +#define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 > + > +#define LCD_NUM_BUFFERS 2 > > #define WSI_TIMEOUT 50 > #define PALETTE_SIZE 256 > @@ -111,13 +119,20 @@ static inline void lcdc_write(unsigned int val, > unsigned int addr) struct da8xx_fb_par { > resource_size_t p_palette_base; > unsigned char *v_palette_base; > + dma_addr_t vram_phys; > + unsigned long vram_size; > + void *vram_virt; > + unsigned int dma_start; > + unsigned int dma_end; > struct clk *lcdc_clk; > int irq; > unsigned short pseudo_palette[16]; > - unsigned int databuf_sz; > unsigned int palette_sz; > unsigned int pxl_clk; > int blank; > + wait_queue_head_t vsync_wait; > + int vsync_flag; > + int vsync_timeout; > #ifdef CONFIG_CPU_FREQ > struct notifier_block freq_transition; > #endif > @@ -148,9 +163,9 @@ static struct fb_fix_screeninfo da8xx_fb_fix > __devinitdata = { .type = FB_TYPE_PACKED_PIXELS, > .type_aux = 0, > .visual = FB_VISUAL_PSEUDOCOLOR, > - .xpanstep = 1, > + .xpanstep = 0, > .ypanstep = 1, > - .ywrapstep = 1, > + .ywrapstep = 0, > .accel = FB_ACCEL_NONE > }; > > @@ -221,22 +236,48 @@ static inline void lcd_disable_raster(void) > > static void lcd_blit(int load_mode, struct da8xx_fb_par *par) > { > - u32 tmp = par->p_palette_base + par->databuf_sz - 4; > - u32 reg; > + u32 start; > + u32 end; > + u32 reg_ras; > + u32 reg_dma; > + > + /* init reg to clear PLM (loading mode) fields */ > + reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); > + reg_ras &= ~(3 << 20); > + > + reg_dma = lcdc_read(LCD_DMA_CTRL_REG); > + > + if (load_mode == LOAD_DATA) { > + start = par->dma_start; > + end = par->dma_end; > + > + reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); > + reg_dma |= LCD_END_OF_FRAME_INT_ENA; > + reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; > + > + lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); > + lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); > + lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); > + lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); > + } else if (load_mode == LOAD_PALETTE) { > + start = par->p_palette_base; > + end = start + par->palette_sz - 1; > + > + reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); > + reg_ras |= LCD_PL_ENABLE; > + > + lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); > + lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); > + } > > - /* Update the databuf in the hw. */ > - lcdc_write(par->p_palette_base, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); > - lcdc_write(tmp, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); > + lcdc_write(reg_dma, LCD_DMA_CTRL_REG); > + lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); > > - /* Start the DMA. */ > - reg = lcdc_read(LCD_RASTER_CTRL_REG); > - reg &= ~(3 << 20); > - if (load_mode == LOAD_DATA) > - reg |= LCD_PALETTE_LOAD_MODE(PALETTE_AND_DATA); > - else if (load_mode == LOAD_PALETTE) > - reg |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); > - > - lcdc_write(reg, LCD_RASTER_CTRL_REG); > + /* > + * The Raster enable bit must be set after all other control fields > are + * set. > + */ > + lcd_enable_raster(); > } > > /* Configure the Burst Size of DMA */ > @@ -368,12 +409,8 @@ static int lcd_cfg_display(const struct > lcd_ctrl_config *cfg) static int lcd_cfg_frame_buffer(struct da8xx_fb_par > *par, u32 width, u32 height, u32 bpp, u32 raster_order) > { > - u32 bpl, reg; > + u32 reg; > > - /* Disable Dual Frame Buffer. */ > - reg = lcdc_read(LCD_DMA_CTRL_REG); > - lcdc_write(reg & ~LCD_DUAL_FRAME_BUFFER_ENABLE, > - LCD_DMA_CTRL_REG); > /* Set the Panel Width */ > /* Pixels per line = (PPL + 1)*16 */ > /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/ > @@ -410,9 +447,6 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par > *par, u32 width, u32 height, return -EINVAL; > } > > - bpl = width * bpp / 8; > - par->databuf_sz = height * bpl + par->palette_sz; > - > return 0; > } > > @@ -421,8 +455,9 @@ static int fb_setcolreg(unsigned regno, unsigned red, > unsigned green, struct fb_info *info) > { > struct da8xx_fb_par *par = info->par; > - unsigned short *palette = (unsigned short *)par->v_palette_base; > + unsigned short *palette = (unsigned short *) par->v_palette_base; > u_short pal; > + int update_hw = 0; > > if (regno > 255) > return 1; > @@ -439,8 +474,10 @@ static int fb_setcolreg(unsigned regno, unsigned red, > unsigned green, pal |= (green & 0x00f0); > pal |= (blue & 0x000f); > > - palette[regno] = pal; > - > + if (palette[regno] != pal) { > + update_hw = 1; > + palette[regno] = pal; > + } > } else if ((info->var.bits_per_pixel == 16) && regno < 16) { > red >>= (16 - info->var.red.length); > red <<= info->var.red.offset; > @@ -453,9 +490,16 @@ static int fb_setcolreg(unsigned regno, unsigned red, > unsigned green, > > par->pseudo_palette[regno] = red | green | blue; > > - palette[0] = 0x4000; > + if (palette[0] != 0x4000) { > + update_hw = 1; > + palette[0] = 0x4000; > + } > } > > + /* Update the palette in the h/w as needed. */ > + if (update_hw) > + lcd_blit(LOAD_PALETTE, par); > + > return 0; > } > > @@ -541,15 +585,54 @@ static int lcd_init(struct da8xx_fb_par *par, const > struct lcd_ctrl_config *cfg, > > static irqreturn_t lcdc_irq_handler(int irq, void *arg) > { > + struct da8xx_fb_par *par = arg; > u32 stat = lcdc_read(LCD_STAT_REG); > + u32 reg_ras; > > if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { > lcd_disable_raster(); > lcdc_write(stat, LCD_STAT_REG); > lcd_enable_raster(); > - } else > + } else if (stat & LCD_PL_LOAD_DONE) { > + /* > + * Must disable raster before changing state of any control > bit. + * And also must be disabled before clearing the PL > loading + * interrupt via the following write to the status > register. If + * this is done after then one gets multiple > PL done interrupts. + */ > + lcd_disable_raster(); > + > lcdc_write(stat, LCD_STAT_REG); > > + /* Disable PL completion inerrupt */ > + reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); > + reg_ras &= ~LCD_PL_ENABLE; > + lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); > + > + /* Setup and start data loading mode */ > + lcd_blit(LOAD_DATA, par); > + } else { > + lcdc_write(stat, LCD_STAT_REG); > + > + if (stat & LCD_END_OF_FRAME0) { > + lcdc_write(par->dma_start, > + LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); > + lcdc_write(par->dma_end, > + LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); > + par->vsync_flag = 1; > + wake_up_interruptible(&par->vsync_wait); > + } > + > + if (stat & LCD_END_OF_FRAME1) { > + lcdc_write(par->dma_start, > + LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); > + lcdc_write(par->dma_end, > + LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); > + par->vsync_flag = 1; > + wake_up_interruptible(&par->vsync_wait); > + } > + } > + > return IRQ_HANDLED; > } > > @@ -654,9 +737,10 @@ static int __devexit fb_remove(struct platform_device > *dev) > > unregister_framebuffer(info); > fb_dealloc_cmap(&info->cmap); > - dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE, > - info->screen_base - PAGE_SIZE, > - info->fix.smem_start); > + dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base, > + par->p_palette_base); > + dma_free_coherent(NULL, par->vram_size, par->vram_virt, > + par->vram_phys); > free_irq(par->irq, par); > clk_disable(par->lcdc_clk); > clk_put(par->lcdc_clk); > @@ -668,6 +752,39 @@ static int __devexit fb_remove(struct platform_device > *dev) return 0; > } > > +/* > + * Function to wait for vertical sync which for this LCD peripheral > + * translates into waiting for the current raster frame to complete. > + */ > +static int fb_wait_for_vsync(struct fb_info *info) > +{ > + struct da8xx_fb_par *par = info->par; > + int ret; > + > + /* > + * Set flag to 0 and wait for isr to set to 1. It would seem there > is a + * race condition here where the ISR could have occured just > before or + * just after this set. But since we are just coarsely > waiting for + * a frame to complete then that's OK. i.e. if the > frame completed + * just before this code executed then we have to > wait another full + * frame time but there is no way to avoid such > a situation. On the + * other hand if the frame completed just > after then we don't need + * to wait long at all. Either way we are > guaranteed to return to the + * user immediately after a frame > completion which is all that is + * required. > + */ > + par->vsync_flag = 0; > + ret = wait_event_interruptible_timeout(par->vsync_wait, > + par->vsync_flag != 0, > + par->vsync_timeout); > + if (ret < 0) > + return ret; > + if (ret == 0) > + return -ETIMEDOUT; > + > + return 0; > +} > + > static int fb_ioctl(struct fb_info *info, unsigned int cmd, > unsigned long arg) > { > @@ -697,6 +814,8 @@ static int fb_ioctl(struct fb_info *info, unsigned int > cmd, sync_arg.pulse_width, > sync_arg.front_porch); > break; > + case FBIO_WAITFORVSYNC: > + return fb_wait_for_vsync(info); > default: > return -EINVAL; > } > @@ -732,10 +851,47 @@ static int cfb_blank(int blank, struct fb_info *info) > return ret; > } > > +/* > + * Set new x,y offsets in the virtual display for the visible area and > switch + * to the new mode. > + */ > +static int da8xx_pan_display(struct fb_var_screeninfo *var, > + struct fb_info *fbi) > +{ > + int ret = 0; > + struct fb_var_screeninfo new_var; > + struct da8xx_fb_par *par = fbi->par; > + struct fb_fix_screeninfo *fix = &fbi->fix; > + unsigned int end; > + unsigned int start; > + > + if (var->xoffset != fbi->var.xoffset || > + var->yoffset != fbi->var.yoffset) { > + memcpy(&new_var, &fbi->var, sizeof(new_var)); > + new_var.xoffset = var->xoffset; > + new_var.yoffset = var->yoffset; > + if (fb_check_var(&new_var, fbi)) > + ret = -EINVAL; > + else { > + memcpy(&fbi->var, &new_var, sizeof(new_var)); > + > + start = fix->smem_start + > + new_var.yoffset * fix->line_length + > + new_var.xoffset * var->bits_per_pixel / 8; > + end = start + var->yres * fix->line_length - 1; > + par->dma_start = start; > + par->dma_end = end; > + } > + } > + > + return ret; > +} > + > static struct fb_ops da8xx_fb_ops = { > .owner = THIS_MODULE, > .fb_check_var = fb_check_var, > .fb_setcolreg = fb_setcolreg, > + .fb_pan_display = da8xx_pan_display, > .fb_ioctl = fb_ioctl, > .fb_fillrect = cfb_fillrect, > .fb_copyarea = cfb_copyarea, > @@ -829,40 +985,53 @@ static int __init fb_probe(struct platform_device > *device) } > > /* allocate frame buffer */ > - da8xx_fb_info->screen_base = dma_alloc_coherent(NULL, > - par->databuf_sz + PAGE_SIZE, > - (resource_size_t *) > - &da8xx_fb_info->fix.smem_start, > - GFP_KERNEL | GFP_DMA); > - > - if (!da8xx_fb_info->screen_base) { > + par->vram_size = lcdc_info->width * lcdc_info->height * > lcd_cfg->bpp; + par->vram_size = PAGE_ALIGN(par->vram_size/8); > + par->vram_size = par->vram_size * LCD_NUM_BUFFERS; > + > + par->vram_virt = dma_alloc_coherent(NULL, > + par->vram_size, > + (resource_size_t *) > &par->vram_phys, + GFP_KERNEL | > GFP_DMA); + if (!par->vram_virt) { > dev_err(&device->dev, > "GLCD: kmalloc for frame buffer failed\n"); > ret = -EINVAL; > goto err_release_fb; > } > > - /* move palette base pointer by (PAGE_SIZE - palette_sz) bytes */ > - par->v_palette_base = da8xx_fb_info->screen_base + > - (PAGE_SIZE - par->palette_sz); > - par->p_palette_base = da8xx_fb_info->fix.smem_start + > - (PAGE_SIZE - par->palette_sz); > - > - /* the rest of the frame buffer is pixel data */ > - da8xx_fb_info->screen_base = par->v_palette_base + par->palette_sz; > - da8xx_fb_fix.smem_start = par->p_palette_base + par->palette_sz; > - da8xx_fb_fix.smem_len = par->databuf_sz - par->palette_sz; > - da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8; > + da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt; > + da8xx_fb_fix.smem_start = par->vram_phys; > + da8xx_fb_fix.smem_len = par->vram_size; > + da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8; > + > + par->dma_start = par->vram_phys; > + par->dma_end = par->dma_start + lcdc_info->height * > + da8xx_fb_fix.line_length - 1; > + > + /* allocate palette buffer */ > + par->v_palette_base = dma_alloc_coherent(NULL, > + PALETTE_SIZE, > + (resource_size_t *) > + &par->p_palette_base, > + GFP_KERNEL | GFP_DMA); > + if (!par->v_palette_base) { > + dev_err(&device->dev, > + "GLCD: kmalloc for palette buffer failed\n"); > + ret = -EINVAL; > + goto err_release_fb_mem; > + } > + memset(par->v_palette_base, 0, PALETTE_SIZE); > > par->irq = platform_get_irq(device, 0); > if (par->irq < 0) { > ret = -ENOENT; > - goto err_release_fb_mem; > + goto err_release_pl_mem; > } > > ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); > if (ret) > - goto err_release_fb_mem; > + goto err_release_pl_mem; > > /* Initialize par */ > da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp; > @@ -870,8 +1039,8 @@ static int __init fb_probe(struct platform_device > *device) da8xx_fb_var.xres = lcdc_info->width; > da8xx_fb_var.xres_virtual = lcdc_info->width; > > - da8xx_fb_var.yres = lcdc_info->height; > - da8xx_fb_var.yres_virtual = lcdc_info->height; > + da8xx_fb_var.yres = lcdc_info->height; > + da8xx_fb_var.yres_virtual = lcdc_info->height * LCD_NUM_BUFFERS; > > da8xx_fb_var.grayscale = > lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0; > @@ -892,18 +1061,18 @@ static int __init fb_probe(struct platform_device > *device) ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); if > (ret) > goto err_free_irq; > - > - /* First palette_sz byte of the frame buffer is the palette */ > da8xx_fb_info->cmap.len = par->palette_sz; > > - /* Flush the buffer to the screen. */ > - lcd_blit(LOAD_DATA, par); > - > /* initialize var_screeninfo */ > da8xx_fb_var.activate = FB_ACTIVATE_FORCE; > fb_set_var(da8xx_fb_info, &da8xx_fb_var); > > dev_set_drvdata(&device->dev, da8xx_fb_info); > + > + /* initialize the vsync wait queue */ > + init_waitqueue_head(&par->vsync_wait); > + par->vsync_timeout = HZ / 5; > + > /* Register the Frame Buffer */ > if (register_framebuffer(da8xx_fb_info) < 0) { > dev_err(&device->dev, > @@ -919,10 +1088,6 @@ static int __init fb_probe(struct platform_device > *device) goto err_cpu_freq; > } > #endif > - > - /* enable raster engine */ > - lcd_enable_raster(); > - > return 0; > > #ifdef CONFIG_CPU_FREQ > @@ -936,10 +1101,12 @@ err_dealloc_cmap: > err_free_irq: > free_irq(par->irq, par); > > +err_release_pl_mem: > + dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base, > + par->p_palette_base); > + > err_release_fb_mem: > - dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE, > - da8xx_fb_info->screen_base - PAGE_SIZE, > - da8xx_fb_info->fix.smem_start); > + dma_free_coherent(NULL, par->vram_size, par->vram_virt, > par->vram_phys); > > err_release_fb: > framebuffer_release(da8xx_fb_info); > diff --git a/include/video/da8xx-fb.h b/include/video/da8xx-fb.h > index 89d43b3..6316cda 100644 > --- a/include/video/da8xx-fb.h > +++ b/include/video/da8xx-fb.h > @@ -99,6 +99,7 @@ struct lcd_sync_arg { > #define FBIPUT_COLOR _IOW('F', 6, int) > #define FBIPUT_HSYNC _IOW('F', 9, int) > #define FBIPUT_VSYNC _IOW('F', 10, int) > +#define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t) > > #endif /* ifndef DA8XX_FB_H */ > > -- > 1.6.6.1 > > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source at linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source > From hebert.marcandre at gmail.com Wed Sep 1 07:35:42 2010 From: hebert.marcandre at gmail.com (=?ISO-8859-1?Q?Marc=2DAndr=E9_H=E9bert?=) Date: Wed, 1 Sep 2010 08:35:42 -0400 Subject: Status of OMAPL138 compared to Arago Message-ID: Hello, I am developing for 2 OMAPL138 based boards. After talking with our TI reps a few months back, we started development based on the kernel hosted on arago (git://arago-project.org/git/projects/linux-omapl1.git). But I can see now that there is almost no activity there anymore. I was thinking of rebasing my tree with the linux-davinci instead to facilitate long term support. Is anyone aware if there are any OMAPL138 devices that would be functional in the Arago tree but not yet in the linux-davinci tree (could be because of rejected patches for whatever reasons)? My boards require SPI (0,1), I2C(0,1), SATA, MMCSD (0,1), Ethernet (RMII), UART(0), USB (0,1), McASP. Thanks Marc From schen at mvista.com Wed Sep 1 08:42:45 2010 From: schen at mvista.com (Steve Chen) Date: Wed, 1 Sep 2010 08:42:45 -0500 Subject: Status of OMAPL138 compared to Arago In-Reply-To: References: Message-ID: 2010/9/1 Marc-Andr? H?bert : > Hello, > > I am developing for 2 OMAPL138 based boards. After talking with our TI > reps a few months back, we started development based on the kernel > hosted on arago > (git://arago-project.org/git/projects/linux-omapl1.git). But I can see > now that there is almost no activity there anymore. I recall seeing some very nice charts on the development schedule for the Arago project in the official web site. Perhaps all the tasks are completed? People from TI is probably the best source of information. > > I was thinking of rebasing my tree with the linux-davinci instead to > facilitate long term support. Is anyone aware if there are any > OMAPL138 devices that would be functional in the Arago tree but not > yet in the linux-davinci tree (could be because of rejected patches > for whatever reasons)? My boards require SPI (0,1), I2C(0,1), SATA, > MMCSD (0,1), Ethernet (RMII), UART(0), USB (0,1), McASP. > There is always the option of trying things out at the linux-davinci and report any failures back to the mailing list. If the problem is reproducible on EVM, someone will probably look into it. Regards, Steve From schen at mvista.com Wed Sep 1 09:10:50 2010 From: schen at mvista.com (Steve Chen) Date: Wed, 1 Sep 2010 09:10:50 -0500 Subject: Status of OMAPL138 compared to Arago In-Reply-To: References: Message-ID: 2010/9/1 Marc-Andr? H?bert : > Yeah I remember seeing some charts. > > I'll probably take some next week to try out my changes with > linux-davinci, probably post a few patches afterwards. I was just > wondering if there some kind of big red flag out there (for example > USB doesn't work). > The only red flag I remember seeing is that video does not work too well in some DaVinci variants for the davinci git tree. It was some months ago, so it may already have been addressed. Besides, video is not on your list, so none-issue there. Steve From martin at ti.com Wed Sep 1 09:33:00 2010 From: martin at ti.com (Ambrose, Martin) Date: Wed, 1 Sep 2010 09:33:00 -0500 Subject: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering In-Reply-To: <201009011301.38767.caglarakyuz@gmail.com> References: <1270504278-15088-1-git-send-email-martin@ti.com> <1270504278-15088-2-git-send-email-martin@ti.com> <201009011301.38767.caglarakyuz@gmail.com> Message-ID: On Wed, Sep 01, 2010 at 05:01:38, Caglar Akyuz wrote: > On Tuesday 06 April 2010 12:54:59 am Ambrose, Martin wrote: > > This work includes the following: > > . Implement handler for FBIO_WAITFORVSYNC ioctl. > > > > . Allocate the data and palette buffers separately. > > A consequence of this is that the palette and data loading is now > > done in different phases. And that the LCD must be disabled > > temporarily after the palette is loaded but this will only happen > > once after init and each time the palette is changed. I think this > > is OK. > > > > . Allocate two (ping and pong) framebuffers from memory. > > > > . Add pan_display handler which toggles the LCDC DMA registers between > > the ping and pong buffers. > > > > Hello, > > This patch breaks driver for a VGA display. After reverting this patch, > display works as expected. Do you have any idea what may be the cause? I'm > testing it on L-138 based Hawkboard. What is the nature of the error? Does the driver fail to load/initialize? Does the user space API still work but the display is corrupted? Something else? Regards, Martin From caglarakyuz at gmail.com Wed Sep 1 09:44:48 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Wed, 1 Sep 2010 17:44:48 +0300 Subject: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering In-Reply-To: References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011301.38767.caglarakyuz@gmail.com> Message-ID: <201009011744.48647.caglarakyuz@gmail.com> On Wednesday 01 September 2010 05:33:00 pm Ambrose, Martin wrote: > On Wed, Sep 01, 2010 at 05:01:38, Caglar Akyuz wrote: > > On Tuesday 06 April 2010 12:54:59 am Ambrose, Martin wrote: > > > This work includes the following: > > > . Implement handler for FBIO_WAITFORVSYNC ioctl. > > > > > > . Allocate the data and palette buffers separately. > > > A consequence of this is that the palette and data loading is now > > > done in different phases. And that the LCD must be disabled > > > temporarily after the palette is loaded but this will only happen > > > once after init and each time the palette is changed. I think this > > > is OK. > > > > > > . Allocate two (ping and pong) framebuffers from memory. > > > > > > . Add pan_display handler which toggles the LCDC DMA registers between > > > the ping and pong buffers. > > > > Hello, > > > > This patch breaks driver for a VGA display. After reverting this patch, > > display works as expected. Do you have any idea what may be the cause? > > I'm testing it on L-138 based Hawkboard. > > What is the nature of the error? Does the driver fail to load/initialize? > Does the user space API still work but the display is corrupted? Something > else? > > Regards, > Martin > There is no error in log messages, but display is showing total garbage. I'm trying with framebuffer console but copying known patterns to fb0 also shows garbage. I prepared 3 raw images (red, green, blue) all having the same size as framebuffer. Then: $cp {red|green|blue} /dev/fb0 shows garbage for all three. I compared hsync, vsync, pclk video signals with the working case and all are the same. Best Regards, Caglar From martin at ti.com Wed Sep 1 10:16:21 2010 From: martin at ti.com (Ambrose, Martin) Date: Wed, 1 Sep 2010 10:16:21 -0500 Subject: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering In-Reply-To: <201009011744.48647.caglarakyuz@gmail.com> References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011301.38767.caglarakyuz@gmail.com> <201009011744.48647.caglarakyuz@gmail.com> Message-ID: On Wed, Sep 01, 2010 at 09:44:48, Caglar Akyuz wrote: > On Wednesday 01 September 2010 05:33:00 pm Ambrose, Martin wrote: > > On Wed, Sep 01, 2010 at 05:01:38, Caglar Akyuz wrote: > > > On Tuesday 06 April 2010 12:54:59 am Ambrose, Martin wrote: > > > > This work includes the following: > > > > . Implement handler for FBIO_WAITFORVSYNC ioctl. > > > > > > > > . Allocate the data and palette buffers separately. > > > > A consequence of this is that the palette and data loading is now > > > > done in different phases. And that the LCD must be disabled > > > > temporarily after the palette is loaded but this will only happen > > > > once after init and each time the palette is changed. I think this > > > > is OK. > > > > > > > > . Allocate two (ping and pong) framebuffers from memory. > > > > > > > > . Add pan_display handler which toggles the LCDC DMA registers between > > > > the ping and pong buffers. > > > > > > Hello, > > > > > > This patch breaks driver for a VGA display. After reverting this patch, > > > display works as expected. Do you have any idea what may be the cause? > > > I'm testing it on L-138 based Hawkboard. > > > > What is the nature of the error? Does the driver fail to load/initialize? > > Does the user space API still work but the display is corrupted? Something > > else? > > > > Regards, > > Martin > > > > There is no error in log messages, but display is showing total garbage. > > I'm trying with framebuffer console but copying known patterns to fb0 also > shows garbage. I prepared 3 raw images (red, green, blue) all having the same > size as framebuffer. Then: > > $cp {red|green|blue} /dev/fb0 > > shows garbage for all three. > > I compared hsync, vsync, pclk video signals with the working case and all are > the same. > Hmm. I really have no idea what's wrong. I've used the same code on with a DVI output patch (not in tree) which works for me so I think the resolution portion should be ok. There is a build control in the source drivers/video/da8xx-fb.c #define LCD_NUM_BUFFERS 2 You could try changing this to 1 to see if there is a difference. Although not sure how much information about the root cause this would generate. I couldn't find reference to the Hawkboard in the mainline. Is there a git repo which I could use as a remote to look at diffs? Regards, Martin From caglarakyuz at gmail.com Wed Sep 1 11:56:29 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Wed, 1 Sep 2010 19:56:29 +0300 Subject: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering In-Reply-To: References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011744.48647.caglarakyuz@gmail.com> Message-ID: <201009011956.29788.caglarakyuz@gmail.com> On Wednesday 01 September 2010 06:16:21 pm Ambrose, Martin wrote: > On Wed, Sep 01, 2010 at 09:44:48, Caglar Akyuz wrote: > > On Wednesday 01 September 2010 05:33:00 pm Ambrose, Martin wrote: > > > On Wed, Sep 01, 2010 at 05:01:38, Caglar Akyuz wrote: > > > > On Tuesday 06 April 2010 12:54:59 am Ambrose, Martin wrote: > > > > > This work includes the following: > > > > > . Implement handler for FBIO_WAITFORVSYNC ioctl. > > > > > > > > > > . Allocate the data and palette buffers separately. > > > > > A consequence of this is that the palette and data loading is > > > > > now done in different phases. And that the LCD must be disabled > > > > > temporarily after the palette is loaded but this will only happen > > > > > once after init and each time the palette is changed. I think this > > > > > is OK. > > > > > > > > > > . Allocate two (ping and pong) framebuffers from memory. > > > > > > > > > > . Add pan_display handler which toggles the LCDC DMA registers > > > > > between the ping and pong buffers. > > > > > > > > Hello, > > > > > > > > This patch breaks driver for a VGA display. After reverting this > > > > patch, display works as expected. Do you have any idea what may be > > > > the cause? I'm testing it on L-138 based Hawkboard. > > > > > > What is the nature of the error? Does the driver fail to > > > load/initialize? Does the user space API still work but the display is > > > corrupted? Something else? > > > > > > Regards, > > > Martin > > > > There is no error in log messages, but display is showing total garbage. > > > > I'm trying with framebuffer console but copying known patterns to fb0 > > also shows garbage. I prepared 3 raw images (red, green, blue) all having > > the same size as framebuffer. Then: > > > > $cp {red|green|blue} /dev/fb0 > > > > shows garbage for all three. > > > > I compared hsync, vsync, pclk video signals with the working case and all > > are the same. > > Hmm. I really have no idea what's wrong. > I've used the same code on with a DVI output patch (not in tree) which > works for me so I think the resolution portion should be ok. > What happens if userspace doesn't use FBIO_WAITFORVSYNC? Is it supposed to work without using FBIOPAN_DISPLAY and FBIO_WAITFORVSYNC ioctls? > There is a build control in the source drivers/video/da8xx-fb.c > > #define LCD_NUM_BUFFERS 2 > > You could try changing this to 1 to see if there is a difference. > Although not sure how much information about the root cause this would > generate. > Tried, nothing changed. I tried various other things, as well as diff'ing LCD register values, but I couldn't find anything. At the end of this mail I'm giving 2 different register sets, one is with your patch reverted and the other one is with your patch. Maybe it helps. > I couldn't find reference to the Hawkboard in the mainline. > Is there a git repo which I could use as a remote to look at diffs? > I'm currently working on adding support to mainline for that. That's why I'm tackling with this. Roger Monk gathered all the pieces together but his patch is based on Arago OMAP-L1 tree [1]. I'm trying to adopt it to mainline. Also yesterday Victor Rodriguez submitted a simple patch which has only UART support. Best Regards, Caglar [1] http://cgit.openembedded.org/cgit.cgi/openembedded/tree/recipes/linux/linux-davinci/hawkboard/patch-2.6.33rc4-psp-to-hawkboard.patch > Regards, > Martin > From caglarakyuz at gmail.com Wed Sep 1 11:57:32 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Wed, 1 Sep 2010 19:57:32 +0300 Subject: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering In-Reply-To: <201009011956.29788.caglarakyuz@gmail.com> References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011956.29788.caglarakyuz@gmail.com> Message-ID: <201009011957.32207.caglarakyuz@gmail.com> Forget add LCDC register values: not working: *** 4: 0x601 *** *** 8: 0x4 *** *** 40: 0x2ff0c1 *** *** 44: 0x3030fe70 *** *** 48: 0x1f0b05df *** *** 52: 0x270ff00 *** *** 64: 0x45 *** *** 68: 0xc7a00000 *** *** 72: 0xc7a95ffc *** *** 76: 0xc7a00000 *** *** 80: 0xc7a95ffc *** working: *** 4: 0x601 *** *** 8: 0x145 *** *** 40: 0xff0c1 *** *** 44: 0x3030fe70 *** *** 48: 0x1f0b05df *** *** 52: 0x270ff00 *** *** 64: 0x40 *** *** 68: 0xc7a00fe0 *** *** 72: 0xc7a96ffc *** Caglar On Wednesday 01 September 2010 07:56:29 pm Caglar Akyuz wrote: > On Wednesday 01 September 2010 06:16:21 pm Ambrose, Martin wrote: > > On Wed, Sep 01, 2010 at 09:44:48, Caglar Akyuz wrote: > > > On Wednesday 01 September 2010 05:33:00 pm Ambrose, Martin wrote: > > > > On Wed, Sep 01, 2010 at 05:01:38, Caglar Akyuz wrote: > > > > > On Tuesday 06 April 2010 12:54:59 am Ambrose, Martin wrote: > > > > > > This work includes the following: > > > > > > . Implement handler for FBIO_WAITFORVSYNC ioctl. > > > > > > > > > > > > . Allocate the data and palette buffers separately. > > > > > > A consequence of this is that the palette and data loading is > > > > > > now done in different phases. And that the LCD must be disabled > > > > > > temporarily after the palette is loaded but this will only happen > > > > > > once after init and each time the palette is changed. I think > > > > > > this is OK. > > > > > > > > > > > > . Allocate two (ping and pong) framebuffers from memory. > > > > > > > > > > > > . Add pan_display handler which toggles the LCDC DMA registers > > > > > > between the ping and pong buffers. > > > > > > > > > > Hello, > > > > > > > > > > This patch breaks driver for a VGA display. After reverting this > > > > > patch, display works as expected. Do you have any idea what may be > > > > > the cause? I'm testing it on L-138 based Hawkboard. > > > > > > > > What is the nature of the error? Does the driver fail to > > > > load/initialize? Does the user space API still work but the display > > > > is corrupted? Something else? > > > > > > > > Regards, > > > > Martin > > > > > > There is no error in log messages, but display is showing total > > > garbage. > > > > > > I'm trying with framebuffer console but copying known patterns to fb0 > > > also shows garbage. I prepared 3 raw images (red, green, blue) all > > > having the same size as framebuffer. Then: > > > > > > $cp {red|green|blue} /dev/fb0 > > > > > > shows garbage for all three. > > > > > > I compared hsync, vsync, pclk video signals with the working case and > > > all are the same. > > > > Hmm. I really have no idea what's wrong. > > I've used the same code on with a DVI output patch (not in tree) which > > works for me so I think the resolution portion should be ok. > > What happens if userspace doesn't use FBIO_WAITFORVSYNC? > Is it supposed to work without using FBIOPAN_DISPLAY and > FBIO_WAITFORVSYNC ioctls? > > > There is a build control in the source drivers/video/da8xx-fb.c > > > > #define LCD_NUM_BUFFERS 2 > > > > You could try changing this to 1 to see if there is a difference. > > Although not sure how much information about the root cause this would > > generate. > > Tried, nothing changed. > > I tried various other things, as well as diff'ing LCD register values, > but I couldn't find anything. At the end of this mail I'm giving 2 > different register sets, one is with your patch reverted and the other one > is with your patch. Maybe it helps. > > > I couldn't find reference to the Hawkboard in the mainline. > > Is there a git repo which I could use as a remote to look at diffs? > > I'm currently working on adding support to mainline for that. That's why > I'm tackling with this. Roger Monk gathered all the pieces together but > his patch is based on Arago OMAP-L1 tree [1]. I'm trying to adopt it to > mainline. Also yesterday Victor Rodriguez submitted a simple patch > which has only UART support. > > Best Regards, > Caglar > > [1] > http://cgit.openembedded.org/cgit.cgi/openembedded/tree/recipes/linux/linu > x-davinci/hawkboard/patch-2.6.33rc4-psp-to-hawkboard.patch > > > Regards, > > Martin > From martin at ti.com Wed Sep 1 11:59:00 2010 From: martin at ti.com (Ambrose, Martin) Date: Wed, 1 Sep 2010 11:59:00 -0500 Subject: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering In-Reply-To: <201009011957.32207.caglarakyuz@gmail.com> References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011956.29788.caglarakyuz@gmail.com>, <201009011957.32207.caglarakyuz@gmail.com> Message-ID: Can you provide the non working case with # buffers = 1? -Martin ________________________________________ From: Caglar Akyuz [caglarakyuz at gmail.com] Sent: Wednesday, September 01, 2010 11:57 AM To: Ambrose, Martin Cc: davinci-linux-open-source at linux.davincidsp.com Subject: Re: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering Forget add LCDC register values: not working: *** 4: 0x601 *** *** 8: 0x4 *** *** 40: 0x2ff0c1 *** *** 44: 0x3030fe70 *** *** 48: 0x1f0b05df *** *** 52: 0x270ff00 *** *** 64: 0x45 *** *** 68: 0xc7a00000 *** *** 72: 0xc7a95ffc *** *** 76: 0xc7a00000 *** *** 80: 0xc7a95ffc *** working: *** 4: 0x601 *** *** 8: 0x145 *** *** 40: 0xff0c1 *** *** 44: 0x3030fe70 *** *** 48: 0x1f0b05df *** *** 52: 0x270ff00 *** *** 64: 0x40 *** *** 68: 0xc7a00fe0 *** *** 72: 0xc7a96ffc *** Caglar On Wednesday 01 September 2010 07:56:29 pm Caglar Akyuz wrote: > On Wednesday 01 September 2010 06:16:21 pm Ambrose, Martin wrote: > > On Wed, Sep 01, 2010 at 09:44:48, Caglar Akyuz wrote: > > > On Wednesday 01 September 2010 05:33:00 pm Ambrose, Martin wrote: > > > > On Wed, Sep 01, 2010 at 05:01:38, Caglar Akyuz wrote: > > > > > On Tuesday 06 April 2010 12:54:59 am Ambrose, Martin wrote: > > > > > > This work includes the following: > > > > > > . Implement handler for FBIO_WAITFORVSYNC ioctl. > > > > > > > > > > > > . Allocate the data and palette buffers separately. > > > > > > A consequence of this is that the palette and data loading is > > > > > > now done in different phases. And that the LCD must be disabled > > > > > > temporarily after the palette is loaded but this will only happen > > > > > > once after init and each time the palette is changed. I think > > > > > > this is OK. > > > > > > > > > > > > . Allocate two (ping and pong) framebuffers from memory. > > > > > > > > > > > > . Add pan_display handler which toggles the LCDC DMA registers > > > > > > between the ping and pong buffers. > > > > > > > > > > Hello, > > > > > > > > > > This patch breaks driver for a VGA display. After reverting this > > > > > patch, display works as expected. Do you have any idea what may be > > > > > the cause? I'm testing it on L-138 based Hawkboard. > > > > > > > > What is the nature of the error? Does the driver fail to > > > > load/initialize? Does the user space API still work but the display > > > > is corrupted? Something else? > > > > > > > > Regards, > > > > Martin > > > > > > There is no error in log messages, but display is showing total > > > garbage. > > > > > > I'm trying with framebuffer console but copying known patterns to fb0 > > > also shows garbage. I prepared 3 raw images (red, green, blue) all > > > having the same size as framebuffer. Then: > > > > > > $cp {red|green|blue} /dev/fb0 > > > > > > shows garbage for all three. > > > > > > I compared hsync, vsync, pclk video signals with the working case and > > > all are the same. > > > > Hmm. I really have no idea what's wrong. > > I've used the same code on with a DVI output patch (not in tree) which > > works for me so I think the resolution portion should be ok. > > What happens if userspace doesn't use FBIO_WAITFORVSYNC? > Is it supposed to work without using FBIOPAN_DISPLAY and > FBIO_WAITFORVSYNC ioctls? > > > There is a build control in the source drivers/video/da8xx-fb.c > > > > #define LCD_NUM_BUFFERS 2 > > > > You could try changing this to 1 to see if there is a difference. > > Although not sure how much information about the root cause this would > > generate. > > Tried, nothing changed. > > I tried various other things, as well as diff'ing LCD register values, > but I couldn't find anything. At the end of this mail I'm giving 2 > different register sets, one is with your patch reverted and the other one > is with your patch. Maybe it helps. > > > I couldn't find reference to the Hawkboard in the mainline. > > Is there a git repo which I could use as a remote to look at diffs? > > I'm currently working on adding support to mainline for that. That's why > I'm tackling with this. Roger Monk gathered all the pieces together but > his patch is based on Arago OMAP-L1 tree [1]. I'm trying to adopt it to > mainline. Also yesterday Victor Rodriguez submitted a simple patch > which has only UART support. > > Best Regards, > Caglar > > [1] > http://cgit.openembedded.org/cgit.cgi/openembedded/tree/recipes/linux/linu > x-davinci/hawkboard/patch-2.6.33rc4-psp-to-hawkboard.patch > > > Regards, > > Martin > From Andreas.Gaer at baslerweb.com Wed Sep 1 12:20:46 2010 From: Andreas.Gaer at baslerweb.com (Gaer, A.) Date: Wed, 1 Sep 2010 19:20:46 +0200 Subject: Status of the Davinci EMAC driver Message-ID: Hello all, I am trying to find out, why the ethernet transmit performance of my device is rather poor. Using a DM368 chip, the live555 streaming framework is able to transmit a data rate of ~30 MBit/s using 70% CPU load. This is rather disapointing. After looking into the code of the driver in the LSP kernel, it seems that CRC offloading and TX interrupt pacing are not enabled which could explain why performance is rather poor. Are there any plans on implementing these features in the near future? Should one expect a significant performance boost by these features when sending large amounts of data? Does anybody know the reason why the hardware flow control is not used? Both ethtool and a quick look into the code suggest that hw flow control using pause frames is not enabled in the maccontrol register. Regards, Andreas. -------------- next part -------------- An HTML attachment was scrubbed... URL: From michael.williamson at criticallink.com Wed Sep 1 12:26:45 2010 From: michael.williamson at criticallink.com (Mike Williamson) Date: Wed, 1 Sep 2010 13:26:45 -0400 Subject: Status of the Davinci EMAC driver In-Reply-To: References: Message-ID: On Wed, Sep 1, 2010 at 1:20 PM, Gaer, A. wrote: > > Hello all, > > I am trying to find out, why the ethernet transmit performance of my device is rather poor. Using a DM368 chip, the live555 streaming framework is able to transmit a data rate of ~30 MBit/s using 70% CPU load. This is rather disapointing. > > After looking into the code of the driver in the LSP kernel, it seems that CRC offloading and TX interrupt pacing are not enabled which could explain why performance is rather poor. Are there any plans on implementing these features in the near future? Should one expect a significant performance boost by these features when sending large amounts of data? > I think there is already a patch for at least interrupt pacing queued up: https://patchwork.kernel.org/patch/115148/ -Mike -- Michael Williamson 315-425-4045x230 www.criticallink.com From caglarakyuz at gmail.com Wed Sep 1 12:50:31 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Wed, 1 Sep 2010 20:50:31 +0300 Subject: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering In-Reply-To: References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011957.32207.caglarakyuz@gmail.com> Message-ID: <201009012050.31144.caglarakyuz@gmail.com> On Wednesday 01 September 2010 07:59:00 pm Ambrose, Martin wrote: > Can you provide the non working case with # buffers = 1? > They are the same: *** 4: 0x601 *** *** 8: 0x4 *** *** 40: 0x2ff0c1 *** *** 44: 0x3030fe70 *** *** 48: 0x1f0b05df *** *** 52: 0x270ff00 *** *** 64: 0x45 *** *** 68: 0xc7a00000 *** *** 72: 0xc7a95ffc *** *** 76: 0xc7a00000 *** *** 80: 0xc7a95ffc *** Although fbset shows following: root at hawkboard:~# fbset mode "640x480-47" # D: 21.429 MHz, H: 25.787 kHz, V: 47.315 Hz geometry 640 480 640 480 16 timings 46666 64 64 32 32 63 1 accel false rgba 5/11,6/5,5/0,0/0 endmode While it shows following with LCD_NUM_BUFFERS = 2: root at hawkboard:~# fbset mode "640x480-47" # D: 21.429 MHz, H: 25.787 kHz, V: 47.315 Hz geometry 640 480 640 960 16 timings 46666 64 64 32 32 63 1 accel false rgba 5/11,6/5,5/0,0/0 endmode BTW, these reg dumps are taken at the end of fb_probe. Let me know if there is some better place. Caglar > -Martin > ________________________________________ > From: Caglar Akyuz [caglarakyuz at gmail.com] > Sent: Wednesday, September 01, 2010 11:57 AM > To: Ambrose, Martin > Cc: davinci-linux-open-source at linux.davincidsp.com > Subject: Re: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering > > Forget add LCDC register values: > > not working: > *** 4: 0x601 *** > *** 8: 0x4 *** > *** 40: 0x2ff0c1 *** > *** 44: 0x3030fe70 *** > *** 48: 0x1f0b05df *** > *** 52: 0x270ff00 *** > *** 64: 0x45 *** > *** 68: 0xc7a00000 *** > *** 72: 0xc7a95ffc *** > *** 76: 0xc7a00000 *** > *** 80: 0xc7a95ffc *** > > working: > *** 4: 0x601 *** > *** 8: 0x145 *** > *** 40: 0xff0c1 *** > *** 44: 0x3030fe70 *** > *** 48: 0x1f0b05df *** > *** 52: 0x270ff00 *** > *** 64: 0x40 *** > *** 68: 0xc7a00fe0 *** > *** 72: 0xc7a96ffc *** > > Caglar > > On Wednesday 01 September 2010 07:56:29 pm Caglar Akyuz wrote: > > On Wednesday 01 September 2010 06:16:21 pm Ambrose, Martin wrote: > > > On Wed, Sep 01, 2010 at 09:44:48, Caglar Akyuz wrote: > > > > On Wednesday 01 September 2010 05:33:00 pm Ambrose, Martin wrote: > > > > > On Wed, Sep 01, 2010 at 05:01:38, Caglar Akyuz wrote: > > > > > > On Tuesday 06 April 2010 12:54:59 am Ambrose, Martin wrote: > > > > > > > This work includes the following: > > > > > > > . Implement handler for FBIO_WAITFORVSYNC ioctl. > > > > > > > > > > > > > > . Allocate the data and palette buffers separately. > > > > > > > A consequence of this is that the palette and data loading > > > > > > > is now done in different phases. And that the LCD must be > > > > > > > disabled temporarily after the palette is loaded but this will > > > > > > > only happen once after init and each time the palette is > > > > > > > changed. I think this is OK. > > > > > > > > > > > > > > . Allocate two (ping and pong) framebuffers from memory. > > > > > > > > > > > > > > . Add pan_display handler which toggles the LCDC DMA registers > > > > > > > between the ping and pong buffers. > > > > > > > > > > > > Hello, > > > > > > > > > > > > This patch breaks driver for a VGA display. After reverting this > > > > > > patch, display works as expected. Do you have any idea what may > > > > > > be the cause? I'm testing it on L-138 based Hawkboard. > > > > > > > > > > What is the nature of the error? Does the driver fail to > > > > > load/initialize? Does the user space API still work but the display > > > > > is corrupted? Something else? > > > > > > > > > > Regards, > > > > > Martin > > > > > > > > There is no error in log messages, but display is showing total > > > > garbage. > > > > > > > > I'm trying with framebuffer console but copying known patterns to fb0 > > > > also shows garbage. I prepared 3 raw images (red, green, blue) all > > > > having the same size as framebuffer. Then: > > > > > > > > $cp {red|green|blue} /dev/fb0 > > > > > > > > shows garbage for all three. > > > > > > > > I compared hsync, vsync, pclk video signals with the working case and > > > > all are the same. > > > > > > Hmm. I really have no idea what's wrong. > > > I've used the same code on with a DVI output patch (not in tree) which > > > works for me so I think the resolution portion should be ok. > > > > What happens if userspace doesn't use FBIO_WAITFORVSYNC? > > Is it supposed to work without using FBIOPAN_DISPLAY and > > FBIO_WAITFORVSYNC ioctls? > > > > > There is a build control in the source drivers/video/da8xx-fb.c > > > > > > #define LCD_NUM_BUFFERS 2 > > > > > > You could try changing this to 1 to see if there is a difference. > > > Although not sure how much information about the root cause this would > > > generate. > > > > Tried, nothing changed. > > > > I tried various other things, as well as diff'ing LCD register values, > > but I couldn't find anything. At the end of this mail I'm giving 2 > > different register sets, one is with your patch reverted and the other > > one is with your patch. Maybe it helps. > > > > > I couldn't find reference to the Hawkboard in the mainline. > > > Is there a git repo which I could use as a remote to look at diffs? > > > > I'm currently working on adding support to mainline for that. That's why > > I'm tackling with this. Roger Monk gathered all the pieces together but > > his patch is based on Arago OMAP-L1 tree [1]. I'm trying to adopt it to > > mainline. Also yesterday Victor Rodriguez submitted a simple patch > > which has only UART support. > > > > Best Regards, > > Caglar > > > > [1] > > > > http://cgit.openembedded.org/cgit.cgi/openembedded/tree/recipes/linux/lin > >u x-davinci/hawkboard/patch-2.6.33rc4-psp-to-hawkboard.patch > > > > > Regards, > > > Martin > From martin at ti.com Wed Sep 1 13:30:53 2010 From: martin at ti.com (Ambrose, Martin) Date: Wed, 1 Sep 2010 13:30:53 -0500 Subject: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering In-Reply-To: <201009011957.32207.caglarakyuz@gmail.com> References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011956.29788.caglarakyuz@gmail.com> <201009011957.32207.caglarakyuz@gmail.com> Message-ID: On Wed, Sep 01, 2010 at 11:57:32, Caglar Akyuz wrote: > Forget add LCDC register values: > > not working: > *** 4: 0x601 *** > *** 8: 0x4 *** > *** 40: 0x2ff0c1 *** > *** 44: 0x3030fe70 *** > *** 48: 0x1f0b05df *** > *** 52: 0x270ff00 *** > *** 64: 0x45 *** > *** 68: 0xc7a00000 *** > *** 72: 0xc7a95ffc *** > *** 76: 0xc7a00000 *** > *** 80: 0xc7a95ffc *** > > working: > *** 4: 0x601 *** > *** 8: 0x145 *** > *** 40: 0xff0c1 *** > *** 44: 0x3030fe70 *** > *** 48: 0x1f0b05df *** > *** 52: 0x270ff00 *** > *** 64: 0x40 *** > *** 68: 0xc7a00fe0 *** > *** 72: 0xc7a96ffc *** If I am interpreting the above correctly then "*** 8" corresponds to LCD_STAT. In the working case bit 6 is set indicating the palette has been loaded whereas this is not set in the failure case. This was definitely an area of change in the double buffer patch. Prior the palette was loaded explicitly in the fb_probe function. In the double buffer case this is loaded by the setcolreg function. Normally this is called during kernel boot (I think) when the display is configured for the boot logo. If it is not then I believe you can force a call through a user space ioctl but I'm not sure what that is atm. Now if could be that the palette is being loaded but then there is an error afterwards. Can you add a debug print to the lcd_blit function to see if it is being called with LOAD_PALETTE? Regards, Martin From vm.rod25 at gmail.com Wed Sep 1 13:55:32 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Wed, 1 Sep 2010 13:55:32 -0500 Subject: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering In-Reply-To: <201009011956.29788.caglarakyuz@gmail.com> References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011744.48647.caglarakyuz@gmail.com> <201009011956.29788.caglarakyuz@gmail.com> Message-ID: On Wed, Sep 1, 2010 at 11:56 AM, Caglar Akyuz wrote: > On Wednesday 01 September 2010 06:16:21 pm Ambrose, Martin wrote: >> On Wed, Sep 01, 2010 at 09:44:48, Caglar Akyuz wrote: >> > On Wednesday 01 September 2010 05:33:00 pm Ambrose, Martin wrote: >> > > On Wed, Sep 01, 2010 at 05:01:38, Caglar Akyuz wrote: >> > > > On Tuesday 06 April 2010 12:54:59 am Ambrose, Martin wrote: >> > > > > This work includes the following: >> > > > > ?. Implement handler for FBIO_WAITFORVSYNC ioctl. >> > > > > >> > > > > ?. Allocate the data and palette buffers separately. >> > > > > ? ?A consequence of this is that the palette and data loading is >> > > > > now done in different phases. And that the LCD must be disabled >> > > > > temporarily after the palette is loaded but this will only happen >> > > > > once after init and each time the palette is changed. I think this >> > > > > is OK. >> > > > > >> > > > > ?. Allocate two (ping and pong) framebuffers from memory. >> > > > > >> > > > > ?. Add pan_display handler which toggles the LCDC DMA registers >> > > > > between the ping and pong buffers. >> > > > >> > > > Hello, >> > > > >> > > > This patch breaks driver for a VGA display. After reverting this >> > > > patch, display works as expected. ?Do you have any idea what may be >> > > > the cause? I'm testing it on L-138 based Hawkboard. >> > > >> > > What is the nature of the error? Does the driver fail to >> > > load/initialize? Does the user space API still work but the display is >> > > corrupted? Something else? >> > > >> > > Regards, >> > > Martin >> > >> > There is no error in log messages, but display is showing total garbage. >> > >> > I'm trying with framebuffer console but copying known patterns to fb0 >> > also shows garbage. I prepared 3 raw images (red, green, blue) all having >> > the same size as framebuffer. Then: >> > >> > $cp {red|green|blue} /dev/fb0 >> > >> > shows garbage for all three. >> > >> > I compared hsync, vsync, pclk video signals with the working case and all >> > are the same. >> >> Hmm. I really have no idea what's wrong. >> I've used the same code on with a DVI output patch (not in tree) which >> works for me so I think the resolution portion should be ok. >> > > What happens if userspace doesn't use FBIO_WAITFORVSYNC? > Is it supposed to work without using FBIOPAN_DISPLAY and > FBIO_WAITFORVSYNC ioctls? > >> There is a build control in the source drivers/video/da8xx-fb.c >> >> #define LCD_NUM_BUFFERS 2 >> >> You could try changing this to 1 to see if there is a difference. >> Although not sure how much information about the root cause this would >> ?generate. >> > > Tried, nothing changed. > > I tried various other things, as well as diff'ing LCD register values, > but I couldn't find anything. At the end of this mail I'm giving 2 different > register sets, one is with your patch reverted and the other one is > with your patch. Maybe it helps. > >> I couldn't find reference to the Hawkboard in the mainline. >> Is there a git repo which I could use as a remote to look at diffs? >> > > I'm currently working on adding support to mainline for that. That's why > I'm tackling with this. Roger Monk gathered all the pieces together but > his patch is based on Arago OMAP-L1 tree [1]. I'm trying to adopt it to > mainline. Also yesterday Victor Rodriguez submitted a simple patch > which has only UART support. > > Best Regards, > Caglar > > [1] http://cgit.openembedded.org/cgit.cgi/openembedded/tree/recipes/linux/linux-davinci/hawkboard/patch-2.6.33rc4-psp-to-hawkboard.patch > > >> Regards, >> Martin >> > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source at linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source > HI Caglar thanks for the efforts to migrate Hawkboard to main line, I have already the other patches for sound VGA and USB (still in process), do you want to work toughener in order to implement Hawk board to the mainline ? I have based my work in the link that you said in the begining,[1], actually you gave me that link few weeks ago, besides I am working with kernel, that exist in hawkboard.org Best Regards Victor Rodriguez [1] http://cgit.openembedded.org/cgit.cgi/openembedded/tree/recipes/linux/linux-davinci/hawkboard/patch-2.6.33rc4-psp-to-hawkboard.patch From caglarakyuz at gmail.com Wed Sep 1 14:20:00 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Wed, 1 Sep 2010 22:20:00 +0300 Subject: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering In-Reply-To: References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011957.32207.caglarakyuz@gmail.com> Message-ID: <201009012220.00479.caglarakyuz@gmail.com> On Wednesday 01 September 2010 09:30:53 pm Ambrose, Martin wrote: > On Wed, Sep 01, 2010 at 11:57:32, Caglar Akyuz wrote: > > Forget add LCDC register values: > > > > not working: > > *** 4: 0x601 *** > > *** 8: 0x4 *** > > *** 40: 0x2ff0c1 *** > > *** 44: 0x3030fe70 *** > > *** 48: 0x1f0b05df *** > > *** 52: 0x270ff00 *** > > *** 64: 0x45 *** > > *** 68: 0xc7a00000 *** > > *** 72: 0xc7a95ffc *** > > *** 76: 0xc7a00000 *** > > *** 80: 0xc7a95ffc *** > > > > working: > > *** 4: 0x601 *** > > *** 8: 0x145 *** > > *** 40: 0xff0c1 *** > > *** 44: 0x3030fe70 *** > > *** 48: 0x1f0b05df *** > > *** 52: 0x270ff00 *** > > *** 64: 0x40 *** > > *** 68: 0xc7a00fe0 *** > > *** 72: 0xc7a96ffc *** > > If I am interpreting the above correctly then "*** 8" corresponds to > LCD_STAT. Correct. > In the working case bit 6 is set indicating the palette has been > loaded whereas this is not set in the failure case. > > This was definitely an area of change in the double buffer patch. Prior the > palette was loaded explicitly in the fb_probe function. In the double > buffer case this is loaded by the setcolreg function. Normally this is > called during kernel boot (I think) when the display is configured for the > boot logo. > > If it is not then I believe you can force a call through a user space ioctl > but I'm not sure what that is atm. > > Now if could be that the palette is being loaded but then there is an error > afterwards. Can you add a debug print to the lcd_blit function to see if > it is being called with LOAD_PALETTE? > It seems like there is a race in the driver. Attached patch makes the problem go away. Any ideas for a proper fix? Thanks for the help, Caglar --- diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 309269f..ffc2f43 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -246,6 +246,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); } else if (load_mode == LOAD_PALETTE) { + printk("*** %s: LOAD_PALETTE ***\n", __func__); start = par->p_palette_base; end = start + par->palette_sz - 1; > Regards, > Martin > From martin at ti.com Wed Sep 1 14:34:23 2010 From: martin at ti.com (Ambrose, Martin) Date: Wed, 1 Sep 2010 14:34:23 -0500 Subject: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering In-Reply-To: <201009012220.00479.caglarakyuz@gmail.com> References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011957.32207.caglarakyuz@gmail.com> <201009012220.00479.caglarakyuz@gmail.com> Message-ID: On Wed, Sep 01, 2010 at 14:20:00, Caglar Akyuz wrote: > On Wednesday 01 September 2010 09:30:53 pm Ambrose, Martin wrote: > > On Wed, Sep 01, 2010 at 11:57:32, Caglar Akyuz wrote: [snip] > > If I am interpreting the above correctly then "*** 8" corresponds to > > LCD_STAT. > > Correct. > > > In the working case bit 6 is set indicating the palette has been > > loaded whereas this is not set in the failure case. > > > > This was definitely an area of change in the double buffer patch. Prior the > > palette was loaded explicitly in the fb_probe function. In the double > > buffer case this is loaded by the setcolreg function. Normally this is > > called during kernel boot (I think) when the display is configured for the > > boot logo. > > > > If it is not then I believe you can force a call through a user space ioctl > > but I'm not sure what that is atm. > > > > Now if could be that the palette is being loaded but then there is an error > > afterwards. Can you add a debug print to the lcd_blit function to see if > > it is being called with LOAD_PALETTE? > > > > It seems like there is a race in the driver. Attached patch makes the > problem go away. Looks like just adding the printf changed which side of the race condition you are on. Correct? > Any ideas for a proper fix? Sorry my breadth of knowledge here is pretty shallow. This patch was my first exposure to the framebuffer architecture. I think I would need to be able to recreate the problem to better analyze. And, unfortunately, don't have a Hawkboard myself. If you or Roger have a spare board I can take a more in-depth look but likely not until beginning of Oct due to prior commits. Regards, Martin > Thanks for the help, > Caglar > > --- > > diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c > index 309269f..ffc2f43 100644 > --- a/drivers/video/da8xx-fb.c > +++ b/drivers/video/da8xx-fb.c > @@ -246,6 +246,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) > lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); > lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); > } else if (load_mode == LOAD_PALETTE) { > + printk("*** %s: LOAD_PALETTE ***\n", __func__); > start = par->p_palette_base; > end = start + par->palette_sz - 1; > > > > Regards, > > Martin > > Regards, Martin From caglarakyuz at gmail.com Wed Sep 1 15:41:17 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Wed, 1 Sep 2010 23:41:17 +0300 Subject: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering In-Reply-To: References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009012220.00479.caglarakyuz@gmail.com> Message-ID: <201009012341.17458.caglarakyuz@gmail.com> On Wednesday 01 September 2010 10:34:23 pm Ambrose, Martin wrote: > On Wed, Sep 01, 2010 at 14:20:00, Caglar Akyuz wrote: > > On Wednesday 01 September 2010 09:30:53 pm Ambrose, Martin wrote: > > > On Wed, Sep 01, 2010 at 11:57:32, Caglar Akyuz wrote: > > [snip] > [...] > > Looks like just adding the printf changed which side of the race condition > you are on. Correct? > Yes. > > Any ideas for a proper fix? > > Sorry my breadth of knowledge here is pretty shallow. This patch was my > first exposure to the framebuffer architecture. > > I think I would need to be able to recreate the problem to better analyze. I think race is between irq_handler and fb_setcolreg. Registering irq_handler at the end of probe function solves the issue.(Patch is attached) I don't know da8xx lcd controller enough but one of your comments in the code says lcd raster controller should be disabled prior to any register update. So I think following sequence happens on my board: - raster controller is disabled - fb_setcolreg is called at boot time as you pointed out - irq fires-up, enables raster controller - fb_setcolreg calls lcd_blit which modifies LCD_RASTER_CTRL_REG while raster controller is enabled printk delayed irq and the problem disappeared, registering irq at the end of probe function served the same purpose. > And, unfortunately, don't have a Hawkboard myself. If you or Roger > have a spare board I can take a more in-depth look but likely not until > beginning of Oct due to prior commits. > I never thought TIers would be in a short of development boards, I think I'm being harsh on my local TI representatives :) Thanks for all your help on this and for eventually pointing the source of the problem. Best Regards, Caglar --- diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 0ad6fe4..edb0616 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -1020,10 +1020,6 @@ static int __init fb_probe(struct platform_device *device) goto err_release_pl_mem; } - ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); - if (ret) - goto err_release_pl_mem; - /* Initialize par */ da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp; @@ -1051,7 +1047,7 @@ static int __init fb_probe(struct platform_device *device) ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); if (ret) - goto err_free_irq; + goto err_release_pl_mem; da8xx_fb_info->cmap.len = par->palette_sz; /* initialize var_screeninfo */ @@ -1079,8 +1075,13 @@ static int __init fb_probe(struct platform_device *device) goto err_cpu_freq; } #endif + + ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); + if (ret) + goto irq_freq; return 0; +irq_freq: #ifdef CONFIG_CPU_FREQ err_cpu_freq: unregister_framebuffer(da8xx_fb_info); @@ -1089,9 +1090,6 @@ err_cpu_freq: err_dealloc_cmap: fb_dealloc_cmap(&da8xx_fb_info->cmap); -err_free_irq: - free_irq(par->irq, par); - err_release_pl_mem: dma_free_coherent(NULL, PALETTE_SIZE, par->v_palette_base, par->p_palette_base); From davideaston at nanometrics.ca Wed Sep 1 15:47:53 2010 From: davideaston at nanometrics.ca (David Easton) Date: Wed, 1 Sep 2010 16:47:53 -0400 Subject: Status of OMAPL138 compared to Arago In-Reply-To: References: Message-ID: 2010/9/1 Marc-Andr? H?bert > > I was thinking of rebasing my tree with the linux-davinci instead to > facilitate long term support. Is anyone aware if there are any > OMAPL138 devices that would be functional in the Arago tree but not > yet in the linux-davinci tree (could be because of rejected patches > for whatever reasons)? My boards require SPI (0,1), I2C(0,1), SATA, > MMCSD (0,1), Ethernet (RMII), UART(0), USB (0,1), McASP. > I believe that the current capabilities of the linux-davinci tree are already documented [1]. You may hopefully find that page to be of some help. [1] http://processors.wiki.ti.com/index.php/DaVinci_GIT_Linux_Kernel Regards, David Easton Nanometrics Inc. http://www.nanometrics.ca From caglarakyuz at gmail.com Wed Sep 1 16:20:13 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Thu, 2 Sep 2010 00:20:13 +0300 Subject: Hawkboard Support in Mainline (was Re: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering) In-Reply-To: References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011956.29788.caglarakyuz@gmail.com> Message-ID: <201009020020.13445.caglarakyuz@gmail.com> On Wednesday 01 September 2010 09:55:32 pm Victor Rodriguez wrote: > HI Caglar thanks for the efforts to migrate Hawkboard to main line, I > have already the other patches for sound VGA and USB (still in > process), do you want to work toughener in order to implement Hawk > board to the mainline ? I have based my work in the link that you said > in the begining,[1], actually you gave me that link few weeks ago, > besides I am working with kernel, that exist in hawkboard.org > Hi, Sure, we should work together. Better the sooner. Here is my comments of the current situation: Some components should be removed from Roger Monk's patches and added later: - NAND aemif timing should be removed and added back when following patch goes in: davinci: add support for aemif timing configuration - McBSP support should be removed, AFAIK there is no support in mainline Linux - VPIF support is present but only for DM6467. So no camera support for now. - DA850 RTC support is broken, can be added back when a proper fix goes in. and following components should work: - VGA. Martin Ambrose solved my problem about VGA. There was some comments on this mailing list when Khasim first submitted patches, so I'm trying to improve da8xx-fb at the moment for proper display handling. - I never had chance to play with SATA, but I think every bit is present in mainline to make it work. - MUSB should work I guess. - USB host was working 3-4 months ago when I first tested Hawkboard with mainline, only OHCI glue layer was missing at that time. IIRC, Sergei Shtylyov pushed glue layer last merge window or before. - Sound support is the most trivial I guess, we can use existing DA850 code with minor modifications. If it is rejected, we can prepare a different board file for ASOC. - Ethernet support is working at the moment. All testing I do with NFS. This is where I am and what I'm working on. On the following days I will be dealing with SPI bits so don't know if I can submit anything at the moment. If your situation is better than mine, then please post your patches to the mailing list and if they get accepted then I will send my patches as incremental patches to yours, or, please summarize your findings so that we can join our efforts. One last point, I think we should try to keep Roger Monk(CCed) in the loop. We should add his signed-off to the patches as well(if he is ok with it) as he is the original author and probably much more familiar with the everything about Hawk than we are. Thanks for putting your time on this. Best Regards, Caglar > Best Regards > > Victor Rodriguez > > [1] > http://cgit.openembedded.org/cgit.cgi/openembedded/tree/recipes/linux/linu > x-davinci/hawkboard/patch-2.6.33rc4-psp-to-hawkboard.patch > From vm.rod25 at gmail.com Wed Sep 1 17:24:34 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Wed, 1 Sep 2010 17:24:34 -0500 Subject: Hawkboard Support in Mainline (was Re: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering) In-Reply-To: <201009020020.13445.caglarakyuz@gmail.com> References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011956.29788.caglarakyuz@gmail.com> <201009020020.13445.caglarakyuz@gmail.com> Message-ID: HI Caglar On Wed, Sep 1, 2010 at 4:20 PM, Caglar Akyuz wrote: > On Wednesday 01 September 2010 09:55:32 pm Victor Rodriguez wrote: >> HI Caglar thanks for the efforts to migrate Hawkboard to main line, I >> have already the other patches for sound VGA and USB (still in >> process), do you want to work toughener in order to implement Hawk >> board to the mainline ? I have based my work in the link that you said >> in the begining,[1], actually you gave me that link few weeks ago, >> besides I am working with kernel, that exist in hawkboard.org >> > > Hi, > > Sure, we should work together. Better the sooner. Here is my comments of the > current situation: > > Some components should be removed from Roger Monk's patches and added later: > > - NAND aemif timing should be removed and added back when following patch goes > in: > ? ? ? ?davinci: add support for aemif timing configuration Ok I think the same > - McBSP support should be removed, AFAIK there is no support in mainline Linux Ok > > - VPIF support is present but only for DM6467. So no camera support for now. Good idea > > - DA850 RTC support is broken, can be added back when a proper fix goes in. > > and following components should work: > > - VGA. Martin Ambrose solved my problem about VGA. There was some comments on > this mailing list when Khasim first submitted patches, so I'm trying to > improve da8xx-fb at the moment for proper display handling. Great it works now i laso found some problems in the VGA but did not care to much about it when i started porting to mainline > - I never had chance to play with SATA, but I think every bit is present in > mainline to make it work. me nether, but I think it should be in future patches > - MUSB should work I guess. It is a little bit complicated, the names of some functions and structures has change since 2.6.35+ was realized > - USB host was working 3-4 months ago when I first tested Hawkboard with > mainline, only OHCI glue layer was missing at that time. IIRC, Sergei Shtylyov > pushed glue layer last merge window or before. Let me check that > - Sound support is the most trivial I guess, we can use existing DA850 code > with minor modifications. If it is rejected, we can prepare a different board > file for ASOC. > > - Ethernet support is working at the moment. All testing I do with NFS. Yes hopefully it is working > This is where I am and what I'm working on. On the following days I will be > dealing with SPI bits so don't know if I can submit anything at the moment. If > your situation is better than mine, then please post your patches to the > mailing list and if they get accepted then I will send my patches as > incremental patches to yours, or, please summarize your findings so that we > can join our efforts. In the beginning when I asked to you in hawkboard.org about the argo tree and then start to work to devolop a patch for the Roger Monk patch and the main line that existed on that time (2.6.2.35-rc6). I get it and every thing works fine except USB and MUSB i disable those in the menuconfig, but when I made git pull my patch did not apply :( so I started to clear my patch to just UART communication, and finally last Friday i got it. for the latest version of kernel 2.6.36 -rc2 Now that i already have the basic support for serial communication i can start to rebase my patch that works fine in 2.6.35-rc6 to 2.6.36-rc2 I will send those patches ass soon as posible in the order that you said in this email > One last point, I think we should try to keep Roger Monk(CCed) in the loop. We > should add his signed-off to the patches as well(if he is ok with it) as he is > the original author and probably much more familiar with the everything about > Hawk than we are. Yes I think the same, also Khasim , the one how wrote the board-da850-hawk.c should be a very good help One more thing in the begining i asked to kevin how to apply a patch and he told me that the best is to have a patch for initial support , just UART and nothing more, I do not know when is the next rc3 available but the best is to achive that the hawkboard appear in the mainline for the next rc3 and then we start to submit all the patches for VGA, USB, and anything, please , check the patch that i have sent and if there is any bug that you foud we could fix it and improve the patch together . Other people has mention me about copy rights errors and problems in the the Kconfig, but nothing about bugs or kernel panics So in resume I start to send to the mail list more patches for all the other things, but it will not apply if the main support for hawk board is not approved by Kevin We will share these patches and checked in hardware In the end aour goal is to have a complete support for hawk board in the main line :) > > Thanks for putting your time on this. No problem i like this job :) Best regards Victor Rodriguez > > Best Regards, > Caglar > >> Best Regards >> >> Victor Rodriguez >> >> [1] >> ?http://cgit.openembedded.org/cgit.cgi/openembedded/tree/recipes/linux/linu >> x-davinci/hawkboard/patch-2.6.33rc4-psp-to-hawkboard.patch >> > From vm.rod25 at gmail.com Wed Sep 1 17:55:04 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Wed, 1 Sep 2010 17:55:04 -0500 Subject: Hawkboard Support in Mainline (was Re: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering) In-Reply-To: References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011956.29788.caglarakyuz@gmail.com> <201009020020.13445.caglarakyuz@gmail.com> Message-ID: On Wed, Sep 1, 2010 at 5:24 PM, Victor Rodriguez wrote: > HI Caglar > > On Wed, Sep 1, 2010 at 4:20 PM, Caglar Akyuz wrote: >> On Wednesday 01 September 2010 09:55:32 pm Victor Rodriguez wrote: >>> HI Caglar thanks for the efforts to migrate Hawkboard to main line, I >>> have already the other patches for sound VGA and USB (still in >>> process), do you want to work toughener in order to implement Hawk >>> board to the mainline ? I have based my work in the link that you said >>> in the begining,[1], actually you gave me that link few weeks ago, >>> besides I am working with kernel, that exist in hawkboard.org >>> >> >> Hi, >> >> Sure, we should work together. Better the sooner. Here is my comments of the >> current situation: >> >> Some components should be removed from Roger Monk's patches and added later: >> >> - NAND aemif timing should be removed and added back when following patch goes >> in: >> ? ? ? ?davinci: add support for aemif timing configuration > > Ok I think the same > > >> - McBSP support should be removed, AFAIK there is no support in mainline Linux > > Ok > >> >> - VPIF support is present but only for DM6467. So no camera support for now. > > Good idea > >> >> - DA850 RTC support is broken, can be added back when a proper fix goes in. >> >> and following components should work: >> >> - VGA. Martin Ambrose solved my problem about VGA. There was some comments on >> this mailing list when Khasim first submitted patches, so I'm trying to >> improve da8xx-fb at the moment for proper display handling. > > > Great it works now i laso found some problems in the VGA but did not > care to much about it when i started porting to mainline > > > >> - I never had chance to play with SATA, but I think every bit is present in >> mainline to make it work. > > me nether, but I think it should be in future patches > >> - MUSB should work I guess. > > It is a little bit complicated, the names of some functions and > structures has change since 2.6.35+ was realized > > > >> - USB host was working 3-4 months ago when I first tested Hawkboard with >> mainline, only OHCI glue layer was missing at that time. IIRC, Sergei Shtylyov >> pushed glue layer last merge window or before. > > Let me check that > >> - Sound support is the most trivial I guess, we can use existing DA850 code >> with minor modifications. If it is rejected, we can prepare a different board >> file for ASOC. >> >> - Ethernet support is working at the moment. All testing I do with NFS. > > Yes hopefully it is working > > >> This is where I am and what I'm working on. On the following days I will be >> dealing with SPI bits so don't know if I can submit anything at the moment. If >> your situation is better than mine, then please post your patches to the >> mailing list and if they get accepted then I will send my patches as >> incremental patches to yours, or, please summarize your findings so that we >> can join our efforts. > > > In the beginning when I asked to you in hawkboard.org about the argo > tree and then start to work to devolop a patch for the Roger Monk > patch and the main line that existed on that time (2.6.2.35-rc6). I > get it and every thing works fine except USB and MUSB i disable those > in the menuconfig, but when I made git pull my patch did not apply :( > so I started to clear my patch to just UART communication, and finally > last Friday i got it. for the latest version of kernel 2.6.36 -rc2 > > Now that i already have the basic support for serial communication i > can start to rebase my patch that works fine in 2.6.35-rc6 to > 2.6.36-rc2 > > I will send those patches ass soon as posible in the order that you > said in this email > > >> One last point, I think we should try to keep Roger Monk(CCed) in the loop. We >> should add his signed-off to the patches as well(if he is ok with it) as he is >> the original author and probably much more familiar with the everything about >> Hawk than we are. > > Yes I think the same, also Khasim , the one how wrote the > board-da850-hawk.c should be a very good help > > One more thing in the begining i asked to kevin how to apply a patch > and he told me that the best is to have a patch for initial support , > just UART and nothing more, I do not know when is the next rc3 > available but the best is to achive that the hawkboard appear in the > mainline for the next rc3 and then we start to submit all the patches > for VGA, USB, and anything, please , check the patch that i have sent > and if there is any bug that you foud we could fix it and improve the > patch together . Other people has mention me about copy rights errors > and problems in the the Kconfig, but nothing about bugs or kernel > panics > > So in resume > > I start to send to the mail list more patches for all the other > things, but it will not apply if the main support for hawk board is > not approved by Kevin > > We will share these patches and checked in hardware > > In the end aour goal is to have a complete support for hawk board in > the main line :) > >> >> Thanks for putting your time on this. > > > No problem i like this job :) > > Best regards > > Victor Rodriguez > > >> >> Best Regards, >> Caglar >> >>> Best Regards >>> >>> Victor Rodriguez >>> >>> [1] >>> ?http://cgit.openembedded.org/cgit.cgi/openembedded/tree/recipes/linux/linu >>> x-davinci/hawkboard/patch-2.6.33rc4-psp-to-hawkboard.patch >>> >> > HI Caglar one more thing I have time to work in hawkboard support for mainline. Do you have any patch already for hawkboard runing ? if yes Tell me which one and i start to work in other one based on your patches, this is in order to avoid the double work if not I can do it and send the patches as soon as possible and you start to work in other ones if you want to work on them tell me how much time it will take to you and i will start to work on another things Tell me what do you think about it I am most interest that exist a support for hawk board in main line, but we need to hurry Best regards Victor Rodriguez From vm.rod25 at gmail.com Wed Sep 1 19:30:34 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Wed, 1 Sep 2010 19:30:34 -0500 Subject: Fwd: [PATCH] hawkboard v_2 In-Reply-To: <4C7E1DB4.3070208@mvista.com> References: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> <4C7E1DB4.3070208@mvista.com> Message-ID: On Wed, Sep 1, 2010 at 4:32 AM, Sergei Shtylyov wrote: > Victor Rodriguez wrote: > >> Basic support for Hawkboard OMAPL138 just UART cominication is included > >> Signed-off-by: Victor Rodriguez > >> Notes: ?This patch deletes empty lines and typo mistakes from previous >> version > > ? These notes belong to the space under the --- tear line, not to the patch > description. > Ok sorry my mistake, fIxed for next version >> ? ? ? ?This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 >> from >> ? ? ? ?Kernel development tree for TI DaVinci family of processors > >> ? ? ? ?This patch works with basic da8xx_omapl_defconfig, it just have >> basic support >> ? ? ? ?for UART console > >> ? ? ? ?This patch just works with UART 2 for argo file system > >> Signed-off-by: Victor Rodriguez > > [...] >> >> diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig >> index 2bf03e9..fd8a11c 100644 >> --- a/arch/arm/mach-davinci/Kconfig >> +++ b/arch/arm/mach-davinci/Kconfig >> @@ -185,6 +185,15 @@ config MACH_TNETV107X >> ? ? ? ?help >> ? ? ? ? ?Say Y here to select the TI TNETV107X Evaluation Module. >> ?+config MACH_OMAPL138_HAWKBOARD >> + ? ? ? bool "TI DA850/OMAP-L138/AM18xx Hawkboard(.org) Platform" >> + ? ? ? default ARCH_DAVINCI_DA850 > > ? As I've already said, only EVM boards are enabled by default. Question i have deleted the default ARCH_DAVINCI_DA850 but I have a problem because my board-da850-hawk.c does not compile and because of that when i boot the uImage is impossible to uncompress my kernel image. So do you suggest any other way to fix that with out altering the da8xx_omapl_defconfig? I have already checked the latest change in Kconfig ant is config MACH_TNETV107X bool "TI TNETV107X Reference Platform" default ARCH_DAVINCI_TNETV107X depends on ARCH_DAVINCI_TNETV107X help Say Y here to select the TI TNETV107X Evaluation Module. which also has default. Please clarify this doubt Is one of the few thinks that i need in order to implement the patch > [...] >> >> diff --git a/arch/arm/mach-davinci/board-da850-hawk.c >> b/arch/arm/mach-davinci/board-da850-hawk.c > >> new file mode 100644 >> index 0000000..4a7f2da >> --- /dev/null >> +++ b/arch/arm/mach-davinci/board-da850-hawk.c >> @@ -0,0 +1,67 @@ >> +/* >> + * Hawkboard.org based on TI's OMAP-L138 Platform >> + * >> + * Initial code: Syed Mohammed Khasim >> + * >> + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com >> + * >> + * Derived from: arch/arm/mach-davinci/board-da830-hawk.c >> + * Original Copyrights follow: >> + * >> + * 2007, 2009 (c) MontaVista Software, Inc. This file is licensed under > > ? As I said, the original copyright is invalid. I have changed it to +/* + * Hawkboard.org based on TI's OMAP-L138 Platform + * + * Initial code: Syed Mohammed Khasim + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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. + */ Is this Ok ? Thanks for the help I am really interested to give initial support for Hawkboard Sincerely yours VIctor Rodriguez > WBR, Sergei > From vm.rod25 at gmail.com Wed Sep 1 19:36:26 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Wed, 1 Sep 2010 19:36:26 -0500 Subject: [PATCH v2] davinci: Initial support for Omapl138-Hawkboard Message-ID: <1283387786-30386-1-git-send-email-vm.rod25@gmail.com> This patch adds initial support for the Hawkboard-L138 system under the machine name "omapl138_hawkboard". This system is based on the da850 davinci CPU architecture. Information on these system may be found at http://www.hawkboard.org. Basic support for the console UART is included in this patch. Signed-off-by: Victor Rodriguez --- Changes since v1: 1) Correct copyrights. 2) Delete empty lines and typo mistakes from previous version Notes: This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 from Kernel development tree for TI DaVinci family of processors This patch works with da8xx_omapl_defconfig. This patch just works with UART 2 for argo file system arch/arm/mach-davinci/Kconfig | 9 +++ arch/arm/mach-davinci/Makefile | 1 + arch/arm/mach-davinci/board-da850-hawk.c | 63 +++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/uncompress.h | 1 + 4 files changed, 74 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/board-da850-hawk.c diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 2bf03e9..fd8a11c 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -185,6 +185,15 @@ config MACH_TNETV107X help Say Y here to select the TI TNETV107X Evaluation Module. +config MACH_OMAPL138_HAWKBOARD + bool "TI DA850/OMAP-L138/AM18xx Hawkboard(.org) Platform" + default ARCH_DAVINCI_DA850 + depends on ARCH_DAVINCI_DA850 + help + Say Y here to select the TI DA850/OMAP-L138/AM18xx Hawkboard. + Information of this board may be found at + http://www.hawkboard.org/ + config DAVINCI_MUX bool "DAVINCI multiplexing support" depends on ARCH_DAVINCI diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index eab4c0f..fd271cd 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-da850-hawk.o # Power Management obj-$(CONFIG_CPU_FREQ) += cpufreq.o diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c new file mode 100644 index 0000000..d897e4a --- /dev/null +++ b/arch/arm/mach-davinci/board-da850-hawk.c @@ -0,0 +1,63 @@ +/* + * Hawkboard.org based on TI's OMAP-L138 Platform + * + * Initial code: Syed Mohammed Khasim + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 +#include +#include +#include + +#include +#include + +#include +#include + +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { + .enabled_uarts = 0x7, +}; + +static __init void omapl138_hawk_init(void) +{ + + davinci_serial_init(&omapl138_hawk_uart_config); + + /* + * shut down uart 0 and 1; they are not used on the board and + * accessing them causes endless "too much work in irq53" messages + * with arago fs + */ + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); + +} + +#ifdef CONFIG_SERIAL_8250_CONSOLE +static int __init omapl138_hawk_console_init(void) +{ + return add_preferred_console("ttyS", 2, "115200"); +} +console_initcall(omapl138_hawk_console_init); +#endif + +static void __init omapl138_hawk_map_io(void) +{ + da850_init(); +} + +MACHINE_START(OMAPL138_HAWKBOARD, "OMAPL 138 Hawkboard.org") + .phys_io = IO_PHYS, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, + .boot_params = (DA8XX_DDR_BASE + 0x100), + .map_io = omapl138_hawk_map_io, + .init_irq = cp_intc_init, + .timer = &davinci_timer, + .init_machine = omapl138_hawk_init, +MACHINE_END diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h index 15a6192..640f834 100644 --- a/arch/arm/mach-davinci/include/mach/uncompress.h +++ b/arch/arm/mach-davinci/include/mach/uncompress.h @@ -88,6 +88,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) /* DA8xx boards */ DEBUG_LL_DA8XX(davinci_da830_evm, 2); DEBUG_LL_DA8XX(davinci_da850_evm, 2); + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); /* TNETV107x boards */ DEBUG_LL_TNETV107X(tnetv107x, 1); -- 1.6.0.5 From sshtylyov at mvista.com Thu Sep 2 05:40:30 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Thu, 02 Sep 2010 14:40:30 +0400 Subject: Fwd: [PATCH] hawkboard v_2 In-Reply-To: References: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> <4C7E1DB4.3070208@mvista.com> Message-ID: <4C7F7F1E.1060501@mvista.com> On 02.09.2010 4:30, Victor Rodriguez wrote: >>> Basic support for Hawkboard OMAPL138 just UART cominication is included >>> Signed-off-by: Victor Rodriguez >>> Notes: This patch deletes empty lines and typo mistakes from previous >>> version >> These notes belong to the space under the --- tear line, not to the patch >> description. > Ok sorry my mistake, fIxed for next version >>> This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 >>> from >>> Kernel development tree for TI DaVinci family of processors >>> This patch works with basic da8xx_omapl_defconfig, it just have >>> basic support >>> for UART console >>> This patch just works with UART 2 for argo file system >>> Signed-off-by: Victor Rodriguez >> [...] >>> diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig >>> index 2bf03e9..fd8a11c 100644 >>> --- a/arch/arm/mach-davinci/Kconfig >>> +++ b/arch/arm/mach-davinci/Kconfig >>> @@ -185,6 +185,15 @@ config MACH_TNETV107X >>> help >>> Say Y here to select the TI TNETV107X Evaluation Module. >>> +config MACH_OMAPL138_HAWKBOARD >>> + bool "TI DA850/OMAP-L138/AM18xx Hawkboard(.org) Platform" >>> + default ARCH_DAVINCI_DA850 >> As I've already said, only EVM boards are enabled by default. > Question i have deleted the > default ARCH_DAVINCI_DA850 > but I have a problem because my board-da850-hawk.c does not compile > and because of that when i boot the uImage is impossible to uncompress > my kernel image. > So do you suggest any other way to fix that with out altering the > da8xx_omapl_defconfig? Why do you not want to alter it? I think you should. > I have already checked the latest change in Kconfig ant is > config MACH_TNETV107X > bool "TI TNETV107X Reference Platform" > default ARCH_DAVINCI_TNETV107X > depends on ARCH_DAVINCI_TNETV107X > help > Say Y here to select the TI TNETV107X Evaluation Module. > which also has default. Because this is the evaluation board. > Please clarify this doubt Is one of the few thinks that i need in > order to implement the patch >> [...] >>> diff --git a/arch/arm/mach-davinci/board-da850-hawk.c >>> b/arch/arm/mach-davinci/board-da850-hawk.c >>> new file mode 100644 >>> index 0000000..4a7f2da >>> --- /dev/null >>> +++ b/arch/arm/mach-davinci/board-da850-hawk.c >>> @@ -0,0 +1,67 @@ >>> +/* >>> + * Hawkboard.org based on TI's OMAP-L138 Platform >>> + * >>> + * Initial code: Syed Mohammed Khasim >>> + * >>> + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com >>> + * >>> + * Derived from: arch/arm/mach-davinci/board-da830-hawk.c Oh, and this was bogus too. >>> + * Original Copyrights follow: >>> + * >>> + * 2007, 2009 (c) MontaVista Software, Inc. This file is licensed under >> As I said, the original copyright is invalid. > I have changed it to > +/* > + * Hawkboard.org based on TI's OMAP-L138 Platform > + * > + * Initial code: Syed Mohammed Khasim > + * > + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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. > + */ > Is this Ok ? I guess so. > Thanks for the help I am really interested to give initial support for Hawkboard > Sincerely yours > VIctor Rodriguez WBR, Sergei From vm.rod25 at gmail.com Thu Sep 2 08:54:55 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Thu, 2 Sep 2010 08:54:55 -0500 Subject: Fwd: [PATCH] hawkboard v_2 In-Reply-To: <4C7F7F1E.1060501@mvista.com> References: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> <4C7E1DB4.3070208@mvista.com> <4C7F7F1E.1060501@mvista.com> Message-ID: On Thu, Sep 2, 2010 at 5:40 AM, Sergei Shtylyov wrote: > On 02.09.2010 4:30, Victor Rodriguez wrote: > >>>> Basic support for Hawkboard OMAPL138 just UART cominication is included > >>>> Signed-off-by: Victor Rodriguez > >>>> Notes: ?This patch deletes empty lines and typo mistakes from previous >>>> version > >>> ? These notes belong to the space under the --- tear line, not to the >>> patch >>> description. > >> Ok sorry my mistake, fIxed for next version > >>>> ? ? ? ?This patch is checked with >>>> 0a50e05b20f3c6af67656303bdb3661a2541ce03 >>>> from >>>> ? ? ? ?Kernel development tree for TI DaVinci family of processors > >>>> ? ? ? ?This patch works with basic da8xx_omapl_defconfig, it just have >>>> basic support >>>> ? ? ? ?for UART console > >>>> ? ? ? ?This patch just works with UART 2 for argo file system > >>>> Signed-off-by: Victor Rodriguez > >>> [...] > >>>> diff --git a/arch/arm/mach-davinci/Kconfig >>>> b/arch/arm/mach-davinci/Kconfig >>>> index 2bf03e9..fd8a11c 100644 >>>> --- a/arch/arm/mach-davinci/Kconfig >>>> +++ b/arch/arm/mach-davinci/Kconfig >>>> @@ -185,6 +185,15 @@ config MACH_TNETV107X >>>> ? ? ? ?help >>>> ? ? ? ? ?Say Y here to select the TI TNETV107X Evaluation Module. >>>> ?+config MACH_OMAPL138_HAWKBOARD >>>> + ? ? ? bool "TI DA850/OMAP-L138/AM18xx Hawkboard(.org) Platform" >>>> + ? ? ? default ARCH_DAVINCI_DA850 > >>> ? As I've already said, only EVM boards are enabled by default. > >> Question i have deleted the > >> default ARCH_DAVINCI_DA850 > >> but I have a problem because my board-da850-hawk.c does not compile >> and because of that when i boot the uImage is impossible to uncompress >> my kernel image. > >> So do you suggest any other way to fix that with out altering the >> da8xx_omapl_defconfig? > > ? Why do you not want to alter it? I think you should. Because the discussion that exist in defconfig files in the linux-kernel at vger.kernel.org mailing list, Linus complain about the lack of order in defconfig files. But if you sugest that is ok i would try to modify . So i leave the Kconfig just like this ? +config MACH_OMAPL138_HAWKBOARD + bool "TI DA850/OMAP-L138/AM18xx Hawkboard(.org) Platform" + depends on ARCH_DAVINCI_DA850 + help + Say Y here to select the TI DA850/OMAP-L138/AM18xx Hawkboard. + Information of this board may be found at + http://www.hawkboard.org/ + Thanks Sincerely yours VIctor Rodriguez >> I have already checked the latest change in Kconfig ant is > >> config MACH_TNETV107X >> ? ? ? ?bool "TI TNETV107X Reference Platform" >> ? ? ? ?default ARCH_DAVINCI_TNETV107X >> ? ? ? ?depends on ARCH_DAVINCI_TNETV107X >> ? ? ? ?help >> ? ? ? ? ?Say Y here to select the TI TNETV107X Evaluation Module. > >> which also has default. > > ? Because this is the evaluation board. > >> Please clarify this doubt Is one of the few thinks that i need in >> order to implement the patch > >>> [...] > >>>> diff --git a/arch/arm/mach-davinci/board-da850-hawk.c >>>> b/arch/arm/mach-davinci/board-da850-hawk.c >>>> new file mode 100644 >>>> index 0000000..4a7f2da >>>> --- /dev/null >>>> +++ b/arch/arm/mach-davinci/board-da850-hawk.c >>>> @@ -0,0 +1,67 @@ >>>> +/* >>>> + * Hawkboard.org based on TI's OMAP-L138 Platform >>>> + * >>>> + * Initial code: Syed Mohammed Khasim >>>> + * >>>> + * Copyright (C) 2009 Texas Instruments Incorporated - >>>> http://www.ti.com >>>> + * >>>> + * Derived from: arch/arm/mach-davinci/board-da830-hawk.c > > ? Oh, and this was bogus too. > >>>> + * Original Copyrights follow: >>>> + * >>>> + * 2007, 2009 (c) MontaVista Software, Inc. This file is licensed under > >>> ? As I said, the original copyright is invalid. > >> I have changed it to > >> +/* >> + * Hawkboard.org based on TI's OMAP-L138 Platform >> + * >> + * Initial code: Syed Mohammed Khasim >> + * >> + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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. >> + */ > >> Is this Ok ? > > ? I guess so. > >> Thanks for the help I am really interested to give initial support for >> Hawkboard > >> Sincerely yours > >> VIctor Rodriguez > > WBR, Sergei > From vm.rod25 at gmail.com Thu Sep 2 09:07:24 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Thu, 2 Sep 2010 09:07:24 -0500 Subject: Fwd: [PATCH] hawkboard v_2 In-Reply-To: References: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> <4C7E1DB4.3070208@mvista.com> <4C7F7F1E.1060501@mvista.com> Message-ID: On Thu, Sep 2, 2010 at 8:54 AM, Victor Rodriguez wrote: > On Thu, Sep 2, 2010 at 5:40 AM, Sergei Shtylyov wrote: >> On 02.09.2010 4:30, Victor Rodriguez wrote: >> >>>>> Basic support for Hawkboard OMAPL138 just UART cominication is included >> >>>>> Signed-off-by: Victor Rodriguez >> >>>>> Notes: ?This patch deletes empty lines and typo mistakes from previous >>>>> version >> >>>> ? These notes belong to the space under the --- tear line, not to the >>>> patch >>>> description. >> >>> Ok sorry my mistake, fIxed for next version >> >>>>> ? ? ? ?This patch is checked with >>>>> 0a50e05b20f3c6af67656303bdb3661a2541ce03 >>>>> from >>>>> ? ? ? ?Kernel development tree for TI DaVinci family of processors >> >>>>> ? ? ? ?This patch works with basic da8xx_omapl_defconfig, it just have >>>>> basic support >>>>> ? ? ? ?for UART console >> >>>>> ? ? ? ?This patch just works with UART 2 for argo file system >> >>>>> Signed-off-by: Victor Rodriguez >> >>>> [...] >> >>>>> diff --git a/arch/arm/mach-davinci/Kconfig >>>>> b/arch/arm/mach-davinci/Kconfig >>>>> index 2bf03e9..fd8a11c 100644 >>>>> --- a/arch/arm/mach-davinci/Kconfig >>>>> +++ b/arch/arm/mach-davinci/Kconfig >>>>> @@ -185,6 +185,15 @@ config MACH_TNETV107X >>>>> ? ? ? ?help >>>>> ? ? ? ? ?Say Y here to select the TI TNETV107X Evaluation Module. >>>>> ?+config MACH_OMAPL138_HAWKBOARD >>>>> + ? ? ? bool "TI DA850/OMAP-L138/AM18xx Hawkboard(.org) Platform" >>>>> + ? ? ? default ARCH_DAVINCI_DA850 >> >>>> ? As I've already said, only EVM boards are enabled by default. >> >>> Question i have deleted the >> >>> default ARCH_DAVINCI_DA850 >> >>> but I have a problem because my board-da850-hawk.c does not compile >>> and because of that when i boot the uImage is impossible to uncompress >>> my kernel image. >> >>> So do you suggest any other way to fix that with out altering the >>> da8xx_omapl_defconfig? >> >> ? Why do you not want to alter it? I think you should. > > > Because the discussion that exist in defconfig files in the > linux-kernel at vger.kernel.org mailing list, Linus complain about the > lack of order in defconfig files. > > But if you sugest that is ok i would try to modify . > > So i leave the Kconfig just like this ? > > +config MACH_OMAPL138_HAWKBOARD > + ? ? ? bool "TI DA850/OMAP-L138/AM18xx Hawkboard(.org) Platform" > + ? ? ? depends on ARCH_DAVINCI_DA850 > + ? ? ? help > + ? ? ? ? Say Y here to select the TI DA850/OMAP-L138/AM18xx Hawkboard. > + ? ? ? ? Information of this board may be found at > + ? ? ? ? http://www.hawkboard.org/ One more question I have checked the Michael Williamson patch and he has +config MACH_MITYOMAPL138 + bool "Critical Link MityDSP-L138/MityARM-1808 SoM" + default ARCH_DAVINCI_DA850 >> just like my patch + depends on ARCH_DAVINCI_DA850 + help + Say Y here to select the Critical Link MityDSP-L138/MityARM-1808 + System on Module. Information on this SoM may be found at + http://www.mitydsp.com + Why is this ok ? And he only alter the da8xx-omapl-defconfig by this way diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig index ba66705..3952a4e 100644 --- a/arch/arm/configs/da8xx_omapl_defconfig +++ b/arch/arm/configs/da8xx_omapl_defconfig @@ -79,6 +79,7 @@ CONFIG_I2C_DAVINCI=y # CONFIG_HWMON is not set CONFIG_WATCHDOG=y CONFIG_REGULATOR=y +CONFIG_REGULATOR_DUMMY=y CONFIG_REGULATOR_TPS6507X=y CONFIG_FB=y CONFIG_FB_DA8XX=y Any clue what I am doing this wrong Thanks Victor Rodriguez > > Thanks > > Sincerely yours > > VIctor ?Rodriguez > > >>> I have already checked the latest change in Kconfig ant is >> >>> config MACH_TNETV107X >>> ? ? ? ?bool "TI TNETV107X Reference Platform" >>> ? ? ? ?default ARCH_DAVINCI_TNETV107X >>> ? ? ? ?depends on ARCH_DAVINCI_TNETV107X >>> ? ? ? ?help >>> ? ? ? ? ?Say Y here to select the TI TNETV107X Evaluation Module. >> >>> which also has default. >> >> ? Because this is the evaluation board. >> >>> Please clarify this doubt Is one of the few thinks that i need in >>> order to implement the patch >> >>>> [...] >> >>>>> diff --git a/arch/arm/mach-davinci/board-da850-hawk.c >>>>> b/arch/arm/mach-davinci/board-da850-hawk.c >>>>> new file mode 100644 >>>>> index 0000000..4a7f2da >>>>> --- /dev/null >>>>> +++ b/arch/arm/mach-davinci/board-da850-hawk.c >>>>> @@ -0,0 +1,67 @@ >>>>> +/* >>>>> + * Hawkboard.org based on TI's OMAP-L138 Platform >>>>> + * >>>>> + * Initial code: Syed Mohammed Khasim >>>>> + * >>>>> + * Copyright (C) 2009 Texas Instruments Incorporated - >>>>> http://www.ti.com >>>>> + * >>>>> + * Derived from: arch/arm/mach-davinci/board-da830-hawk.c >> >> ? Oh, and this was bogus too. >> >>>>> + * Original Copyrights follow: >>>>> + * >>>>> + * 2007, 2009 (c) MontaVista Software, Inc. This file is licensed under >> >>>> ? As I said, the original copyright is invalid. >> >>> I have changed it to >> >>> +/* >>> + * Hawkboard.org based on TI's OMAP-L138 Platform >>> + * >>> + * Initial code: Syed Mohammed Khasim >>> + * >>> + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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. >>> + */ >> >>> Is this Ok ? >> >> ? I guess so. >> >>> Thanks for the help I am really interested to give initial support for >>> Hawkboard >> >>> Sincerely yours >> >>> VIctor Rodriguez >> >> WBR, Sergei >> > From khilman at deeprootsystems.com Thu Sep 2 09:54:17 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 02 Sep 2010 07:54:17 -0700 Subject: Fwd: [PATCH] hawkboard v_2 In-Reply-To: (Victor Rodriguez's message of "Thu, 2 Sep 2010 09:07:24 -0500") References: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> <4C7E1DB4.3070208@mvista.com> <4C7F7F1E.1060501@mvista.com> Message-ID: <878w3kci1y.fsf@deeprootsystems.com> Victor Rodriguez writes: > On Thu, Sep 2, 2010 at 8:54 AM, Victor Rodriguez wrote: >> On Thu, Sep 2, 2010 at 5:40 AM, Sergei Shtylyov wrote: >>> On 02.09.2010 4:30, Victor Rodriguez wrote: >>> >>>>>> Basic support for Hawkboard OMAPL138 just UART cominication is included >>> >>>>>> Signed-off-by: Victor Rodriguez >>> >>>>>> Notes: ?This patch deletes empty lines and typo mistakes from previous >>>>>> version >>> >>>>> ? These notes belong to the space under the --- tear line, not to the >>>>> patch >>>>> description. >>> >>>> Ok sorry my mistake, fIxed for next version >>> >>>>>> ? ? ? ?This patch is checked with >>>>>> 0a50e05b20f3c6af67656303bdb3661a2541ce03 >>>>>> from >>>>>> ? ? ? ?Kernel development tree for TI DaVinci family of processors >>> >>>>>> ? ? ? ?This patch works with basic da8xx_omapl_defconfig, it just have >>>>>> basic support >>>>>> ? ? ? ?for UART console >>> >>>>>> ? ? ? ?This patch just works with UART 2 for argo file system >>> >>>>>> Signed-off-by: Victor Rodriguez >>> >>>>> [...] >>> >>>>>> diff --git a/arch/arm/mach-davinci/Kconfig >>>>>> b/arch/arm/mach-davinci/Kconfig >>>>>> index 2bf03e9..fd8a11c 100644 >>>>>> --- a/arch/arm/mach-davinci/Kconfig >>>>>> +++ b/arch/arm/mach-davinci/Kconfig >>>>>> @@ -185,6 +185,15 @@ config MACH_TNETV107X >>>>>> ? ? ? ?help >>>>>> ? ? ? ? ?Say Y here to select the TI TNETV107X Evaluation Module. >>>>>> ?+config MACH_OMAPL138_HAWKBOARD >>>>>> + ? ? ? bool "TI DA850/OMAP-L138/AM18xx Hawkboard(.org) Platform" >>>>>> + ? ? ? default ARCH_DAVINCI_DA850 >>> >>>>> ? As I've already said, only EVM boards are enabled by default. >>> >>>> Question i have deleted the >>> >>>> default ARCH_DAVINCI_DA850 >>> >>>> but I have a problem because my board-da850-hawk.c does not compile >>>> and because of that when i boot the uImage is impossible to uncompress >>>> my kernel image. >>> >>>> So do you suggest any other way to fix that with out altering the >>>> da8xx_omapl_defconfig? >>> >>> ? Why do you not want to alter it? I think you should. >> >> >> Because the discussion that exist in defconfig files in the >> linux-kernel at vger.kernel.org mailing list, Linus complain about the >> lack of order in defconfig files. That's a slightly separate issue. Linus has been irritated with the huge number of defconfigs. Making readable changes to them is just fine. >> But if you sugest that is ok i would try to modify . >> >> So i leave the Kconfig just like this ? >> >> +config MACH_OMAPL138_HAWKBOARD >> + ? ? ? bool "TI DA850/OMAP-L138/AM18xx Hawkboard(.org) Platform" >> + ? ? ? depends on ARCH_DAVINCI_DA850 >> + ? ? ? help >> + ? ? ? ? Say Y here to select the TI DA850/OMAP-L138/AM18xx Hawkboard. >> + ? ? ? ? Information of this board may be found at >> + ? ? ? ? http://www.hawkboard.org/ > > One more question > > I have checked the Michael Williamson patch and he has > > +config MACH_MITYOMAPL138 > + bool "Critical Link MityDSP-L138/MityARM-1808 SoM" > + default ARCH_DAVINCI_DA850 >> just like my patch > + depends on ARCH_DAVINCI_DA850 > + help > + Say Y here to select the Critical Link MityDSP-L138/MityARM-1808 > + System on Module. Information on this SoM may be found at > + http://www.mitydsp.com > + > > Why is this ok ? His hasn't been merged yet either. > And he only alter the da8xx-omapl-defconfig by this way > > > diff --git a/arch/arm/configs/da8xx_omapl_defconfig > b/arch/arm/configs/da8xx_omapl_defconfig > index ba66705..3952a4e 100644 > --- a/arch/arm/configs/da8xx_omapl_defconfig > +++ b/arch/arm/configs/da8xx_omapl_defconfig > @@ -79,6 +79,7 @@ CONFIG_I2C_DAVINCI=y > # CONFIG_HWMON is not set > CONFIG_WATCHDOG=y > CONFIG_REGULATOR=y > +CONFIG_REGULATOR_DUMMY=y > CONFIG_REGULATOR_TPS6507X=y > CONFIG_FB=y > CONFIG_FB_DA8XX=y This is an unrelated change. > Any clue what I am doing this wrong So, what Sergei mentioned is that by default, in the Kconfigs, the (relatively arbitrary) policy we've had is that only the TI official EVMs have been enabled by default *in the Kconfig*. IOW, Sergei is suggesting that you don't enable your board by default in the Kconfig, but you should enable it by default in da8xx_omapl_defconfig. Kevin From nsekhar at ti.com Thu Sep 2 10:08:45 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Thu, 2 Sep 2010 20:38:45 +0530 Subject: [PATCH v2] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <1283387786-30386-1-git-send-email-vm.rod25@gmail.com> References: <1283387786-30386-1-git-send-email-vm.rod25@gmail.com> Message-ID: Hi Victor, On Thu, Sep 02, 2010 at 06:06:26, Victor Rodriguez wrote: > This patch adds initial support for the Hawkboard-L138 system under the machine name "omapl138_hawkboard". This system is based on the da850 davinci CPU architecture. Information on these system may be found at http://www.hawkboard.org. > Less than 80 characters per line in patch description is required. > diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig > index 2bf03e9..fd8a11c 100644 > --- a/arch/arm/mach-davinci/Kconfig > +++ b/arch/arm/mach-davinci/Kconfig > @@ -185,6 +185,15 @@ config MACH_TNETV107X > help > Say Y here to select the TI TNETV107X Evaluation Module. > > +config MACH_OMAPL138_HAWKBOARD > + bool "TI DA850/OMAP-L138/AM18xx Hawkboard(.org) Platform" > + default ARCH_DAVINCI_DA850 > + depends on ARCH_DAVINCI_DA850 > + help > + Say Y here to select the TI DA850/OMAP-L138/AM18xx Hawkboard. "AM18x" is enough. > + Information of this board may be found at > + http://www.hawkboard.org/ > + > +#ifdef CONFIG_SERIAL_8250_CONSOLE > +static int __init omapl138_hawk_console_init(void) > +{ > + return add_preferred_console("ttyS", 2, "115200"); > +} > +console_initcall(omapl138_hawk_console_init); > +#endif Michael recently fixed an issue with this code. Please make a similar fix here. http://linux.davincidsp.com/pipermail/davinci-linux-open-source/2010-August/020040.html > + > +static void __init omapl138_hawk_map_io(void) > +{ > + da850_init(); > +} > + > +MACHINE_START(OMAPL138_HAWKBOARD, "OMAPL 138 Hawkboard.org") TI documentation usually refers to the part as "OMAP-L138" Thanks, Sekhar From nsekhar at ti.com Thu Sep 2 10:31:28 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Thu, 2 Sep 2010 21:01:28 +0530 Subject: Hawkboard Support in Mainline (was Re: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering) In-Reply-To: <201009020020.13445.caglarakyuz@gmail.com> References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009011956.29788.caglarakyuz@gmail.com> <201009020020.13445.caglarakyuz@gmail.com> Message-ID: Hi Caglar, On Thu, Sep 02, 2010 at 02:50:13, Caglar Akyuz wrote: > - DA850 RTC support is broken, can be added back when a proper fix goes in. Hmm, I thought this was working. Can you specify what is broken? > - MUSB should work I guess. MUSB DMA support is still under discussion. I guess PIO mode should be possible to get working. Thanks, Sekhar From caglarakyuz at gmail.com Thu Sep 2 11:06:57 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Thu, 2 Sep 2010 19:06:57 +0300 Subject: Hawkboard Support in Mainline (was Re: [PATCH v3 1/1] DA8XX/OMAP-L1XX: FB: Implement double buffering) In-Reply-To: References: <1270504278-15088-1-git-send-email-martin@ti.com> <201009020020.13445.caglarakyuz@gmail.com> Message-ID: <201009021906.57289.caglarakyuz@gmail.com> On Thursday 02 September 2010 06:31:28 pm Nori, Sekhar wrote: > Hi Caglar, > > On Thu, Sep 02, 2010 at 02:50:13, Caglar Akyuz wrote: > > - DA850 RTC support is broken, can be added back when a proper fix goes > > in. > > Hmm, I thought this was working. Can you specify what is broken? > On some of the boards we faced locking ups when rtc is enabled. Last kernel log was(with arago tree): Switching to clocksource timer0_1 Roger Monk was mentioned that they found the root cause but I don't know. First time I tried this on mainline status was the same. But I tried a lot of things these days, maybe I missed something. > > - MUSB should work I guess. > > MUSB DMA support is still under discussion. I guess PIO mode should be > possible to get working. > That's what I'm thinking. Best Regards, Caglar > Thanks, > Sekhar > From khilman at deeprootsystems.com Thu Sep 2 12:00:20 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 02 Sep 2010 10:00:20 -0700 Subject: [PATCH] hawkboard v_2 In-Reply-To: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> (Victor Rodriguez's message of "Tue, 31 Aug 2010 14:48:36 -0500") References: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> Message-ID: <87y6bk9j2z.fsf@deeprootsystems.com> Victor Rodriguez writes: > Basic support for Hawkboard OMAPL138 just UART cominication is included > > Signed-off-by: Victor Rodriguez > [...] > +static __init void omapl138_hawk_init(void) > +{ > + > + davinci_serial_init(&omapl138_hawk_uart_config); > + > + /* > + * shut down uart 0 and 1; they are not used on the board and > + * accessing them causes endless "too much work in irq53" messages > + * with arago fs > + */ > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); This hack/workaround needs to be removed and/or better described so we know *why* such a thing is needed. Khasim, do you know what the root cause is here? Kevin > +} > > +#ifdef CONFIG_SERIAL_8250_CONSOLE > +static int __init omapl138_hawk_console_init(void) > +{ > + return add_preferred_console("ttyS", 2, "115200"); > +} > +console_initcall(omapl138_hawk_console_init); > +#endif > + > +static void __init omapl138_hawk_map_io(void) > +{ > + da850_init(); > +} > + > +MACHINE_START(OMAPL138_HAWKBOARD, "OMAPL 138 Hawkboard.org") > + .phys_io = IO_PHYS, > + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, > + .boot_params = (DA8XX_DDR_BASE + 0x100), > + .map_io = omapl138_hawk_map_io, > + .init_irq = cp_intc_init, > + .timer = &davinci_timer, > + .init_machine = omapl138_hawk_init, > +MACHINE_END > diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h > index 15a6192..640f834 100644 > --- a/arch/arm/mach-davinci/include/mach/uncompress.h > +++ b/arch/arm/mach-davinci/include/mach/uncompress.h > @@ -88,6 +88,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) > /* DA8xx boards */ > DEBUG_LL_DA8XX(davinci_da830_evm, 2); > DEBUG_LL_DA8XX(davinci_da850_evm, 2); > + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); > > /* TNETV107x boards */ > DEBUG_LL_TNETV107X(tnetv107x, 1); From khilman at deeprootsystems.com Thu Sep 2 12:05:02 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 02 Sep 2010 10:05:02 -0700 Subject: [PATCH] davinci: Add machine checks to DA8XX serial console init routines In-Reply-To: <1283279415-25678-1-git-send-email-michael.williamson@criticallink.com> (Michael Williamson's message of "Tue, 31 Aug 2010 14:30:15 -0400") References: <1283279415-25678-1-git-send-email-michael.williamson@criticallink.com> Message-ID: <87r5hc9iv5.fsf@deeprootsystems.com> Michael Williamson writes: > This patch adds machine checks in the serial console init routines > for the DA8XX EVM boards. This is needed because there are other > DA8XX based machines that use a different UART/tty as the console > and may be included in a common kernel build. > > Signed-off-by: Michael Williamson Applied, queueing for 2.6.37 in davinci-next branch. Thanks, Kevin > --- > arch/arm/mach-davinci/board-da830-evm.c | 3 +++ > arch/arm/mach-davinci/board-da850-evm.c | 3 +++ > 2 files changed, 6 insertions(+), 0 deletions(-) > > diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c > index 292e8b7..e51a80f 100644 > --- a/arch/arm/mach-davinci/board-da830-evm.c > +++ b/arch/arm/mach-davinci/board-da830-evm.c > @@ -586,6 +586,9 @@ static __init void da830_evm_init(void) > #ifdef CONFIG_SERIAL_8250_CONSOLE > static int __init da830_evm_console_init(void) > { > + if (!machine_is_davinci_da830_evm()) > + return 0; > + > return add_preferred_console("ttyS", 2, "115200"); > } > console_initcall(da830_evm_console_init); > diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c > index 190ebd3..d491b5f 100644 > --- a/arch/arm/mach-davinci/board-da850-evm.c > +++ b/arch/arm/mach-davinci/board-da850-evm.c > @@ -847,6 +847,9 @@ static __init void da850_evm_init(void) > #ifdef CONFIG_SERIAL_8250_CONSOLE > static int __init da850_evm_console_init(void) > { > + if (!machine_is_davinci_da850_evm()) > + return 0; > + > return add_preferred_console("ttyS", 2, "115200"); > } > console_initcall(da850_evm_console_init); From khasim at ti.com Thu Sep 2 12:05:09 2010 From: khasim at ti.com (Syed Mohammed, Khasim) Date: Thu, 2 Sep 2010 22:35:09 +0530 Subject: [PATCH] hawkboard v_2 In-Reply-To: <87y6bk9j2z.fsf@deeprootsystems.com> References: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> <87y6bk9j2z.fsf@deeprootsystems.com> Message-ID: <0680EC522D0CC943BC586913CF3768C003C1CA50ED@dbde02.ent.ti.com> Kevin, > -----Original Message----- > From: davinci-linux-open-source-bounces+khasim=ti.com at linux.davincidsp.com > [mailto:davinci-linux-open-source-bounces+khasim=ti.com at linux.davincidsp.com] > On Behalf Of Kevin Hilman > Sent: Thursday, September 02, 2010 10:30 PM > To: Victor Rodriguez > Cc: davinci-linux-open-source at linux.davincidsp.com > Subject: Re: [PATCH] hawkboard v_2 > > Victor Rodriguez writes: > > > Basic support for Hawkboard OMAPL138 just UART cominication is included > > > > Signed-off-by: Victor Rodriguez > > > > [...] > > > +static __init void omapl138_hawk_init(void) > > +{ > > + > > + davinci_serial_init(&omapl138_hawk_uart_config); > > + > > + /* > > + * shut down uart 0 and 1; they are not used on the board and > > + * accessing them causes endless "too much work in irq53" messages > > + * with arago fs > > + */ > > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > > + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); > > This hack/workaround needs to be removed and/or better described so we > know *why* such a thing is needed. > > Khasim, do you know what the root cause is here? I will have to look into this, I will get back to you in a day or two. Regards, Khasim From khilman at deeprootsystems.com Thu Sep 2 12:05:15 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 02 Sep 2010 10:05:15 -0700 Subject: [PATCH] davinci: Add CONFIG_REGULATOR_DUMMY to DA8XX defconfig file. In-Reply-To: <1283280152-26059-1-git-send-email-michael.williamson@criticallink.com> (Michael Williamson's message of "Tue, 31 Aug 2010 14:42:32 -0400") References: <1283280152-26059-1-git-send-email-michael.williamson@criticallink.com> Message-ID: <87mxs09ius.fsf@deeprootsystems.com> Michael Williamson writes: > In order to support reference DA8XX machines not providing a > voltage regulator control for the core voltage, the REGULATOR_DUMMY > option is required. > > Signed-off-by: Michael Williamson Applied, queueing for 2.6.37 in davinci-next branch. Thanks, Kevin > --- > arch/arm/configs/da8xx_omapl_defconfig | 1 + > 1 files changed, 1 insertions(+), 0 deletions(-) > > diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig > index ba66705..3952a4e 100644 > --- a/arch/arm/configs/da8xx_omapl_defconfig > +++ b/arch/arm/configs/da8xx_omapl_defconfig > @@ -79,6 +79,7 @@ CONFIG_I2C_DAVINCI=y > # CONFIG_HWMON is not set > CONFIG_WATCHDOG=y > CONFIG_REGULATOR=y > +CONFIG_REGULATOR_DUMMY=y > CONFIG_REGULATOR_TPS6507X=y > CONFIG_FB=y > CONFIG_FB_DA8XX=y From khilman at deeprootsystems.com Thu Sep 2 12:09:17 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 02 Sep 2010 10:09:17 -0700 Subject: [PATCH v2] davinci: Initial support for MityDSP-L138/MityARM-1808 In-Reply-To: <1283281015-28360-1-git-send-email-michael.williamson@criticallink.com> (Michael Williamson's message of "Tue, 31 Aug 2010 14:56:55 -0400") References: <1283281015-28360-1-git-send-email-michael.williamson@criticallink.com> Message-ID: <87d3sw9io2.fsf@deeprootsystems.com> Michael Williamson writes: > This patch adds initial support for the MityDSP-L138 and MityDSP-1808 system > on Module (SOM) under the machine name "mityomapl138". These SOMs are based > on the da850 davinci CPU architecture. Information on these SOMs may be > found at http://www.mitydsp.com. > > Basic support for the console UART, NAND, and EMAC (MII interface) is > included in this patch. > > Signed-off-by: Michael Williamson Looks good, one comple very minor things left... > --- > Changes since v1: > 1) Split out defconfig changes to separate patch. > 2) Split out console init changes to DA8XX EVMS to separate patch. > 3) Change a pr_info() to a pr_debug(). > > arch/arm/mach-davinci/Kconfig | 9 + > arch/arm/mach-davinci/Makefile | 1 + > arch/arm/mach-davinci/board-mityomapl138.c | 220 +++++++++++++++++++++++ > arch/arm/mach-davinci/include/mach/uncompress.h | 1 + > 4 files changed, 231 insertions(+), 0 deletions(-) > create mode 100644 arch/arm/mach-davinci/board-mityomapl138.c > > diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig > index 2bf03e9..633eccb 100644 > --- a/arch/arm/mach-davinci/Kconfig > +++ b/arch/arm/mach-davinci/Kconfig > @@ -185,6 +185,15 @@ config MACH_TNETV107X > help > Say Y here to select the TI TNETV107X Evaluation Module. > > +config MACH_MITYOMAPL138 > + bool "Critical Link MityDSP-L138/MityARM-1808 SoM" > + default ARCH_DAVINCI_DA850 We have a (admittedly arbitrary) policy of only enabling the official EVM boards in the Kconfig. However, feel free to enable your board by default in da8xx_omapl_defconfig. > + depends on ARCH_DAVINCI_DA850 > + help > + Say Y here to select the Critical Link MityDSP-L138/MityARM-1808 > + System on Module. Information on this SoM may be found at > + http://www.mitydsp.com > + > config DAVINCI_MUX > bool "DAVINCI multiplexing support" > depends on ARCH_DAVINCI > diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile > index eab4c0f..3e966e8 100644 > --- a/arch/arm/mach-davinci/Makefile > +++ b/arch/arm/mach-davinci/Makefile > @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o > obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o > obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o > obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o > +obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o > > # Power Management > obj-$(CONFIG_CPU_FREQ) += cpufreq.o > diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c > new file mode 100644 > index 0000000..f95cd9c > --- /dev/null > +++ b/arch/arm/mach-davinci/board-mityomapl138.c > @@ -0,0 +1,220 @@ > +/* > + * Critical Link MityOMAP-L138 SoM > + * > + * Copyright (C) 2010 Critical Link LLC - http://www.criticallink.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 > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define MITYOMAPL138_PHY_MASK 0x08 /* hardcoded for now */ > +#define MITYOMAPL138_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ > + > +/* > + * MityDSP-L138 includes a 256 MByte large-page NAND flash > + * (128K blocks). > + */ > +struct mtd_partition mityomapl138_nandflash_partition[] = { > + { > + .name = "rootfs", > + .offset = 0, > + .size = SZ_128M, > + .mask_flags = 0, /* MTD_WRITEABLE, */ > + }, > + { > + .name = "homefs", > + .offset = MTDPART_OFS_APPEND, > + .size = MTDPART_SIZ_FULL, > + .mask_flags = 0, > + }, > +}; > + > +static struct davinci_nand_pdata mityomapl138_nandflash_data = { > + .parts = mityomapl138_nandflash_partition, > + .nr_parts = ARRAY_SIZE(mityomapl138_nandflash_partition), > + .ecc_mode = NAND_ECC_HW, > + .options = NAND_USE_FLASH_BBT | NAND_BUSWIDTH_16, > + .ecc_bits = 1, /* 4 bit mode is not supported with 16 bit NAND */ Missing a tab in this list line for alignment. [...] Kevin From sshtylyov at mvista.com Thu Sep 2 12:23:03 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Thu, 02 Sep 2010 21:23:03 +0400 Subject: [PATCH] davinci: Add machine checks to DA8XX serial console init routines In-Reply-To: <87r5hc9iv5.fsf@deeprootsystems.com> References: <1283279415-25678-1-git-send-email-michael.williamson@criticallink.com> <87r5hc9iv5.fsf@deeprootsystems.com> Message-ID: <4C7FDD77.3010204@mvista.com> Hello. Kevin Hilman wrote: >> This patch adds machine checks in the serial console init routines >> for the DA8XX EVM boards. This is needed because there are other >> DA8XX based machines that use a different UART/tty as the console >> and may be included in a common kernel build. >> Signed-off-by: Michael Williamson > Applied, queueing for 2.6.37 in davinci-next branch. But this is a bugfix, no? WBR, Sergei From khilman at deeprootsystems.com Thu Sep 2 12:30:25 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 02 Sep 2010 10:30:25 -0700 Subject: [PATCH] davinci: Add machine checks to DA8XX serial console init routines In-Reply-To: <4C7FDD77.3010204@mvista.com> (Sergei Shtylyov's message of "Thu, 02 Sep 2010 21:23:03 +0400") References: <1283279415-25678-1-git-send-email-michael.williamson@criticallink.com> <87r5hc9iv5.fsf@deeprootsystems.com> <4C7FDD77.3010204@mvista.com> Message-ID: <87r5hc834e.fsf@deeprootsystems.com> Sergei Shtylyov writes: > Hello. > > Kevin Hilman wrote: > >>> This patch adds machine checks in the serial console init routines >>> for the DA8XX EVM boards. This is needed because there are other >>> DA8XX based machines that use a different UART/tty as the console >>> and may be included in a common kernel build. > >>> Signed-off-by: Michael Williamson > >> Applied, queueing for 2.6.37 in davinci-next branch. > > But this is a bugfix, no? > True, but we're already at -rc3 and Linus only wants true regression fixes after -rc3. Technically, it's not a regresssion since it's been there all along. ;) (lame excuse, I know) The real reason is that I don't have any other davinci fixes queued, so I'm choosing to be lazy and queue this with the rest of the stuff for .37. Kevin From vm.rod25 at gmail.com Thu Sep 2 12:39:47 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Thu, 2 Sep 2010 12:39:47 -0500 Subject: [PATCH v3] davinci: Initial support for Omapl138-Hawkboard Message-ID: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> This patch adds initial support for the Hawkboard-L138 system It is under the machine name "omapl138_hawkboard". This system is based on the da850 davinci CPU architecture. Information on these system may be found at http://www.hawkboard.org. Basic support for the console UART is included in this patch. Depends on Michael Williamson patches: http://alturl.com/hha7u and http://alturl.com/qy4cr Signed-off-by: Victor Rodriguez Changes since v2: 1) Correct number of characters per line in patch description. 2) Correct board description in Kconfig file 3) Correct da8xx_omapl_defconfig 4) Correct issue with CONFIG_SERIAL_8250_CONSOLE based on Michael Williamson patch http://alturl.com/hha7u 5) Correct issue with voltage regulator control based on Michael Williamson patch http://alturl.com/qy4cr --- Notes: This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 from Kernel development tree for TI DaVinci family of processors. This patch works with da8xx_omapl_defconfig plus this patch. Depens on patches http://alturl.com/hha7u and http://alturl.com/qy4cr This patch just works with UART 2 for Argo file system arch/arm/configs/da8xx_omapl_defconfig | 1 + arch/arm/mach-davinci/Kconfig | 8 +++ arch/arm/mach-davinci/Makefile | 1 + arch/arm/mach-davinci/board-da850-hawk.c | 65 +++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/uncompress.h | 1 + 5 files changed, 76 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/board-da850-hawk.c diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig index 3952a4e..d7cb4b8 100644 --- a/arch/arm/configs/da8xx_omapl_defconfig +++ b/arch/arm/configs/da8xx_omapl_defconfig @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y CONFIG_ARCH_DAVINCI=y CONFIG_ARCH_DAVINCI_DA830=y CONFIG_ARCH_DAVINCI_DA850=y +CONFIG_MACH_OMAPL138_HAWKBOARD=y CONFIG_DAVINCI_RESET_CLOCKS=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 2bf03e9..d1dce71 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -185,6 +185,14 @@ config MACH_TNETV107X help Say Y here to select the TI TNETV107X Evaluation Module. +config MACH_OMAPL138_HAWKBOARD + bool "TI DA850/OMAP-L138/AM18xx" + depends on ARCH_DAVINCI_DA850 + help + Say Y here to select the TI DA850/OMAP-L138/AM18xx. + Information of this board may be found at + http://www.hawkboard.org/ + config DAVINCI_MUX bool "DAVINCI multiplexing support" depends on ARCH_DAVINCI diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 77a0f71..484071d 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-da850-hawk.o # Power Management obj-$(CONFIG_CPU_FREQ) += cpufreq.o diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c new file mode 100644 index 0000000..eb23f7a --- /dev/null +++ b/arch/arm/mach-davinci/board-da850-hawk.c @@ -0,0 +1,65 @@ +/* + * Hawkboard.org based on TI's OMAP-L138 Platform + * + * Initial code: Syed Mohammed Khasim + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 +#include +#include +#include + +#include +#include + +#include +#include + +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { + .enabled_uarts = 0x7, +}; + +static __init void omapl138_hawk_init(void) +{ + + davinci_serial_init(&omapl138_hawk_uart_config); + + /* + * shut down uart 0 and 1; they are not used on the board and + * accessing them causes endless "too much work in irq53" messages + * with arago fs + */ + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); + +} + +#ifdef CONFIG_SERIAL_8250_CONSOLE +static int __init omapl138_hawk_console_init(void) +{ + if (!machine_is_omapl138_hawkboard()) + return 0; + return add_preferred_console("ttyS", 1, "115200"); +} +console_initcall(omapl138_hawk_console_init); +#endif + +static void __init omapl138_hawk_map_io(void) +{ + da850_init(); +} + +MACHINE_START(OMAPL138_HAWKBOARD, "OMAP-L138") + .phys_io = IO_PHYS, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, + .boot_params = (DA8XX_DDR_BASE + 0x100), + .map_io = omapl138_hawk_map_io, + .init_irq = cp_intc_init, + .timer = &davinci_timer, + .init_machine = omapl138_hawk_init, +MACHINE_END diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h index 15a6192..640f834 100644 --- a/arch/arm/mach-davinci/include/mach/uncompress.h +++ b/arch/arm/mach-davinci/include/mach/uncompress.h @@ -88,6 +88,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) /* DA8xx boards */ DEBUG_LL_DA8XX(davinci_da830_evm, 2); DEBUG_LL_DA8XX(davinci_da850_evm, 2); + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); /* TNETV107x boards */ DEBUG_LL_TNETV107X(tnetv107x, 1); -- 1.6.0.5 From michael.williamson at criticallink.com Thu Sep 2 12:58:07 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Thu, 2 Sep 2010 13:58:07 -0400 Subject: [PATCH v3] davinci: Initial support for MityDSP-L138/MityARM-1808 Message-ID: <1283450287-9881-1-git-send-email-michael.williamson@criticallink.com> This patch adds initial support for the MityDSP-L138 and MityDSP-1808 system on Module (SOM) under the machine name "mityomapl138". These SOMs are based on the da850 davinci CPU architecture. Information on these SOMs may be found at http://www.mitydsp.com. Basic support for the console UART, NAND, and EMAC (MII interface) is included in this patch. Signed-off-by: Michael Williamson --- Changes since v2: 1) Remove defaulting this board from Kconfig. 2) Add MITYOMAPL138 board to da8xx_omapl_defconfig. 3) Fix tabs alignment per comment. The new defconfig file was generated by: make da8xx_omapl_defconfig make menuconfig select MITYOMAPL138 option make savedefconfig cp defconfig arch/arm/configs/da8xx_omapl_defconfig I think the other 3 lines were a result of updated KConfig options in the current baseline. arch/arm/configs/da8xx_omapl_defconfig | 4 +- arch/arm/mach-davinci/Kconfig | 8 + arch/arm/mach-davinci/Makefile | 1 + arch/arm/mach-davinci/board-mityomapl138.c | 220 +++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/uncompress.h | 1 + 5 files changed, 232 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig index 3952a4e..38e58e8 100644 --- a/arch/arm/configs/da8xx_omapl_defconfig +++ b/arch/arm/configs/da8xx_omapl_defconfig @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y CONFIG_ARCH_DAVINCI=y CONFIG_ARCH_DAVINCI_DA830=y CONFIG_ARCH_DAVINCI_DA850=y +CONFIG_MACH_MITYOMAPL138=y CONFIG_DAVINCI_RESET_CLOCKS=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -73,6 +74,7 @@ CONFIG_SERIO_LIBPS2=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=3 +CONFIG_SERIAL_8250_RUNTIME_UARTS=3 CONFIG_I2C=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_DAVINCI=y @@ -83,7 +85,6 @@ CONFIG_REGULATOR_DUMMY=y CONFIG_REGULATOR_TPS6507X=y CONFIG_FB=y CONFIG_FB_DA8XX=y -# CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y CONFIG_SOUND=m @@ -95,7 +96,6 @@ CONFIG_SND_DAVINCI_SOC=m CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y CONFIG_XFS_FS=m -CONFIG_INOTIFY=y CONFIG_AUTOFS4_FS=m CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 2bf03e9..9aca60c 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -185,6 +185,14 @@ config MACH_TNETV107X help Say Y here to select the TI TNETV107X Evaluation Module. +config MACH_MITYOMAPL138 + bool "Critical Link MityDSP-L138/MityARM-1808 SoM" + depends on ARCH_DAVINCI_DA850 + help + Say Y here to select the Critical Link MityDSP-L138/MityARM-1808 + System on Module. Information on this SoM may be found at + http://www.mitydsp.com + config DAVINCI_MUX bool "DAVINCI multiplexing support" depends on ARCH_DAVINCI diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index eab4c0f..3e966e8 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o +obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o # Power Management obj-$(CONFIG_CPU_FREQ) += cpufreq.o diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c new file mode 100644 index 0000000..78c972b --- /dev/null +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -0,0 +1,220 @@ +/* + * Critical Link MityOMAP-L138 SoM + * + * Copyright (C) 2010 Critical Link LLC - http://www.criticallink.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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define MITYOMAPL138_PHY_MASK 0x08 /* hardcoded for now */ +#define MITYOMAPL138_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ + +/* + * MityDSP-L138 includes a 256 MByte large-page NAND flash + * (128K blocks). + */ +struct mtd_partition mityomapl138_nandflash_partition[] = { + { + .name = "rootfs", + .offset = 0, + .size = SZ_128M, + .mask_flags = 0, /* MTD_WRITEABLE, */ + }, + { + .name = "homefs", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .mask_flags = 0, + }, +}; + +static struct davinci_nand_pdata mityomapl138_nandflash_data = { + .parts = mityomapl138_nandflash_partition, + .nr_parts = ARRAY_SIZE(mityomapl138_nandflash_partition), + .ecc_mode = NAND_ECC_HW, + .options = NAND_USE_FLASH_BBT | NAND_BUSWIDTH_16, + .ecc_bits = 1, /* 4 bit mode is not supported with 16 bit NAND */ +}; + +static struct resource mityomapl138_nandflash_resource[] = { + { + .start = DA8XX_AEMIF_CS3_BASE, + .end = DA8XX_AEMIF_CS3_BASE + SZ_512K + 2 * SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = DA8XX_AEMIF_CTL_BASE, + .end = DA8XX_AEMIF_CTL_BASE + SZ_32K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device mityomapl138_nandflash_device = { + .name = "davinci_nand", + .id = 0, + .dev = { + .platform_data = &mityomapl138_nandflash_data, + }, + .num_resources = ARRAY_SIZE(mityomapl138_nandflash_resource), + .resource = mityomapl138_nandflash_resource, +}; + +static struct platform_device *mityomapl138_devices[] __initdata = { + &mityomapl138_nandflash_device, +}; + +static void __init mityomapl138_setup_nand(void) +{ + platform_add_devices(mityomapl138_devices, + ARRAY_SIZE(mityomapl138_devices)); +} + +static struct davinci_uart_config mityomapl138_uart_config __initdata = { + .enabled_uarts = 0x7, +}; + +static const short mityomap_mii_pins[] = { + DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3, + DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER, + DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3, + DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK, + DA850_MDIO_D, + -1 +}; + +static const short mityomap_rmii_pins[] = { + DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN, + DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, + DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK, + DA850_MDIO_D, + -1 +}; + +static void __init mityomapl138_config_emac(void) +{ + void __iomem *cfg_chip3_base; + int ret; + u32 val; + struct davinci_soc_info *soc_info = &davinci_soc_info; + soc_info->emac_pdata->rmii_en = 0; /* hardcoded for now */ + + cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG); + val = __raw_readl(cfg_chip3_base); + + if (soc_info->emac_pdata->rmii_en) { + val |= BIT(8); + ret = davinci_cfg_reg_list(mityomap_rmii_pins); + pr_info("RMII PHY configured\n"); + } else { + val &= ~BIT(8); + ret = davinci_cfg_reg_list(mityomap_mii_pins); + pr_info("MII PHY configured\n"); + } + + if (ret) { + pr_warning("mii/rmii mux setup failed: %d\n", ret); + return; + } + + /* configure the CFGCHIP3 register for RMII or MII */ + __raw_writel(val, cfg_chip3_base); + + soc_info->emac_pdata->phy_mask = MITYOMAPL138_PHY_MASK; + pr_debug("setting phy_mask to %x\n", soc_info->emac_pdata->phy_mask); + soc_info->emac_pdata->mdio_max_freq = MITYOMAPL138_MDIO_FREQUENCY; + + ret = da8xx_register_emac(); + if (ret) + pr_warning("emac registration failed: %d\n", ret); +} + +static struct davinci_pm_config da850_pm_pdata = { + .sleepcount = 128, +}; + +static struct platform_device da850_pm_device = { + .name = "pm-davinci", + .dev = { + .platform_data = &da850_pm_pdata, + }, + .id = -1, +}; + +static void __init mityomapl138_init(void) +{ + int ret; + + /* for now, no special EDMA channels are reserved */ + ret = da850_register_edma(NULL); + if (ret) + pr_warning("edma registration failed: %d\n", ret); + + ret = da8xx_register_watchdog(); + if (ret) + pr_warning("watchdog registration failed: %d\n", ret); + + davinci_serial_init(&mityomapl138_uart_config); + + mityomapl138_setup_nand(); + + mityomapl138_config_emac(); + + ret = da8xx_register_rtc(); + if (ret) + pr_warning("rtc setup failed: %d\n", ret); + + ret = da850_register_cpufreq("pll0_sysclk3"); + if (ret) + pr_warning("cpufreq registration failed: %d\n", ret); + + ret = da8xx_register_cpuidle(); + if (ret) + pr_warning("cpuidle registration failed: %d\n", ret); + + ret = da850_register_pm(&da850_pm_device); + if (ret) + pr_warning("da850_evm_init: suspend registration failed: %d\n", + ret); +} + +#ifdef CONFIG_SERIAL_8250_CONSOLE +static int __init mityomapl138_console_init(void) +{ + if (!machine_is_mityomapl138()) + return 0; + + return add_preferred_console("ttyS", 1, "115200"); +} +console_initcall(mityomapl138_console_init); +#endif + +static void __init mityomapl138_map_io(void) +{ + da850_init(); +} + +MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808") + .phys_io = IO_PHYS, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, + .boot_params = (DA8XX_DDR_BASE + 0x100), + .map_io = mityomapl138_map_io, + .init_irq = cp_intc_init, + .timer = &davinci_timer, + .init_machine = mityomapl138_init, +MACHINE_END diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h index 15a6192..d370391 100644 --- a/arch/arm/mach-davinci/include/mach/uncompress.h +++ b/arch/arm/mach-davinci/include/mach/uncompress.h @@ -88,6 +88,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) /* DA8xx boards */ DEBUG_LL_DA8XX(davinci_da830_evm, 2); DEBUG_LL_DA8XX(davinci_da850_evm, 2); + DEBUG_LL_DA8XX(mityomapl138, 1); /* TNETV107x boards */ DEBUG_LL_TNETV107X(tnetv107x, 1); From khilman at deeprootsystems.com Thu Sep 2 13:00:12 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 02 Sep 2010 11:00:12 -0700 Subject: [PATCH v3] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> (Victor Rodriguez's message of "Thu, 2 Sep 2010 12:39:47 -0500") References: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> Message-ID: <87fwxs6n6b.fsf@deeprootsystems.com> Victor Rodriguez writes: > This patch adds initial support for the Hawkboard-L138 system > It is under the machine name "omapl138_hawkboard". > This system is based on the da850 davinci CPU architecture. > Information on these system may be found at http://www.hawkboard.org. > Basic support for the console UART is included in this patch. > Depends on Michael Williamson patches: > http://alturl.com/hha7u and http://alturl.com/qy4cr > > Signed-off-by: Victor Rodriguez > > Changes since v2: > 1) Correct number of characters per line in patch description. > 2) Correct board description in Kconfig file > 3) Correct da8xx_omapl_defconfig > 4) Correct issue with CONFIG_SERIAL_8250_CONSOLE > based on Michael Williamson patch http://alturl.com/hha7u > 5) Correct issue with voltage regulator control > based on Michael Williamson patch http://alturl.com/qy4cr [...] > +static __init void omapl138_hawk_init(void) > +{ > + > + davinci_serial_init(&omapl138_hawk_uart_config); > + > + /* > + * shut down uart 0 and 1; they are not used on the board and > + * accessing them causes endless "too much work in irq53" messages > + * with arago fs > + */ > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); I still dont' want to merge this until this issue is understood and described in the changelog (or the code removed.) Kevin From sshtylyov at mvista.com Thu Sep 2 13:00:35 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Thu, 02 Sep 2010 22:00:35 +0400 Subject: [PATCH v3] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> References: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> Message-ID: <4C7FE643.4020804@mvista.com> Hello. Victor Rodriguez wrote: > This patch adds initial support for the Hawkboard-L138 system > It is under the machine name "omapl138_hawkboard". > This system is based on the da850 davinci CPU architecture. > Information on these system may be found at http://www.hawkboard.org. > Basic support for the console UART is included in this patch. > Depends on Michael Williamson patches: > http://alturl.com/hha7u and http://alturl.com/qy4cr > Signed-off-by: Victor Rodriguez > Changes since v2: > 1) Correct number of characters per line in patch description. > 2) Correct board description in Kconfig file > 3) Correct da8xx_omapl_defconfig > 4) Correct issue with CONFIG_SERIAL_8250_CONSOLE > based on Michael Williamson patch http://alturl.com/hha7u > 5) Correct issue with voltage regulator control > based on Michael Williamson patch http://alturl.com/qy4cr The patch changes belong after --- tear line again. [...] > diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig > index 2bf03e9..d1dce71 100644 > --- a/arch/arm/mach-davinci/Kconfig > +++ b/arch/arm/mach-davinci/Kconfig > @@ -185,6 +185,14 @@ config MACH_TNETV107X > help > Say Y here to select the TI TNETV107X Evaluation Module. > > +config MACH_OMAPL138_HAWKBOARD > + bool "TI DA850/OMAP-L138/AM18xx" Why you stopped calling it Hawkboard? Thios way the option looks like it selects a CPU type... > + depends on ARCH_DAVINCI_DA850 > + help > + Say Y here to select the TI DA850/OMAP-L138/AM18xx. Same comment here... > + Information of this board may be found at > + http://www.hawkboard.org/ > + > config DAVINCI_MUX > bool "DAVINCI multiplexing support" > depends on ARCH_DAVINCI [...] > diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c > new file mode 100644 > index 0000000..eb23f7a > --- /dev/null > +++ b/arch/arm/mach-davinci/board-da850-hawk.c > @@ -0,0 +1,65 @@ > +/* > + * Hawkboard.org based on TI's OMAP-L138 Platform > + * > + * Initial code: Syed Mohammed Khasim > + * > + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 > +#include > +#include > +#include > + > +#include > +#include > + > +#include > +#include > + > +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { > + .enabled_uarts = 0x7, > +}; > + > +static __init void omapl138_hawk_init(void) > +{ > + > + davinci_serial_init(&omapl138_hawk_uart_config); > + > + /* > + * shut down uart 0 and 1; they are not used on the board and > + * accessing them causes endless "too much work in irq53" messages > + * with arago fs > + */ > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); > + > +} > + > +#ifdef CONFIG_SERIAL_8250_CONSOLE > +static int __init omapl138_hawk_console_init(void) > +{ > + if (!machine_is_omapl138_hawkboard()) > + return 0; An empty line wouldn't hurt here... WBR, Sergei From sshtylyov at mvista.com Thu Sep 2 13:05:39 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Thu, 02 Sep 2010 22:05:39 +0400 Subject: [PATCH v3] davinci: Initial support for MityDSP-L138/MityARM-1808 In-Reply-To: <1283450287-9881-1-git-send-email-michael.williamson@criticallink.com> References: <1283450287-9881-1-git-send-email-michael.williamson@criticallink.com> Message-ID: <4C7FE773.5070005@mvista.com> Hello. Michael Williamson wrote: > This patch adds initial support for the MityDSP-L138 and MityDSP-1808 system > on Module (SOM) under the machine name "mityomapl138". These SOMs are based > on the da850 davinci CPU architecture. Information on these SOMs may be > found at http://www.mitydsp.com. > Basic support for the console UART, NAND, and EMAC (MII interface) is > included in this patch. > Signed-off-by: Michael Williamson [...] > diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c > new file mode 100644 > index 0000000..78c972b > --- /dev/null > +++ b/arch/arm/mach-davinci/board-mityomapl138.c > @@ -0,0 +1,220 @@ [...] > +static const short mityomap_mii_pins[] = { > + DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3, > + DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER, > + DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3, > + DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK, > + DA850_MDIO_D, > + -1 > +}; > + > +static const short mityomap_rmii_pins[] = { > + DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN, > + DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, > + DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK, > + DA850_MDIO_D, > + -1 > +}; > + > +static void __init mityomapl138_config_emac(void) > +{ > + void __iomem *cfg_chip3_base; > + int ret; > + u32 val; > + struct davinci_soc_info *soc_info = &davinci_soc_info; Should be an empty line here... > + soc_info->emac_pdata->rmii_en = 0; /* hardcoded for now */ > + > + cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG); > + val = __raw_readl(cfg_chip3_base); > + > + if (soc_info->emac_pdata->rmii_en) { If it's hard coded to 0, why handle the other case? > + val |= BIT(8); > + ret = davinci_cfg_reg_list(mityomap_rmii_pins); > + pr_info("RMII PHY configured\n"); > + } else { > + val &= ~BIT(8); > + ret = davinci_cfg_reg_list(mityomap_mii_pins); > + pr_info("MII PHY configured\n"); > + } WBR, Sergei From khilman at deeprootsystems.com Thu Sep 2 13:10:16 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 02 Sep 2010 11:10:16 -0700 Subject: [PATCH v3] davinci: Initial support for MityDSP-L138/MityARM-1808 In-Reply-To: <1283450287-9881-1-git-send-email-michael.williamson@criticallink.com> (Michael Williamson's message of "Thu, 2 Sep 2010 13:58:07 -0400") References: <1283450287-9881-1-git-send-email-michael.williamson@criticallink.com> Message-ID: <871v9c6mpj.fsf@deeprootsystems.com> Michael Williamson writes: > This patch adds initial support for the MityDSP-L138 and MityDSP-1808 system > on Module (SOM) under the machine name "mityomapl138". These SOMs are based > on the da850 davinci CPU architecture. Information on these SOMs may be > found at http://www.mitydsp.com. > > Basic support for the console UART, NAND, and EMAC (MII interface) is > included in this patch. > > Signed-off-by: Michael Williamson Thanks, applying and queueing for 2.6.37 (with one minor change below...) > --- > Changes since v2: > 1) Remove defaulting this board from Kconfig. > 2) Add MITYOMAPL138 board to da8xx_omapl_defconfig. > 3) Fix tabs alignment per comment. > > The new defconfig file was generated by: > make da8xx_omapl_defconfig > make menuconfig > select MITYOMAPL138 option > make savedefconfig > cp defconfig arch/arm/configs/da8xx_omapl_defconfig > > I think the other 3 lines were a result of updated KConfig options > in the current baseline. Yes, but to minimize unrelated defconfig diffs upstream, I'm going to remove the 3 unrelated ones when applying this patch. Soon we will hopefully be getting rid of defconfigs all together, but until that is sorted out, we need to minimize diffs against defconfigs, especially ones that are not related to the patch. Kevin From khilman at deeprootsystems.com Thu Sep 2 13:17:26 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 02 Sep 2010 11:17:26 -0700 Subject: [PATCH v3] davinci: Initial support for MityDSP-L138/MityARM-1808 In-Reply-To: <4C7FE773.5070005@mvista.com> (Sergei Shtylyov's message of "Thu, 02 Sep 2010 22:05:39 +0400") References: <1283450287-9881-1-git-send-email-michael.williamson@criticallink.com> <4C7FE773.5070005@mvista.com> Message-ID: <87tym857t5.fsf@deeprootsystems.com> Sergei Shtylyov writes: > Hello. > > Michael Williamson wrote: > >> This patch adds initial support for the MityDSP-L138 and MityDSP-1808 system >> on Module (SOM) under the machine name "mityomapl138". These SOMs are based >> on the da850 davinci CPU architecture. Information on these SOMs may be >> found at http://www.mitydsp.com. > >> Basic support for the console UART, NAND, and EMAC (MII interface) is >> included in this patch. > >> Signed-off-by: Michael Williamson > > [...] > >> diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c >> new file mode 100644 >> index 0000000..78c972b >> --- /dev/null >> +++ b/arch/arm/mach-davinci/board-mityomapl138.c >> @@ -0,0 +1,220 @@ > [...] >> +static const short mityomap_mii_pins[] = { >> + DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3, >> + DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER, >> + DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3, >> + DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK, >> + DA850_MDIO_D, >> + -1 >> +}; >> + >> +static const short mityomap_rmii_pins[] = { >> + DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN, >> + DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, >> + DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK, >> + DA850_MDIO_D, >> + -1 >> +}; >> + >> +static void __init mityomapl138_config_emac(void) >> +{ >> + void __iomem *cfg_chip3_base; >> + int ret; >> + u32 val; >> + struct davinci_soc_info *soc_info = &davinci_soc_info; > > Should be an empty line here... I'll add this before pushing. >> + soc_info->emac_pdata->rmii_en = 0; /* hardcoded for now */ >> + >> + cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG); >> + val = __raw_readl(cfg_chip3_base); >> + >> + if (soc_info->emac_pdata->rmii_en) { > > If it's hard coded to 0, why handle the other case? He's planning to add support for the other options in subsequent patches, so I'm OK with leaving this as is. >> + val |= BIT(8); >> + ret = davinci_cfg_reg_list(mityomap_rmii_pins); >> + pr_info("RMII PHY configured\n"); >> + } else { >> + val &= ~BIT(8); >> + ret = davinci_cfg_reg_list(mityomap_mii_pins); >> + pr_info("MII PHY configured\n"); >> + } > > WBR, Sergei Kevin From michael.williamson at criticallink.com Thu Sep 2 16:57:16 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Thu, 02 Sep 2010 17:57:16 -0400 Subject: [PATCH v3] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <87fwxs6n6b.fsf@deeprootsystems.com> References: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> <87fwxs6n6b.fsf@deeprootsystems.com> Message-ID: <4C801DBC.5050105@criticallink.com> On 09/02/2010 02:00 PM, Kevin Hilman wrote: > Victor Rodriguez writes: > [...] > > [...] > >> +static __init void omapl138_hawk_init(void) >> +{ >> + >> + davinci_serial_init(&omapl138_hawk_uart_config); >> + >> + /* >> + * shut down uart 0 and 1; they are not used on the board and >> + * accessing them causes endless "too much work in irq53" messages >> + * with arago fs >> + */ >> + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >> + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); > > I still dont' want to merge this until this issue is understood and > described in the changelog (or the code removed.) > Looking at the schametic, neither UART0 or UART1 are ever hooked up, so it seems like the "enabled_uarts" fields should just be set to 0x4 (UART2) and these lines that pound the controller removed. I'm fairly certain the "too much work in irq53" issue here has to do with the fact that the pins for the UART0 Rx line and output flow control line, which share pin-mux duties with the MII data lines, are hooked up externally to the LAN8710 chip on the hawkboard. Turns out, the pin-mux controls don't appear to really disconnect inputs from devices having input ports that share a pin via the muxing logic (only outputs are truly "muxed" at the pin level). The LAN interface is probably causing serial interrupts based on receive data or flow control logic firing for UART0, because you're enabling it in the enable_uarts mask and enumerating the device. We actually have seen a similar problem with trying to use UART1 with no HW flow control and and the McASP. The UART1 CTS/RTS lines pin-mux-share lines with the McASP AHCLKX and AHCLKR. The minute you try to enable the McASP, the serial driver gets pounded with flow control interrupts. There's no provision, that I can find in the kernel anyway, that allows for disabling CTS/RTS interrupts in the platform definition. (looking at a patch for this...) -Mike From cyril at ti.com Thu Sep 2 17:03:18 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 2 Sep 2010 18:03:18 -0400 Subject: [PATCH v2 00/10] split out emac cpdma and mdio for reuse Message-ID: <1283465008-18606-1-git-send-email-cyril@ti.com> Davinci's EMAC device has an in-built MDIO controller and a CPDMA engine. These hardware modules are not restricted to EMAC device alone. For example, CPSW3G (3-port gigabit ethernet switch) hardware uses these very same modules internally. This patch series separates out EMAC's MDIO and CPDMA functionality, allowing these individual pieces to be reused across TI hardware. This patch series has been broadly organized as follows: MDIO: - Add new functionality netdev: separate out davinci mdio controller code - Hookup new functionality davinci: add mdio platform devices omap: add mdio platform devices netdev: switch davinci emac to new mdio driver - Cleanup left over cruft davinci: cleanup unused davinci mdio arch code omap: cleanup unused davinci mdio arch code netdev: cleanup unused davinci mdio emac code CPDMA: - Add new functionality netdev: separate out davinci cpdma controller code - Hookup new functionality netdev: switch davinci emac to new cpdma layer - Cleanup left over cruft netdev: cleanup unused davinci emac cpdma code This series has been tested on dm365 and tnetv107x (with additional cpsw patches) hardware. Although am3517 (omap) board support code has been updated as needed, emac does not work on this platform. Changes from v1: 1. Fixed memory leak in cpdma_chan_create() failure case 2. Included new omap patches for am3517, avoids build breakage Cyril Chemparathy (8): netdev: separate out davinci mdio controller code davinci: add mdio platform devices omap: add mdio platform devices net: davinci_emac: switch to new mdio davinci: cleanup unused davinci mdio arch code omap: cleanup unused davinci mdio arch code net: davinci_emac: cleanup unused mdio emac code net: davinci_emac: separate out cpdma code net: davinci_emac: switch to new cpdma layer net: davinci_emac: cleanup unused cpdma code arch/arm/mach-davinci/board-da830-evm.c | 5 - arch/arm/mach-davinci/board-da850-evm.c | 6 - arch/arm/mach-davinci/board-dm365-evm.c | 7 - arch/arm/mach-davinci/board-dm644x-evm.c | 7 - arch/arm/mach-davinci/board-dm646x-evm.c | 8 - arch/arm/mach-davinci/board-neuros-osd2.c | 7 - arch/arm/mach-davinci/board-sffsdr.c | 7 - arch/arm/mach-davinci/devices-da8xx.c | 31 +- arch/arm/mach-davinci/dm365.c | 23 +- arch/arm/mach-davinci/dm644x.c | 23 +- arch/arm/mach-davinci/dm646x.c | 22 +- arch/arm/mach-davinci/include/mach/dm365.h | 2 +- arch/arm/mach-davinci/include/mach/dm644x.h | 2 +- arch/arm/mach-davinci/include/mach/dm646x.h | 2 +- arch/arm/mach-omap2/board-am3517evm.c | 31 +- drivers/net/Kconfig | 21 + drivers/net/Makefile | 2 + drivers/net/davinci_cpdma.c | 837 +++++++++++++++++ drivers/net/davinci_cpdma.h | 105 +++ drivers/net/davinci_emac.c | 1325 ++++----------------------- drivers/net/davinci_mdio.c | 386 ++++++++ include/linux/davinci_emac.h | 8 +- 22 files changed, 1635 insertions(+), 1232 deletions(-) create mode 100644 drivers/net/davinci_cpdma.c create mode 100644 drivers/net/davinci_cpdma.h create mode 100644 drivers/net/davinci_mdio.c From cyril at ti.com Thu Sep 2 17:03:19 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 2 Sep 2010 18:03:19 -0400 Subject: [PATCH v2 01/10] net: davinci_emac: separate out davinci mdio In-Reply-To: <1283465008-18606-1-git-send-email-cyril@ti.com> References: <1283465008-18606-1-git-send-email-cyril@ti.com> Message-ID: <1283465008-18606-2-git-send-email-cyril@ti.com> Davinci's MDIO controller is present on other TI devices, without an accompanying EMAC. For example, on tnetv107x, the same MDIO module is used in conjunction with a 3-port switch hardware. By separating the MDIO controller code into its own platform driver, this patch allows common logic to be reused on such platforms. Signed-off-by: Cyril Chemparathy --- drivers/net/Kconfig | 10 + drivers/net/Makefile | 1 + drivers/net/davinci_mdio.c | 386 ++++++++++++++++++++++++++++++++++++++++++ include/linux/davinci_emac.h | 4 + 4 files changed, 401 insertions(+), 0 deletions(-) create mode 100644 drivers/net/davinci_mdio.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2cc81a5..c5c86e0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -958,6 +958,16 @@ config TI_DAVINCI_EMAC To compile this driver as a module, choose M here: the module will be called davinci_emac_driver. This is recommended. +config TI_DAVINCI_MDIO + tristate "TI DaVinci MDIO Support" + depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + select PHYLIB + help + This driver supports TI's DaVinci MDIO module. + + To compile this driver as a module, choose M here: the module + will be called davinci_mdio. This is recommended. + config DM9000 tristate "DM9000 support" depends on ARM || BLACKFIN || MIPS diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 3e8f150..d38a7ab 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_MDIO) += mdio.o obj-$(CONFIG_PHYLIB) += phy/ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o +obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_E1000E) += e1000e/ diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c new file mode 100644 index 0000000..d34a53a --- /dev/null +++ b/drivers/net/davinci_mdio.c @@ -0,0 +1,386 @@ +/* + * DaVinci MDIO Module driver + * + * Copyright (C) 2010 Texas Instruments. + * + * Shamelessly ripped out of davinci_emac.c, original copyrights follow: + * + * Copyright (C) 2009 Texas Instruments. + * + * --------------------------------------------------------------------------- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * --------------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PHY_REG_MASK 0x1f +#define PHY_ID_MASK 0x1f + +#define DEF_OUT_FREQ 2200000 /* 2.2 MHz */ + +struct davinci_mdio_regs { + u32 version; + u32 control; +#define CONTROL_IDLE BIT(31) +#define CONTROL_ENABLE BIT(30) +#define CONTROL_MAX_DIV (0xff) + + u32 alive; + u32 link; + u32 linkintraw; + u32 linkintmasked; + u32 __reserved_0[2]; + u32 userintraw; + u32 userintmasked; + u32 userintmaskset; + u32 userintmaskclr; + u32 __reserved_1[20]; + + struct { + u32 access; +#define USERACCESS_GO BIT(31) +#define USERACCESS_WRITE BIT(30) +#define USERACCESS_ACK BIT(29) +#define USERACCESS_READ (0) +#define USERACCESS_DATA (0xffff) + + u32 physel; + } user[0]; +}; + +struct mdio_platform_data default_pdata = { + .bus_freq = DEF_OUT_FREQ, +}; + +struct davinci_mdio_data { + struct mdio_platform_data pdata; + struct davinci_mdio_regs __iomem *regs; + spinlock_t lock; + struct clk *clk; + struct device *dev; + struct mii_bus *bus; + bool suspended; +}; + +/* wait until hardware is ready for another user access */ +static inline u32 wait_for_user_access(struct davinci_mdio_data *data) +{ + struct davinci_mdio_regs __iomem *regs = data->regs; + u32 reg; + + while ((reg = __raw_readl(®s->user[0].access)) & USERACCESS_GO) + ; + + return reg; +} + +/* wait until hardware state machine is idle */ +static inline void wait_for_idle(struct davinci_mdio_data *data) +{ + struct davinci_mdio_regs __iomem *regs = data->regs; + + while ((__raw_readl(®s->control) & CONTROL_IDLE) == 0) + ; +} + +static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg) +{ + struct davinci_mdio_data *data = bus->priv; + u32 reg; + + if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) + return -EINVAL; + + spin_lock(&data->lock); + + if (data->suspended) { + spin_unlock(&data->lock); + return -ENODEV; + } + + wait_for_user_access(data); + reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) | + (phy_id << 16)); + __raw_writel(reg, &data->regs->user[0].access); + reg = wait_for_user_access(data); + spin_unlock(&data->lock); + + return (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO; +} + +static int davinci_mdio_write(struct mii_bus *bus, int phy_id, + int phy_reg, u16 phy_data) +{ + struct davinci_mdio_data *data = bus->priv; + u32 reg; + + if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) + return -EINVAL; + + spin_lock(&data->lock); + + if (data->suspended) { + spin_unlock(&data->lock); + return -ENODEV; + } + + wait_for_user_access(data); + reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) | + (phy_id << 16) | (phy_data & USERACCESS_DATA)); + __raw_writel(reg, &data->regs->user[0].access); + wait_for_user_access(data); + spin_unlock(&data->lock); + + return 0; +} + +static int __devinit davinci_mdio_probe(struct platform_device *pdev) +{ + struct mdio_platform_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct davinci_mdio_data *data; + struct resource *res; + u32 mdio_in_freq, mdio_out_freq, div, phy_mask, ver; + struct phy_device *phy; + int ret, addr; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + dev_err(dev, "failed to alloc device data\n"); + return -ENOMEM; + } + + data->pdata = pdata ? (*pdata) : default_pdata; + + data->bus = mdiobus_alloc(); + if (!data->bus) { + dev_err(dev, "failed to alloc mii bus\n"); + ret = -ENOMEM; + goto bail_out; + } + + data->bus->name = dev_name(dev); + data->bus->read = davinci_mdio_read, + data->bus->write = davinci_mdio_write, + data->bus->parent = dev; + data->bus->priv = data; + snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); + + data->clk = clk_get(dev, NULL); + if (IS_ERR(data->clk)) { + data->clk = NULL; + dev_err(dev, "failed to get device clock\n"); + ret = PTR_ERR(data->clk); + goto bail_out; + } + + clk_enable(data->clk); + + dev_set_drvdata(dev, data); + data->dev = dev; + spin_lock_init(&data->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "could not find register map resource\n"); + ret = -ENOENT; + goto bail_out; + } + + res = devm_request_mem_region(dev, res->start, resource_size(res), + dev_name(dev)); + if (!res) { + dev_err(dev, "could not allocate register map resource\n"); + ret = -ENXIO; + goto bail_out; + } + + data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); + if (!data->regs) { + dev_err(dev, "could not map mdio registers\n"); + ret = -ENOMEM; + goto bail_out; + } + + mdio_in_freq = clk_get_rate(data->clk); + div = (mdio_in_freq / data->pdata.bus_freq) - 1; + if (div > CONTROL_MAX_DIV) + div = CONTROL_MAX_DIV; + mdio_out_freq = mdio_in_freq / (div + 1); + + /* set enable and clock divider */ + __raw_writel(div | CONTROL_ENABLE, &data->regs->control); + + /* + * wait for scan logic to settle: + * the scan time consists of (a) a large fixed component, and (b) a + * small component that varies with the mii bus frequency. These + * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x + * silicon. Since the effect of (b) was found to be largely + * negligible, we keep things simple here. + */ + mdelay(1); + + /* dump hardware version info */ + ver = __raw_readl(&data->regs->version); + dev_info(dev, "davinci mdio revision %d.%d\n", + (ver >> 8) & 0xff, ver & 0xff); + + /* get phy mask from the alive register */ + phy_mask = __raw_readl(&data->regs->alive); + if (phy_mask) { + /* restrict mdio bus to live phys only */ + dev_info(dev, "detected phy mask %x\n", ~phy_mask); + phy_mask = ~phy_mask; + } else { + /* desperately scan all phys */ + dev_warn(dev, "failed to detect live phys, scanning all\n"); + phy_mask = 0; + } + data->bus->phy_mask = phy_mask; + + /* register the mii bus */ + ret = mdiobus_register(data->bus); + if (ret) + goto bail_out; + + /* scan and dump the bus */ + for (addr = 0; addr < PHY_MAX_ADDR; addr++) { + phy = data->bus->phy_map[addr]; + if (phy) { + dev_info(dev, "phy[%d]: device %s, driver %s\n", + phy->addr, dev_name(&phy->dev), + phy->drv ? phy->drv->name : "unknown"); + } + } + + return 0; + +bail_out: + if (data->bus) + mdiobus_free(data->bus); + + if (data->clk) { + clk_disable(data->clk); + clk_put(data->clk); + } + + kfree(data); + + return ret; +} + +static int __devexit davinci_mdio_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct davinci_mdio_data *data = dev_get_drvdata(dev); + + if (data->bus) + mdiobus_free(data->bus); + + if (data->clk) { + clk_disable(data->clk); + clk_put(data->clk); + } + + dev_set_drvdata(dev, NULL); + + kfree(data); + + return 0; +} + +static int davinci_mdio_suspend(struct device *dev) +{ + struct davinci_mdio_data *data = dev_get_drvdata(dev); + u32 ctrl; + + spin_lock(&data->lock); + + /* shutdown the scan state machine */ + ctrl = __raw_readl(&data->regs->control); + ctrl &= ~CONTROL_ENABLE; + __raw_writel(ctrl, &data->regs->control); + wait_for_idle(data); + + if (data->clk) + clk_disable(data->clk); + + data->suspended = true; + spin_unlock(&data->lock); + + return 0; +} + +static int davinci_mdio_resume(struct device *dev) +{ + struct davinci_mdio_data *data = dev_get_drvdata(dev); + u32 ctrl; + + spin_lock(&data->lock); + if (data->clk) + clk_enable(data->clk); + + /* restart the scan state machine */ + ctrl = __raw_readl(&data->regs->control); + ctrl |= CONTROL_ENABLE; + __raw_writel(ctrl, &data->regs->control); + + data->suspended = false; + spin_unlock(&data->lock); + + return 0; +} + +static const struct dev_pm_ops davinci_mdio_pm_ops = { + .suspend = davinci_mdio_suspend, + .resume = davinci_mdio_resume, +}; + +static struct platform_driver davinci_mdio_driver = { + .driver = { + .name = "davinci_mdio", + .owner = THIS_MODULE, + .pm = &davinci_mdio_pm_ops, + }, + .probe = davinci_mdio_probe, + .remove = __devexit_p(davinci_mdio_remove), +}; + +static int __init davinci_mdio_init(void) +{ + return platform_driver_register(&davinci_mdio_driver); +} +device_initcall(davinci_mdio_init); + +static void __exit davinci_mdio_exit(void) +{ + platform_driver_unregister(&davinci_mdio_driver); +} +module_exit(davinci_mdio_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("DaVinci MDIO driver"); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index 7c930db..a04fd8c 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -14,6 +14,10 @@ #include #include +struct mdio_platform_data { + unsigned long bus_freq; +}; + struct emac_platform_data { char mac_addr[ETH_ALEN]; u32 ctrl_reg_offset; -- 1.7.0.4 From cyril at ti.com Thu Sep 2 17:03:21 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 2 Sep 2010 18:03:21 -0400 Subject: [PATCH v2 03/10] omap: add mdio platform devices In-Reply-To: <1283465008-18606-1-git-send-email-cyril@ti.com> References: <1283465008-18606-1-git-send-email-cyril@ti.com> Message-ID: <1283465008-18606-4-git-send-email-cyril@ti.com> This patch adds mdio platform devices on SoCs that have the necessary hardware. Clock lookup entries (aliases) have also been added, so that the MDIO and EMAC drivers can independently enable/disable a shared underlying clock. Further, the EMAC MMR region has been split down into separate MDIO and EMAC regions. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-omap2/board-am3517evm.c | 27 ++++++++++++++++++++++++++- 1 files changed, 26 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 4d0f585..5dd1b73 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,27 @@ #define AM35XX_EVM_PHY_MASK (0xF) #define AM35XX_EVM_MDIO_FREQUENCY (1000000) +static struct mdio_platform_data am3517_evm_mdio_pdata = { + .bus_freq = AM35XX_EVM_MDIO_FREQUENCY, +}; + +static struct resource am3517_mdio_resources[] = { + { + .start = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET, + .end = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET + + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device am3517_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(am3517_mdio_resources), + .resource = am3517_mdio_resources, + .dev.platform_data = &am3517_evm_mdio_pdata, +}; + static struct emac_platform_data am3517_evm_emac_pdata = { .phy_mask = AM35XX_EVM_PHY_MASK, .mdio_max_freq = AM35XX_EVM_MDIO_FREQUENCY, @@ -50,7 +72,7 @@ static struct emac_platform_data am3517_evm_emac_pdata = { static struct resource am3517_emac_resources[] = { { .start = AM35XX_IPSS_EMAC_BASE, - .end = AM35XX_IPSS_EMAC_BASE + 0x3FFFF, + .end = AM35XX_IPSS_EMAC_BASE + 0x2FFFF, .flags = IORESOURCE_MEM, }, { @@ -121,6 +143,9 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata) pdata->interrupt_disable = am3517_disable_ethernet_int; am3517_emac_device.dev.platform_data = pdata; platform_device_register(&am3517_emac_device); + platform_device_register(&am3517_mdio_device); + clk_add_alias(NULL, dev_name(&am3517_mdio_device.dev), + NULL, &am3517_emac_device.dev); regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); regval = regval & (~(AM35XX_CPGMACSS_SW_RST)); -- 1.7.0.4 From cyril at ti.com Thu Sep 2 17:03:20 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 2 Sep 2010 18:03:20 -0400 Subject: [PATCH v2 02/10] davinci: add mdio platform devices In-Reply-To: <1283465008-18606-1-git-send-email-cyril@ti.com> References: <1283465008-18606-1-git-send-email-cyril@ti.com> Message-ID: <1283465008-18606-3-git-send-email-cyril@ti.com> This patch adds mdio platform devices on SoCs that have the necessary hardware. Clock lookup entries (aliases) have also been added, so that the MDIO and EMAC drivers can independently enable/disable a shared underlying clock. Further, the EMAC MMR region has been split down into separate MDIO and EMAC regions. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/devices-da8xx.c | 29 +++++++++++++++++++++++++- arch/arm/mach-davinci/dm365.c | 22 +++++++++++++++++++- arch/arm/mach-davinci/dm644x.c | 22 +++++++++++++++++++- arch/arm/mach-davinci/dm646x.c | 21 ++++++++++++++++++- arch/arm/mach-davinci/include/mach/dm365.h | 1 + arch/arm/mach-davinci/include/mach/dm644x.h | 1 + arch/arm/mach-davinci/include/mach/dm646x.h | 1 + 7 files changed, 92 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index caeb7f4..9039221 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -352,7 +352,7 @@ int __init da8xx_register_watchdog(void) static struct resource da8xx_emac_resources[] = { { .start = DA8XX_EMAC_CPPI_PORT_BASE, - .end = DA8XX_EMAC_CPPI_PORT_BASE + 0x5000 - 1, + .end = DA8XX_EMAC_CPPI_PORT_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -396,9 +396,34 @@ static struct platform_device da8xx_emac_device = { .resource = da8xx_emac_resources, }; +static struct resource da8xx_mdio_resources[] = { + { + .start = DA8XX_EMAC_MDIO_BASE, + .end = DA8XX_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device da8xx_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(da8xx_mdio_resources), + .resource = da8xx_mdio_resources, +}; + int __init da8xx_register_emac(void) { - return platform_device_register(&da8xx_emac_device); + int ret; + + ret = platform_device_register(&da8xx_mdio_device); + if (ret < 0) + return ret; + ret = platform_device_register(&da8xx_emac_device); + if (ret < 0) + return ret; + ret = clk_add_alias(NULL, dev_name(&da8xx_mdio_device.dev), + NULL, &da8xx_emac_device.dev); + return ret; } static struct resource da830_mcasp1_resources[] = { diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 7781e35..0add1ca 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -699,7 +699,7 @@ static struct emac_platform_data dm365_emac_pdata = { static struct resource dm365_emac_resources[] = { { .start = DM365_EMAC_BASE, - .end = DM365_EMAC_BASE + 0x47ff, + .end = DM365_EMAC_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -734,6 +734,21 @@ static struct platform_device dm365_emac_device = { .resource = dm365_emac_resources, }; +static struct resource dm365_mdio_resources[] = { + { + .start = DM365_EMAC_MDIO_BASE, + .end = DM365_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device dm365_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(dm365_mdio_resources), + .resource = dm365_mdio_resources, +}; + static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = { [IRQ_VDINT0] = 2, [IRQ_VDINT1] = 6, @@ -1219,7 +1234,12 @@ static int __init dm365_init_devices(void) davinci_cfg_reg(DM365_INT_EDMA_CC); platform_device_register(&dm365_edma_device); + + platform_device_register(&dm365_mdio_device); platform_device_register(&dm365_emac_device); + clk_add_alias(NULL, dev_name(&dm365_mdio_device.dev), + NULL, &dm365_emac_device.dev); + /* Add isif clock alias */ clk_add_alias("master", dm365_isif_dev.name, "vpss_master", NULL); platform_device_register(&dm365_vpss_device); diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 5e5b0a7..7dc71c1 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -330,7 +330,7 @@ static struct emac_platform_data dm644x_emac_pdata = { static struct resource dm644x_emac_resources[] = { { .start = DM644X_EMAC_BASE, - .end = DM644X_EMAC_BASE + 0x47ff, + .end = DM644X_EMAC_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -350,6 +350,21 @@ static struct platform_device dm644x_emac_device = { .resource = dm644x_emac_resources, }; +static struct resource dm644x_mdio_resources[] = { + { + .start = DM644X_EMAC_MDIO_BASE, + .end = DM644X_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device dm644x_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(dm644x_mdio_resources), + .resource = dm644x_mdio_resources, +}; + /* * Device specific mux setup * @@ -776,7 +791,12 @@ static int __init dm644x_init_devices(void) clk_add_alias("master", dm644x_ccdc_dev.name, "vpss_master", NULL); clk_add_alias("slave", dm644x_ccdc_dev.name, "vpss_slave", NULL); platform_device_register(&dm644x_edma_device); + + platform_device_register(&dm644x_mdio_device); platform_device_register(&dm644x_emac_device); + clk_add_alias(NULL, dev_name(&dm644x_mdio_device.dev), + NULL, &dm644x_emac_device.dev); + platform_device_register(&dm644x_vpss_device); platform_device_register(&dm644x_ccdc_dev); platform_device_register(&vpfe_capture_dev); diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 26e8a9c..3d636b2 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -366,7 +366,7 @@ static struct emac_platform_data dm646x_emac_pdata = { static struct resource dm646x_emac_resources[] = { { .start = DM646X_EMAC_BASE, - .end = DM646X_EMAC_BASE + 0x47ff, + .end = DM646X_EMAC_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -401,6 +401,21 @@ static struct platform_device dm646x_emac_device = { .resource = dm646x_emac_resources, }; +static struct resource dm646x_mdio_resources[] = { + { + .start = DM646X_EMAC_MDIO_BASE, + .end = DM646X_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device dm646x_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(dm646x_mdio_resources), + .resource = dm646x_mdio_resources, +}; + /* * Device specific mux setup * @@ -896,7 +911,11 @@ static int __init dm646x_init_devices(void) if (!cpu_is_davinci_dm646x()) return 0; + platform_device_register(&dm646x_mdio_device); platform_device_register(&dm646x_emac_device); + clk_add_alias(NULL, dev_name(&dm646x_mdio_device.dev), + NULL, &dm646x_emac_device.dev); + return 0; } postcore_initcall(dm646x_init_devices); diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h index ea5df3b..dbb5052 100644 --- a/arch/arm/mach-davinci/include/mach/dm365.h +++ b/arch/arm/mach-davinci/include/mach/dm365.h @@ -21,6 +21,7 @@ #include #define DM365_EMAC_BASE (0x01D07000) +#define DM365_EMAC_MDIO_BASE (DM365_EMAC_BASE + 0x4000) #define DM365_EMAC_CNTRL_OFFSET (0x0000) #define DM365_EMAC_CNTRL_MOD_OFFSET (0x3000) #define DM365_EMAC_CNTRL_RAM_OFFSET (0x1000) diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h index 6fca568..5159117 100644 --- a/arch/arm/mach-davinci/include/mach/dm644x.h +++ b/arch/arm/mach-davinci/include/mach/dm644x.h @@ -28,6 +28,7 @@ #include #define DM644X_EMAC_BASE (0x01C80000) +#define DM644X_EMAC_MDIO_BASE (DM644X_EMAC_BASE + 0x4000) #define DM644X_EMAC_CNTRL_OFFSET (0x0000) #define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000) diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h index 0a27ee9..1c4dca9 100644 --- a/arch/arm/mach-davinci/include/mach/dm646x.h +++ b/arch/arm/mach-davinci/include/mach/dm646x.h @@ -19,6 +19,7 @@ #include #define DM646X_EMAC_BASE (0x01C80000) +#define DM646X_EMAC_MDIO_BASE (DM646X_EMAC_BASE + 0x4000) #define DM646X_EMAC_CNTRL_OFFSET (0x0000) #define DM646X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM646X_EMAC_CNTRL_RAM_OFFSET (0x2000) -- 1.7.0.4 From cyril at ti.com Thu Sep 2 17:03:22 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 2 Sep 2010 18:03:22 -0400 Subject: [PATCH v2 04/10] net: davinci_emac: switch to new mdio In-Reply-To: <1283465008-18606-1-git-send-email-cyril@ti.com> References: <1283465008-18606-1-git-send-email-cyril@ti.com> Message-ID: <1283465008-18606-5-git-send-email-cyril@ti.com> This patch switches the emac implementation over to the newly separated MDIO driver. With this, the mdio bus frequency defaults to a safe 2.2MHz. Boards may optionally specify a bus frequency via platform data. The phy identification scheme has been modified to use a phy bus id instead of a mask. This largely serves to eliminate the "phy search" code in emac init. Signed-off-by: Cyril Chemparathy --- drivers/net/Kconfig | 1 + drivers/net/davinci_emac.c | 88 ++++++++++++++--------------------------- include/linux/davinci_emac.h | 1 + 3 files changed, 32 insertions(+), 58 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c5c86e0..911e7f1 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -951,6 +951,7 @@ config NET_NETX config TI_DAVINCI_EMAC tristate "TI DaVinci EMAC Support" depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + select TI_DAVINCI_MDIO select PHYLIB help This driver supports TI's DaVinci Ethernet . diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 7fbd052..6ed779d 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -500,6 +500,7 @@ struct emac_priv { u32 phy_mask; /* mii_bus,phy members */ struct mii_bus *mii_bus; + const char *phy_id; struct phy_device *phydev; spinlock_t lock; /*platform specific members*/ @@ -686,7 +687,7 @@ static int emac_get_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) { struct emac_priv *priv = netdev_priv(ndev); - if (priv->phy_mask) + if (priv->phydev) return phy_ethtool_gset(priv->phydev, ecmd); else return -EOPNOTSUPP; @@ -704,7 +705,7 @@ static int emac_get_settings(struct net_device *ndev, static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) { struct emac_priv *priv = netdev_priv(ndev); - if (priv->phy_mask) + if (priv->phydev) return phy_ethtool_sset(priv->phydev, ecmd); else return -EOPNOTSUPP; @@ -841,7 +842,7 @@ static void emac_update_phystatus(struct emac_priv *priv) mac_control = emac_read(EMAC_MACCONTROL); cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ? DUPLEX_FULL : DUPLEX_HALF; - if (priv->phy_mask) + if (priv->phydev) new_duplex = priv->phydev->duplex; else new_duplex = DUPLEX_FULL; @@ -2485,6 +2486,11 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) return -EOPNOTSUPP; } +static int match_first_device(struct device *dev, void *data) +{ + return 1; +} + /** * emac_dev_open: EMAC device open * @ndev: The DaVinci EMAC network adapter @@ -2499,7 +2505,6 @@ static int emac_dev_open(struct net_device *ndev) { struct device *emac_dev = &ndev->dev; u32 rc, cnt, ch; - int phy_addr; struct resource *res; int q, m; int i = 0; @@ -2560,28 +2565,26 @@ static int emac_dev_open(struct net_device *ndev) emac_set_coalesce(ndev, &coal); } - /* find the first phy */ priv->phydev = NULL; - if (priv->phy_mask) { - emac_mii_reset(priv->mii_bus); - for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { - if (priv->mii_bus->phy_map[phy_addr]) { - priv->phydev = priv->mii_bus->phy_map[phy_addr]; - break; - } - } + /* use the first phy on the bus if pdata did not give us a phy id */ + if (!priv->phy_id) { + struct device *phy; - if (!priv->phydev) { - printk(KERN_ERR "%s: no PHY found\n", ndev->name); - return -1; - } + phy = bus_find_device(&mdio_bus_type, NULL, NULL, + match_first_device); + if (phy) + priv->phy_id = dev_name(phy); + } - priv->phydev = phy_connect(ndev, dev_name(&priv->phydev->dev), - &emac_adjust_link, 0, PHY_INTERFACE_MODE_MII); + if (priv->phy_id) { + priv->phydev = phy_connect(ndev, priv->phy_id, + &emac_adjust_link, 0, + PHY_INTERFACE_MODE_MII); if (IS_ERR(priv->phydev)) { - printk(KERN_ERR "%s: Could not attach to PHY\n", - ndev->name); + dev_err(emac_dev, "could not connect to phy %s\n", + priv->phy_id); + priv->phydev = NULL; return PTR_ERR(priv->phydev); } @@ -2589,12 +2592,13 @@ static int emac_dev_open(struct net_device *ndev) priv->speed = 0; priv->duplex = ~0; - printk(KERN_INFO "%s: attached PHY driver [%s] " - "(mii_bus:phy_addr=%s, id=%x)\n", ndev->name, + dev_info(emac_dev, "attached PHY driver [%s] " + "(mii_bus:phy_addr=%s, id=%x)\n", priv->phydev->drv->name, dev_name(&priv->phydev->dev), priv->phydev->phy_id); - } else{ + } else { /* No PHY , fix the link, speed and duplex settings */ + dev_notice(emac_dev, "no phy, defaulting to 100/full\n"); priv->link = 1; priv->speed = SPEED_100; priv->duplex = DUPLEX_FULL; @@ -2607,7 +2611,7 @@ static int emac_dev_open(struct net_device *ndev) if (netif_msg_drv(priv)) dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name); - if (priv->phy_mask) + if (priv->phydev) phy_start(priv->phydev); return 0; @@ -2794,7 +2798,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) /* MAC addr and PHY mask , RMII enable info from platform_data */ memcpy(priv->mac_addr, pdata->mac_addr, 6); - priv->phy_mask = pdata->phy_mask; + priv->phy_id = pdata->phy_id; priv->rmii_en = pdata->rmii_en; priv->version = pdata->version; priv->int_enable = pdata->interrupt_enable; @@ -2871,32 +2875,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) } - /* MII/Phy intialisation, mdio bus registration */ - emac_mii = mdiobus_alloc(); - if (emac_mii == NULL) { - dev_err(emac_dev, "DaVinci EMAC: Error allocating mii_bus\n"); - rc = -ENOMEM; - goto mdio_alloc_err; - } - - priv->mii_bus = emac_mii; - emac_mii->name = "emac-mii", - emac_mii->read = emac_mii_read, - emac_mii->write = emac_mii_write, - emac_mii->reset = emac_mii_reset, - emac_mii->irq = mii_irqs, - emac_mii->phy_mask = ~(priv->phy_mask); - emac_mii->parent = &pdev->dev; - emac_mii->priv = priv->remap_addr + pdata->mdio_reg_offset; - snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", priv->pdev->id); - mdio_max_freq = pdata->mdio_max_freq; - emac_mii->reset(emac_mii); - - /* Register the MII bus */ - rc = mdiobus_register(emac_mii); - if (rc) - goto mdiobus_quit; - if (netif_msg_probe(priv)) { dev_notice(emac_dev, "DaVinci EMAC Probe found device "\ "(regs: %p, irq: %d)\n", @@ -2904,11 +2882,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) } return 0; -mdiobus_quit: - mdiobus_free(emac_mii); - netdev_reg_err: -mdio_alloc_err: clk_disable(emac_clk); no_irq_res: res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -2938,8 +2912,6 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mdiobus_unregister(priv->mii_bus); - mdiobus_free(priv->mii_bus); release_mem_region(res->start, res->end - res->start + 1); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index a04fd8c..6bcd247 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -28,6 +28,7 @@ struct emac_platform_data { u32 ctrl_ram_size; u32 phy_mask; u32 mdio_max_freq; + const char *phy_id; u8 rmii_en; u8 version; void (*interrupt_enable) (void); -- 1.7.0.4 From cyril at ti.com Thu Sep 2 17:03:23 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 2 Sep 2010 18:03:23 -0400 Subject: [PATCH v2 05/10] davinci: cleanup unused davinci mdio arch code In-Reply-To: <1283465008-18606-1-git-send-email-cyril@ti.com> References: <1283465008-18606-1-git-send-email-cyril@ti.com> Message-ID: <1283465008-18606-6-git-send-email-cyril@ti.com> This patch removes davinci architecture code that has now been rendered useless by the previous patches in the MDIO separation series. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/board-da830-evm.c | 5 ----- arch/arm/mach-davinci/board-da850-evm.c | 6 ------ arch/arm/mach-davinci/board-dm365-evm.c | 7 ------- arch/arm/mach-davinci/board-dm644x-evm.c | 7 ------- arch/arm/mach-davinci/board-dm646x-evm.c | 8 -------- arch/arm/mach-davinci/board-neuros-osd2.c | 7 ------- arch/arm/mach-davinci/board-sffsdr.c | 7 ------- arch/arm/mach-davinci/devices-da8xx.c | 2 -- arch/arm/mach-davinci/dm365.c | 1 - arch/arm/mach-davinci/dm644x.c | 1 - arch/arm/mach-davinci/dm646x.c | 1 - arch/arm/mach-davinci/include/mach/dm365.h | 1 - arch/arm/mach-davinci/include/mach/dm644x.h | 1 - arch/arm/mach-davinci/include/mach/dm646x.h | 1 - 14 files changed, 0 insertions(+), 55 deletions(-) diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index de82739..d91d12d 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -31,9 +31,6 @@ #include #include -#define DA830_EVM_PHY_MASK 0x0 -#define DA830_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ - /* * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4]. */ @@ -558,8 +555,6 @@ static __init void da830_evm_init(void) da830_evm_usb_init(); - soc_info->emac_pdata->phy_mask = DA830_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DA830_EVM_MDIO_FREQUENCY; soc_info->emac_pdata->rmii_en = 1; ret = davinci_cfg_reg_list(da830_cpgmac_pins); diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index c1d45d7..3aa4e6b 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -38,9 +38,6 @@ #include #include -#define DA850_EVM_PHY_MASK 0x1 -#define DA850_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ - #define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8) #define DA850_LCD_BL_PIN GPIO_TO_PIN(2, 15) @@ -678,9 +675,6 @@ static int __init da850_evm_config_emac(void) /* Enable/Disable MII MDIO clock */ gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en); - soc_info->emac_pdata->phy_mask = DA850_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DA850_EVM_MDIO_FREQUENCY; - ret = da8xx_register_emac(); if (ret) pr_warning("da850_evm_init: emac registration failed: %d\n", diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index 60c59dd..f697914 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -54,9 +54,6 @@ static inline int have_tvp7002(void) return 0; } -#define DM365_EVM_PHY_MASK (0x2) -#define DM365_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - /* * A MAX-II CPLD is used for various board control functions. */ @@ -530,16 +527,12 @@ fail: /* externally mux MMC1/ENET/AIC33 to imager */ mux |= BIT(6) | BIT(5) | BIT(3); } else { - struct davinci_soc_info *soc_info = &davinci_soc_info; - /* we can use MMC1 ... */ dm365evm_mmc_configure(); davinci_setup_mmc(1, &dm365evm_mmc_config); /* ... and ENET ... */ dm365evm_emac_configure(); - soc_info->emac_pdata->phy_mask = DM365_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DM365_EVM_MDIO_FREQUENCY; resets &= ~BIT(3); /* ... and AIC33 */ diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 65bb940..c86bf23 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -39,9 +39,6 @@ #include #include -#define DM644X_EVM_PHY_MASK (0x2) -#define DM644X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - #define LXT971_PHY_ID (0x001378e2) #define LXT971_PHY_MASK (0xfffffff0) @@ -672,7 +669,6 @@ static int davinci_phy_fixup(struct phy_device *phydev) static __init void davinci_evm_init(void) { struct clk *aemif_clk; - struct davinci_soc_info *soc_info = &davinci_soc_info; aemif_clk = clk_get(NULL, "aemif"); clk_enable(aemif_clk); @@ -707,9 +703,6 @@ static __init void davinci_evm_init(void) davinci_serial_init(&uart_config); dm644x_init_asp(&dm644x_evm_snd_data); - soc_info->emac_pdata->phy_mask = DM644X_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DM644X_EVM_MDIO_FREQUENCY; - /* Register the fixup for PHY on DaVinci */ phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK, davinci_phy_fixup); diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 5a29955..3f34221 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -729,9 +729,6 @@ static struct davinci_uart_config uart_config __initdata = { .enabled_uarts = (1 << 0), }; -#define DM646X_EVM_PHY_MASK (0x2) -#define DM646X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - /* * The following EDMA channels/slots are not being used by drivers (for * example: Timer, GPIO, UART events etc) on dm646x, hence they are being @@ -767,8 +764,6 @@ static struct edma_rsv_info dm646x_edma_rsv[] = { static __init void evm_init(void) { - struct davinci_soc_info *soc_info = &davinci_soc_info; - evm_init_i2c(); davinci_serial_init(&uart_config); dm646x_init_mcasp0(&dm646x_evm_snd_data[0]); @@ -783,9 +778,6 @@ static __init void evm_init(void) if (HAS_ATA) davinci_init_ide(); - - soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY; } #define DM646X_EVM_REF_FREQ 27000000 diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index 4c30e92..4b32f0a 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -39,9 +39,6 @@ #include #include -#define NEUROS_OSD2_PHY_MASK 0x2 -#define NEUROS_OSD2_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ - #define LXT971_PHY_ID 0x001378e2 #define LXT971_PHY_MASK 0xfffffff0 @@ -218,7 +215,6 @@ static struct davinci_mmc_config davinci_ntosd2_mmc_config = { static __init void davinci_ntosd2_init(void) { struct clk *aemif_clk; - struct davinci_soc_info *soc_info = &davinci_soc_info; int status; aemif_clk = clk_get(NULL, "aemif"); @@ -252,9 +248,6 @@ static __init void davinci_ntosd2_init(void) davinci_serial_init(&uart_config); dm644x_init_asp(&dm644x_ntosd2_snd_data); - soc_info->emac_pdata->phy_mask = NEUROS_OSD2_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = NEUROS_OSD2_MDIO_FREQUENCY; - davinci_setup_usb(1000, 8); /* * Mux the pins to be GPIOs, VLYNQEN is already done at startup. diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 23e664a..b372d7f 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -42,9 +42,6 @@ #include #include -#define SFFSDR_PHY_MASK (0x2) -#define SFFSDR_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - static struct mtd_partition davinci_sffsdr_nandflash_partition[] = { /* U-Boot Environment: Block 0 * UBL: Block 1 @@ -137,14 +134,10 @@ static void __init davinci_sffsdr_map_io(void) static __init void davinci_sffsdr_init(void) { - struct davinci_soc_info *soc_info = &davinci_soc_info; - platform_add_devices(davinci_sffsdr_devices, ARRAY_SIZE(davinci_sffsdr_devices)); sffsdr_init_i2c(); davinci_serial_init(&uart_config); - soc_info->emac_pdata->phy_mask = SFFSDR_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = SFFSDR_MDIO_FREQUENCY; davinci_setup_usb(0, 0); /* We support only peripheral mode. */ /* mux VLYNQ pins */ diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 9039221..9eec630 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -42,7 +42,6 @@ #define DA8XX_EMAC_CTRL_REG_OFFSET 0x3000 #define DA8XX_EMAC_MOD_REG_OFFSET 0x2000 #define DA8XX_EMAC_RAM_OFFSET 0x0000 -#define DA8XX_MDIO_REG_OFFSET 0x4000 #define DA8XX_EMAC_CTRL_RAM_SIZE SZ_8K void __iomem *da8xx_syscfg0_base; @@ -381,7 +380,6 @@ struct emac_platform_data da8xx_emac_pdata = { .ctrl_reg_offset = DA8XX_EMAC_CTRL_REG_OFFSET, .ctrl_mod_reg_offset = DA8XX_EMAC_MOD_REG_OFFSET, .ctrl_ram_offset = DA8XX_EMAC_RAM_OFFSET, - .mdio_reg_offset = DA8XX_MDIO_REG_OFFSET, .ctrl_ram_size = DA8XX_EMAC_CTRL_RAM_SIZE, .version = EMAC_VERSION_2, }; diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 0add1ca..a12065e 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -691,7 +691,6 @@ static struct emac_platform_data dm365_emac_pdata = { .ctrl_reg_offset = DM365_EMAC_CNTRL_OFFSET, .ctrl_mod_reg_offset = DM365_EMAC_CNTRL_MOD_OFFSET, .ctrl_ram_offset = DM365_EMAC_CNTRL_RAM_OFFSET, - .mdio_reg_offset = DM365_EMAC_MDIO_OFFSET, .ctrl_ram_size = DM365_EMAC_CNTRL_RAM_SIZE, .version = EMAC_VERSION_2, }; diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 7dc71c1..5d97072 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -322,7 +322,6 @@ static struct emac_platform_data dm644x_emac_pdata = { .ctrl_reg_offset = DM644X_EMAC_CNTRL_OFFSET, .ctrl_mod_reg_offset = DM644X_EMAC_CNTRL_MOD_OFFSET, .ctrl_ram_offset = DM644X_EMAC_CNTRL_RAM_OFFSET, - .mdio_reg_offset = DM644X_EMAC_MDIO_OFFSET, .ctrl_ram_size = DM644X_EMAC_CNTRL_RAM_SIZE, .version = EMAC_VERSION_1, }; diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 3d636b2..1e0f809 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -358,7 +358,6 @@ static struct emac_platform_data dm646x_emac_pdata = { .ctrl_reg_offset = DM646X_EMAC_CNTRL_OFFSET, .ctrl_mod_reg_offset = DM646X_EMAC_CNTRL_MOD_OFFSET, .ctrl_ram_offset = DM646X_EMAC_CNTRL_RAM_OFFSET, - .mdio_reg_offset = DM646X_EMAC_MDIO_OFFSET, .ctrl_ram_size = DM646X_EMAC_CNTRL_RAM_SIZE, .version = EMAC_VERSION_2, }; diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h index dbb5052..2563bf4 100644 --- a/arch/arm/mach-davinci/include/mach/dm365.h +++ b/arch/arm/mach-davinci/include/mach/dm365.h @@ -25,7 +25,6 @@ #define DM365_EMAC_CNTRL_OFFSET (0x0000) #define DM365_EMAC_CNTRL_MOD_OFFSET (0x3000) #define DM365_EMAC_CNTRL_RAM_OFFSET (0x1000) -#define DM365_EMAC_MDIO_OFFSET (0x4000) #define DM365_EMAC_CNTRL_RAM_SIZE (0x2000) /* Base of key scan register bank */ diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h index 5159117..5a1b26d 100644 --- a/arch/arm/mach-davinci/include/mach/dm644x.h +++ b/arch/arm/mach-davinci/include/mach/dm644x.h @@ -32,7 +32,6 @@ #define DM644X_EMAC_CNTRL_OFFSET (0x0000) #define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000) -#define DM644X_EMAC_MDIO_OFFSET (0x4000) #define DM644X_EMAC_CNTRL_RAM_SIZE (0x2000) #define DM644X_ASYNC_EMIF_CONTROL_BASE 0x01E00000 diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h index 1c4dca9..7a27f3f 100644 --- a/arch/arm/mach-davinci/include/mach/dm646x.h +++ b/arch/arm/mach-davinci/include/mach/dm646x.h @@ -23,7 +23,6 @@ #define DM646X_EMAC_CNTRL_OFFSET (0x0000) #define DM646X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM646X_EMAC_CNTRL_RAM_OFFSET (0x2000) -#define DM646X_EMAC_MDIO_OFFSET (0x4000) #define DM646X_EMAC_CNTRL_RAM_SIZE (0x2000) #define DM646X_ASYNC_EMIF_CONTROL_BASE 0x20008000 -- 1.7.0.4 From cyril at ti.com Thu Sep 2 17:03:25 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 2 Sep 2010 18:03:25 -0400 Subject: [PATCH v2 07/10] net: davinci_emac: cleanup unused mdio emac code In-Reply-To: <1283465008-18606-1-git-send-email-cyril@ti.com> References: <1283465008-18606-1-git-send-email-cyril@ti.com> Message-ID: <1283465008-18606-8-git-send-email-cyril@ti.com> This patch removes code that has been rendered useless by the previous patches in this series. Signed-off-by: Cyril Chemparathy --- drivers/net/davinci_emac.c | 107 ------------------------------------------ include/linux/davinci_emac.h | 3 - 2 files changed, 0 insertions(+), 110 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 6ed779d..036681a 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -113,7 +113,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_FRAME_SIZE (1500 + 14 + 4 + 4) #define EMAC_DEF_TX_CH (0) /* Default 0th channel */ #define EMAC_DEF_RX_CH (0) /* Default 0th channel */ -#define EMAC_DEF_MDIO_TICK_MS (10) /* typically 1 tick=1 ms) */ #define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */ #define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */ #define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */ @@ -303,25 +302,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DM644X_INTMIN_INTVL 0x1 #define EMAC_DM644X_INTMAX_INTVL (EMAC_DM644X_EWINTCNT_MASK) -/* EMAC MDIO related */ -/* Mask & Control defines */ -#define MDIO_CONTROL_CLKDIV (0xFF) -#define MDIO_CONTROL_ENABLE BIT(30) -#define MDIO_USERACCESS_GO BIT(31) -#define MDIO_USERACCESS_WRITE BIT(30) -#define MDIO_USERACCESS_READ (0) -#define MDIO_USERACCESS_REGADR (0x1F << 21) -#define MDIO_USERACCESS_PHYADR (0x1F << 16) -#define MDIO_USERACCESS_DATA (0xFFFF) -#define MDIO_USERPHYSEL_LINKSEL BIT(7) -#define MDIO_VER_MODID (0xFFFF << 16) -#define MDIO_VER_REVMAJ (0xFF << 8) -#define MDIO_VER_REVMIN (0xFF) - -#define MDIO_USERACCESS(inst) (0x80 + (inst * 8)) -#define MDIO_USERPHYSEL(inst) (0x84 + (inst * 8)) -#define MDIO_CONTROL (0x04) - /* EMAC DM646X control module registers */ #define EMAC_DM646X_CMINTCTRL 0x0C #define EMAC_DM646X_CMRXINTEN 0x14 @@ -493,13 +473,6 @@ struct emac_priv { u32 mac_hash2; u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS]; u32 rx_addr_type; - /* periodic timer required for MDIO polling */ - struct timer_list periodic_timer; - u32 periodic_ticks; - u32 timer_active; - u32 phy_mask; - /* mii_bus,phy members */ - struct mii_bus *mii_bus; const char *phy_id; struct phy_device *phydev; spinlock_t lock; @@ -511,7 +484,6 @@ struct emac_priv { /* clock frequency for EMAC */ static struct clk *emac_clk; static unsigned long emac_bus_frequency; -static unsigned long mdio_max_freq; #define emac_virt_to_phys(addr, priv) \ (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \ @@ -549,9 +521,6 @@ static char *emac_rxhost_errcodes[16] = { #define emac_ctrl_read(reg) ioread32((priv->ctrl_base + (reg))) #define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg))) -#define emac_mdio_read(reg) ioread32(bus->priv + (reg)) -#define emac_mdio_write(reg, val) iowrite32(val, (bus->priv + (reg))) - /** * emac_dump_regs: Dump important EMAC registers to debug terminal * @priv: The DaVinci EMAC private adapter structure @@ -657,9 +626,6 @@ static void emac_dump_regs(struct emac_priv *priv) emac_read(EMAC_RXDMAOVERRUNS)); } -/************************************************************************* - * EMAC MDIO/Phy Functionality - *************************************************************************/ /** * emac_get_drvinfo: Get EMAC driver information * @ndev: The DaVinci EMAC network adapter @@ -2349,79 +2315,6 @@ void emac_poll_controller(struct net_device *ndev) } #endif -/* PHY/MII bus related */ - -/* Wait until mdio is ready for next command */ -#define MDIO_WAIT_FOR_USER_ACCESS\ - while ((emac_mdio_read((MDIO_USERACCESS(0))) &\ - MDIO_USERACCESS_GO) != 0) - -static int emac_mii_read(struct mii_bus *bus, int phy_id, int phy_reg) -{ - unsigned int phy_data = 0; - unsigned int phy_control; - - /* Wait until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - phy_control = (MDIO_USERACCESS_GO | - MDIO_USERACCESS_READ | - ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | - ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | - (phy_data & MDIO_USERACCESS_DATA)); - emac_mdio_write(MDIO_USERACCESS(0), phy_control); - - /* Wait until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - return emac_mdio_read(MDIO_USERACCESS(0)) & MDIO_USERACCESS_DATA; - -} - -static int emac_mii_write(struct mii_bus *bus, int phy_id, - int phy_reg, u16 phy_data) -{ - - unsigned int control; - - /* until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - control = (MDIO_USERACCESS_GO | - MDIO_USERACCESS_WRITE | - ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | - ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | - (phy_data & MDIO_USERACCESS_DATA)); - emac_mdio_write(MDIO_USERACCESS(0), control); - - return 0; -} - -static int emac_mii_reset(struct mii_bus *bus) -{ - unsigned int clk_div; - int mdio_bus_freq = emac_bus_frequency; - - if (mdio_max_freq && mdio_bus_freq) - clk_div = ((mdio_bus_freq / mdio_max_freq) - 1); - else - clk_div = 0xFF; - - clk_div &= MDIO_CONTROL_CLKDIV; - - /* Set enable and clock divider in MDIOControl */ - emac_mdio_write(MDIO_CONTROL, (clk_div | MDIO_CONTROL_ENABLE)); - - return 0; - -} - -static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, PHY_POLL }; - -/* emac_driver: EMAC MII bus structure */ - -static struct mii_bus *emac_mii; - static void emac_adjust_link(struct net_device *ndev) { struct emac_priv *priv = netdev_priv(ndev); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index 6bcd247..7508e49 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -24,10 +24,7 @@ struct emac_platform_data { u32 ctrl_mod_reg_offset; u32 ctrl_ram_offset; u32 hw_ram_addr; - u32 mdio_reg_offset; u32 ctrl_ram_size; - u32 phy_mask; - u32 mdio_max_freq; const char *phy_id; u8 rmii_en; u8 version; -- 1.7.0.4 From cyril at ti.com Thu Sep 2 17:03:24 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 2 Sep 2010 18:03:24 -0400 Subject: [PATCH v2 06/10] omap: cleanup unused davinci mdio arch code In-Reply-To: <1283465008-18606-1-git-send-email-cyril@ti.com> References: <1283465008-18606-1-git-send-email-cyril@ti.com> Message-ID: <1283465008-18606-7-git-send-email-cyril@ti.com> This patch removes davinci architecture code that has now been rendered useless by the previous patches in the MDIO separation series. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-omap2/board-am3517evm.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 5dd1b73..5225df6 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -39,7 +39,6 @@ #include "mux.h" -#define AM35XX_EVM_PHY_MASK (0xF) #define AM35XX_EVM_MDIO_FREQUENCY (1000000) static struct mdio_platform_data am3517_evm_mdio_pdata = { @@ -64,8 +63,6 @@ static struct platform_device am3517_mdio_device = { }; static struct emac_platform_data am3517_evm_emac_pdata = { - .phy_mask = AM35XX_EVM_PHY_MASK, - .mdio_max_freq = AM35XX_EVM_MDIO_FREQUENCY, .rmii_en = 1, }; @@ -135,7 +132,6 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata) pdata->ctrl_reg_offset = AM35XX_EMAC_CNTRL_OFFSET; pdata->ctrl_mod_reg_offset = AM35XX_EMAC_CNTRL_MOD_OFFSET; pdata->ctrl_ram_offset = AM35XX_EMAC_CNTRL_RAM_OFFSET; - pdata->mdio_reg_offset = AM35XX_EMAC_MDIO_OFFSET; pdata->ctrl_ram_size = AM35XX_EMAC_CNTRL_RAM_SIZE; pdata->version = EMAC_VERSION_2; pdata->hw_ram_addr = AM35XX_EMAC_HW_RAM_ADDR; -- 1.7.0.4 From cyril at ti.com Thu Sep 2 17:03:27 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 2 Sep 2010 18:03:27 -0400 Subject: [PATCH v2 09/10] net: davinci_emac: switch to new cpdma layer In-Reply-To: <1283465008-18606-1-git-send-email-cyril@ti.com> References: <1283465008-18606-1-git-send-email-cyril@ti.com> Message-ID: <1283465008-18606-10-git-send-email-cyril@ti.com> This patch hooks up the emac driver with the newly separated cpdma driver. Key differences introduced here: - The old buffer list scheme is no longer required - The original code maintained mac address per rx channel, even if only one rx channel was being used. With this change, mac address is maintained device wide. If support for multiple rx channels is added in future, this will need to be reworked a bit. - The new CPDMA code handles short packets better than before. The earlier code was adjusting the length up, without ensuring that the tail end of the padding was cleared - a possible security issue. This has been fixed to use skb_padto(). Signed-off-by: Cyril Chemparathy --- drivers/net/davinci_emac.c | 232 ++++++++++++++++++++++++++++---------------- 1 files changed, 147 insertions(+), 85 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 036681a..4147d32 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -63,6 +63,8 @@ #include #include +#include "davinci_cpdma.h" + static int debug_level; module_param(debug_level, int, 0); MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)"); @@ -113,6 +115,7 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_FRAME_SIZE (1500 + 14 + 4 + 4) #define EMAC_DEF_TX_CH (0) /* Default 0th channel */ #define EMAC_DEF_RX_CH (0) /* Default 0th channel */ +#define EMAC_DEF_RX_NUM_DESC (128) #define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */ #define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */ #define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */ @@ -460,6 +463,9 @@ struct emac_priv { u32 hw_ram_addr; struct emac_txch *txch[EMAC_DEF_MAX_TX_CH]; struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH]; + struct cpdma_ctlr *dma; + struct cpdma_chan *txchan; + struct cpdma_chan *rxchan; u32 link; /* 1=link on, 0=link off */ u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */ u32 duplex; /* Link duplex: 0=Half, 1=Full */ @@ -1151,6 +1157,57 @@ static irqreturn_t emac_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static struct sk_buff *emac_rx_alloc(struct emac_priv *priv) +{ + struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size); + if (WARN_ON(!skb)) + return NULL; + skb->dev = priv->ndev; + skb_reserve(skb, NET_IP_ALIGN); + return skb; +} + +static void emac_rx_handler(void *token, int len, int status) +{ + struct sk_buff *skb = token; + struct net_device *ndev = skb->dev; + struct emac_priv *priv = netdev_priv(ndev); + int ret; + + if (status < 0) { + /* error */ + goto recycle; + } + + skb_put(skb, len); + skb->protocol = eth_type_trans(skb, ndev); + netif_receive_skb(skb); + ndev->stats.rx_bytes += len; + ndev->stats.rx_packets++; + + /* alloc a new packet for receive */ + skb = emac_rx_alloc(priv); + +recycle: + if (skb) { + ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, + skb_tailroom(skb), GFP_KERNEL); + WARN_ON(ret < 0); + } +} + +static void emac_tx_handler(void *token, int len, int status) +{ + struct sk_buff *skb = token; + struct net_device *ndev = skb->dev; + + if (unlikely(netif_queue_stopped(ndev))) + netif_start_queue(ndev); + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += len; + dev_kfree_skb_any(skb); +} + /** EMAC on-chip buffer descriptor memory * * WARNING: Please note that the on chip memory is used for both TX and RX @@ -1532,42 +1589,36 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) { struct device *emac_dev = &ndev->dev; int ret_code; - struct emac_netbufobj tx_buf; /* buffer obj-only single frame support */ - struct emac_netpktobj tx_packet; /* packet object */ struct emac_priv *priv = netdev_priv(ndev); /* If no link, return */ if (unlikely(!priv->link)) { if (netif_msg_tx_err(priv) && net_ratelimit()) dev_err(emac_dev, "DaVinci EMAC: No link to transmit"); - return NETDEV_TX_BUSY; + goto fail_tx; } - /* Build the buffer and packet objects - Since only single fragment is - * supported, need not set length and token in both packet & object. - * Doing so for completeness sake & to show that this needs to be done - * in multifragment case - */ - tx_packet.buf_list = &tx_buf; - tx_packet.num_bufs = 1; /* only single fragment supported */ - tx_packet.pkt_length = skb->len; - tx_packet.pkt_token = (void *)skb; - tx_buf.length = skb->len; - tx_buf.buf_token = (void *)skb; - tx_buf.data_ptr = skb->data; - ret_code = emac_send(priv, &tx_packet, EMAC_DEF_TX_CH); + ret_code = skb_padto(skb, EMAC_DEF_MIN_ETHPKTSIZE); + if (unlikely(ret_code < 0)) { + if (netif_msg_tx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "DaVinci EMAC: packet pad failed"); + goto fail_tx; + } + + ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len, + GFP_KERNEL); if (unlikely(ret_code != 0)) { - if (ret_code == EMAC_ERR_TX_OUT_OF_BD) { - if (netif_msg_tx_err(priv) && net_ratelimit()) - dev_err(emac_dev, "DaVinci EMAC: xmit() fatal"\ - " err. Out of TX BD's"); - netif_stop_queue(priv->ndev); - } - ndev->stats.tx_dropped++; - return NETDEV_TX_BUSY; + if (netif_msg_tx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "DaVinci EMAC: desc submit failed"); + goto fail_tx; } return NETDEV_TX_OK; + +fail_tx: + ndev->stats.tx_dropped++; + netif_stop_queue(ndev); + return NETDEV_TX_BUSY; } /** @@ -1590,11 +1641,8 @@ static void emac_dev_tx_timeout(struct net_device *ndev) ndev->stats.tx_errors++; emac_int_disable(priv); - emac_stop_txch(priv, EMAC_DEF_TX_CH); - emac_cleanup_txch(priv, EMAC_DEF_TX_CH); - emac_init_txch(priv, EMAC_DEF_TX_CH); - emac_write(EMAC_TXHDP(0), 0); - emac_write(EMAC_TXINTMASKSET, BIT(EMAC_DEF_TX_CH)); + cpdma_chan_stop(priv->txchan); + cpdma_chan_start(priv->txchan); emac_int_enable(priv); } @@ -1915,7 +1963,6 @@ static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr) static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) { struct emac_priv *priv = netdev_priv(ndev); - struct emac_rxch *rxch = priv->rxch[EMAC_DEF_RX_CH]; struct device *emac_dev = &priv->ndev->dev; struct sockaddr *sa = addr; @@ -1926,11 +1973,10 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); - /* If the interface is down - rxch is NULL. */ /* MAC address is configured only after the interface is enabled. */ if (netif_running(ndev)) { - memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); - emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); + memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); + emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); } if (netif_msg_drv(priv)) @@ -2139,7 +2185,7 @@ end_emac_rx_bdproc: */ static int emac_hw_enable(struct emac_priv *priv) { - u32 ch, val, mbp_enable, mac_control; + u32 val, mbp_enable, mac_control; /* Soft reset */ emac_write(EMAC_SOFTRESET, 1); @@ -2182,26 +2228,9 @@ static int emac_hw_enable(struct emac_priv *priv) emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL); priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF; - val = emac_read(EMAC_TXCONTROL); - val |= EMAC_TX_CONTROL_TX_ENABLE_VAL; - emac_write(EMAC_TXCONTROL, val); - val = emac_read(EMAC_RXCONTROL); - val |= EMAC_RX_CONTROL_RX_ENABLE_VAL; - emac_write(EMAC_RXCONTROL, val); emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL); - for (ch = 0; ch < EMAC_DEF_MAX_TX_CH; ch++) { - emac_write(EMAC_TXHDP(ch), 0); - emac_write(EMAC_TXINTMASKSET, BIT(ch)); - } - for (ch = 0; ch < EMAC_DEF_MAX_RX_CH; ch++) { - struct emac_rxch *rxch = priv->rxch[ch]; - emac_setmac(priv, ch, rxch->mac_addr); - emac_write(EMAC_RXINTMASKSET, BIT(ch)); - rxch->queue_active = 1; - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(rxch->active_queue_head, priv)); - } + emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); /* Enable MII */ val = emac_read(EMAC_MACCONTROL); @@ -2246,8 +2275,8 @@ static int emac_poll(struct napi_struct *napi, int budget) mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC; if (status & mask) { - num_tx_pkts = emac_tx_bdproc(priv, EMAC_DEF_TX_CH, - EMAC_DEF_TX_MAX_SERVICE); + num_tx_pkts = cpdma_chan_process(priv->txchan, + EMAC_DEF_TX_MAX_SERVICE); } /* TX processing */ mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC; @@ -2256,7 +2285,7 @@ static int emac_poll(struct napi_struct *napi, int budget) mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC; if (status & mask) { - num_rx_pkts = emac_rx_bdproc(priv, EMAC_DEF_RX_CH, budget); + num_rx_pkts = cpdma_chan_process(priv->rxchan, budget); } /* RX processing */ mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT; @@ -2397,9 +2426,9 @@ static int match_first_device(struct device *dev, void *data) static int emac_dev_open(struct net_device *ndev) { struct device *emac_dev = &ndev->dev; - u32 rc, cnt, ch; + u32 cnt; struct resource *res; - int q, m; + int q, m, ret; int i = 0; int k = 0; struct emac_priv *priv = netdev_priv(ndev); @@ -2411,29 +2440,21 @@ static int emac_dev_open(struct net_device *ndev) /* Configuration items */ priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN; - /* Clear basic hardware */ - for (ch = 0; ch < EMAC_MAX_TXRX_CHANNELS; ch++) { - emac_write(EMAC_TXHDP(ch), 0); - emac_write(EMAC_RXHDP(ch), 0); - emac_write(EMAC_RXHDP(ch), 0); - emac_write(EMAC_RXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); - emac_write(EMAC_TXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); - } priv->mac_hash1 = 0; priv->mac_hash2 = 0; emac_write(EMAC_MACHASH1, 0); emac_write(EMAC_MACHASH2, 0); - /* multi ch not supported - open 1 TX, 1RX ch by default */ - rc = emac_init_txch(priv, EMAC_DEF_TX_CH); - if (0 != rc) { - dev_err(emac_dev, "DaVinci EMAC: emac_init_txch() failed"); - return rc; - } - rc = emac_init_rxch(priv, EMAC_DEF_RX_CH, priv->mac_addr); - if (0 != rc) { - dev_err(emac_dev, "DaVinci EMAC: emac_init_rxch() failed"); - return rc; + for (i = 0; i < EMAC_DEF_RX_NUM_DESC; i++) { + struct sk_buff *skb = emac_rx_alloc(priv); + + if (!skb) + break; + + ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, + skb_tailroom(skb), GFP_KERNEL); + if (WARN_ON(ret < 0)) + break; } /* Request IRQ */ @@ -2458,6 +2479,8 @@ static int emac_dev_open(struct net_device *ndev) emac_set_coalesce(ndev, &coal); } + cpdma_ctlr_start(priv->dma); + priv->phydev = NULL; /* use the first phy on the bus if pdata did not give us a phy id */ if (!priv->phy_id) { @@ -2545,10 +2568,7 @@ static int emac_dev_stop(struct net_device *ndev) netif_carrier_off(ndev); emac_int_disable(priv); - emac_stop_txch(priv, EMAC_DEF_TX_CH); - emac_stop_rxch(priv, EMAC_DEF_RX_CH); - emac_cleanup_txch(priv, EMAC_DEF_TX_CH); - emac_cleanup_rxch(priv, EMAC_DEF_RX_CH); + cpdma_ctlr_stop(priv->dma); emac_write(EMAC_SOFTRESET, 1); if (priv->phydev) @@ -2653,9 +2673,10 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) struct resource *res; struct net_device *ndev; struct emac_priv *priv; - unsigned long size; + unsigned long size, hw_ram_addr; struct emac_platform_data *pdata; struct device *emac_dev; + struct cpdma_params dma_params; /* obtain emac clock from kernel */ emac_clk = clk_get(&pdev->dev, NULL); @@ -2731,11 +2752,40 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->ctrl_ram_size = pdata->ctrl_ram_size; priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset; - if (pdata->hw_ram_addr) - priv->hw_ram_addr = pdata->hw_ram_addr; - else - priv->hw_ram_addr = (u32 __force)res->start + - pdata->ctrl_ram_offset; + hw_ram_addr = pdata->hw_ram_addr; + if (!hw_ram_addr) + hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset; + + memset(&dma_params, 0, sizeof(dma_params)); + dma_params.dev = emac_dev; + dma_params.dmaregs = priv->emac_base; + dma_params.rxthresh = priv->emac_base + 0x120; + dma_params.rxfree = priv->emac_base + 0x140; + dma_params.txhdp = priv->emac_base + 0x600; + dma_params.rxhdp = priv->emac_base + 0x620; + dma_params.txcp = priv->emac_base + 0x640; + dma_params.rxcp = priv->emac_base + 0x660; + dma_params.num_chan = EMAC_MAX_TXRX_CHANNELS; + dma_params.min_packet_size = EMAC_DEF_MIN_ETHPKTSIZE; + dma_params.desc_mem_phys = hw_ram_addr; + dma_params.desc_mem_size = pdata->ctrl_ram_size; + dma_params.desc_align = 16; + + priv->dma = cpdma_ctlr_create(&dma_params); + if (!priv->dma) { + dev_err(emac_dev, "DaVinci EMAC: Error initializing DMA\n"); + rc = -ENOMEM; + goto no_dma; + } + + priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH), + emac_tx_handler); + priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH), + emac_rx_handler); + if (WARN_ON(!priv->txchan || !priv->rxchan)) { + rc = -ENOMEM; + goto no_irq_res; + } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { @@ -2778,6 +2828,12 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) netdev_reg_err: clk_disable(emac_clk); no_irq_res: + if (priv->txchan) + cpdma_chan_destroy(priv->txchan); + if (priv->rxchan) + cpdma_chan_destroy(priv->rxchan); + cpdma_ctlr_destroy(priv->dma); +no_dma: res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, res->end - res->start + 1); iounmap(priv->remap_addr); @@ -2806,6 +2862,12 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (priv->txchan) + cpdma_chan_destroy(priv->txchan); + if (priv->rxchan) + cpdma_chan_destroy(priv->rxchan); + cpdma_ctlr_destroy(priv->dma); + release_mem_region(res->start, res->end - res->start + 1); unregister_netdev(ndev); -- 1.7.0.4 From cyril at ti.com Thu Sep 2 17:03:26 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 2 Sep 2010 18:03:26 -0400 Subject: [PATCH v2 08/10] net: davinci_emac: separate out cpdma code In-Reply-To: <1283465008-18606-1-git-send-email-cyril@ti.com> References: <1283465008-18606-1-git-send-email-cyril@ti.com> Message-ID: <1283465008-18606-9-git-send-email-cyril@ti.com> In addition to being embedded into the EMAC controller, the CPDMA hardware block is used in TI's CPSW switch controller. Fortunately, the programming interface to this hardware block remains pretty nicely consistent across these devices. This patch adds a new CPDMA services layer, which can then be reused across EMAC and CPSW drivers. Signed-off-by: Cyril Chemparathy --- drivers/net/Kconfig | 10 + drivers/net/Makefile | 1 + drivers/net/davinci_cpdma.c | 837 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/davinci_cpdma.h | 105 ++++++ 4 files changed, 953 insertions(+), 0 deletions(-) create mode 100644 drivers/net/davinci_cpdma.c create mode 100644 drivers/net/davinci_cpdma.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 911e7f1..775fd87 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -952,6 +952,7 @@ config TI_DAVINCI_EMAC tristate "TI DaVinci EMAC Support" depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) select TI_DAVINCI_MDIO + select TI_DAVINCI_CPDMA select PHYLIB help This driver supports TI's DaVinci Ethernet . @@ -969,6 +970,15 @@ config TI_DAVINCI_MDIO To compile this driver as a module, choose M here: the module will be called davinci_mdio. This is recommended. +config TI_DAVINCI_CPDMA + tristate "TI DaVinci CPDMA Support" + depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + help + This driver supports TI's DaVinci CPDMA dma engine. + + To compile this driver as a module, choose M here: the module + will be called davinci_cpdma. This is recommended. + config DM9000 tristate "DM9000 support" depends on ARM || BLACKFIN || MIPS diff --git a/drivers/net/Makefile b/drivers/net/Makefile index d38a7ab..65da885 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_PHYLIB) += phy/ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o +obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_E1000E) += e1000e/ diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c new file mode 100644 index 0000000..ab7ecd7 --- /dev/null +++ b/drivers/net/davinci_cpdma.c @@ -0,0 +1,837 @@ +/* + * Texas Instruments CPDMA Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "davinci_cpdma.h" + +/* DMA Registers */ +#define CPDMA_TXIDVER 0x00 +#define CPDMA_TXCONTROL 0x04 +#define CPDMA_TXTEARDOWN 0x08 +#define CPDMA_RXIDVER 0x10 +#define CPDMA_RXCONTROL 0x14 +#define CPDMA_SOFTRESET 0x1c +#define CPDMA_RXTEARDOWN 0x18 +#define CPDMA_TXINTSTATRAW 0x80 +#define CPDMA_TXINTSTATMASKED 0x84 +#define CPDMA_TXINTMASKSET 0x88 +#define CPDMA_TXINTMASKCLEAR 0x8c +#define CPDMA_MACINVECTOR 0x90 +#define CPDMA_MACEOIVECTOR 0x94 +#define CPDMA_RXINTSTATRAW 0xa0 +#define CPDMA_RXINTSTATMASKED 0xa4 +#define CPDMA_RXINTMASKSET 0xa8 +#define CPDMA_RXINTMASKCLEAR 0xac +#define CPDMA_DMAINTSTATRAW 0xb0 +#define CPDMA_DMAINTSTATMASKED 0xb4 +#define CPDMA_DMAINTMASKSET 0xb8 +#define CPDMA_DMAINTMASKCLEAR 0xbc +#define CPDMA_DMAINT_HOSTERR BIT(1) + +/* the following exist only if has_ext_regs is set */ +#define CPDMA_DMACONTROL 0x20 +#define CPDMA_DMASTATUS 0x24 +#define CPDMA_RXBUFFOFS 0x28 +#define CPDMA_EM_CONTROL 0x2c + +/* Descriptor mode bits */ +#define CPDMA_DESC_SOP BIT(31) +#define CPDMA_DESC_EOP BIT(30) +#define CPDMA_DESC_OWNER BIT(29) +#define CPDMA_DESC_EOQ BIT(28) +#define CPDMA_DESC_TD_COMPLETE BIT(27) +#define CPDMA_DESC_PASS_CRC BIT(26) + +#define CPDMA_TEARDOWN_VALUE 0xfffffffc + +struct cpdma_desc { + /* hardware fields */ + u32 hw_next; + u32 hw_buffer; + u32 hw_len; + u32 hw_mode; + /* software fields */ + void *sw_token; + u32 sw_buffer; + u32 sw_len; +}; + +struct cpdma_desc_pool { + u32 phys; + void __iomem *iomap; /* ioremap map */ + void *cpumap; /* dma_alloc map */ + int desc_size, mem_size; + int num_desc, used_desc; + unsigned long *bitmap; + struct device *dev; + spinlock_t lock; +}; + +enum cpdma_state { + CPDMA_STATE_IDLE, + CPDMA_STATE_ACTIVE, + CPDMA_STATE_TEARDOWN, +}; + +struct cpdma_ctlr { + enum cpdma_state state; + struct cpdma_params params; + struct device *dev; + struct cpdma_desc_pool *pool; + spinlock_t lock; + struct cpdma_chan *channels[2 * CPDMA_MAX_CHANNELS]; +}; + +struct cpdma_chan { + enum cpdma_state state; + struct cpdma_ctlr *ctlr; + int chan_num; + spinlock_t lock; + struct cpdma_desc __iomem *head, *tail; + int count; + void __iomem *hdp, *cp, *rxfree; + u32 mask; + cpdma_handler_fn handler; + enum dma_data_direction dir; + struct cpdma_chan_stats stats; + /* offsets into dmaregs */ + int int_set, int_clear, td; +}; + +/* The following make access to common cpdma_ctlr params more readable */ +#define dmaregs params.dmaregs +#define num_chan params.num_chan + +/* various accessors */ +#define dma_reg_read(ctlr, ofs) __raw_readl((ctlr)->dmaregs + (ofs)) +#define chan_read(chan, fld) __raw_readl((chan)->fld) +#define desc_read(desc, fld) __raw_readl(&(desc)->fld) +#define dma_reg_write(ctlr, ofs, v) __raw_writel(v, (ctlr)->dmaregs + (ofs)) +#define chan_write(chan, fld, v) __raw_writel(v, (chan)->fld) +#define desc_write(desc, fld, v) __raw_writel((u32)(v), &(desc)->fld) + +/* + * Utility constructs for a cpdma descriptor pool. Some devices (e.g. davinci + * emac) have dedicated on-chip memory for these descriptors. Some other + * devices (e.g. cpsw switches) use plain old memory. Descriptor pools + * abstract out these details + */ +static struct cpdma_desc_pool * +cpdma_desc_pool_create(struct device *dev, u32 phys, int size, int align) +{ + int bitmap_size; + struct cpdma_desc_pool *pool; + + pool = kzalloc(sizeof(*pool), GFP_KERNEL); + if (!pool) + return NULL; + + spin_lock_init(&pool->lock); + + pool->dev = dev; + pool->mem_size = size; + pool->desc_size = ALIGN(sizeof(struct cpdma_desc), align); + pool->num_desc = size / pool->desc_size; + + bitmap_size = (pool->num_desc / BITS_PER_LONG) * sizeof(long); + pool->bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!pool->bitmap) + goto fail; + + if (phys) { + pool->phys = phys; + pool->iomap = ioremap(phys, size); + } else { + pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys, + GFP_KERNEL); + pool->iomap = (void __force __iomem *)pool->cpumap; + } + + if (pool->iomap) + return pool; + +fail: + kfree(pool->bitmap); + kfree(pool); + return NULL; +} + +static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool) +{ + unsigned long flags; + + if (!pool) + return; + + spin_lock_irqsave(&pool->lock, flags); + WARN_ON(pool->used_desc); + kfree(pool->bitmap); + if (pool->cpumap) { + dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap, + pool->phys); + } else { + iounmap(pool->iomap); + } + spin_unlock_irqrestore(&pool->lock, flags); + kfree(pool); +} + +static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool, + struct cpdma_desc __iomem *desc) +{ + if (!desc) + return 0; + return pool->phys + (__force dma_addr_t)desc - + (__force dma_addr_t)pool->iomap; +} + +static inline struct cpdma_desc __iomem * +desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma) +{ + return dma ? pool->iomap + dma - pool->phys : NULL; +} + +static struct cpdma_desc __iomem * +cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc) +{ + unsigned long flags; + int index; + struct cpdma_desc __iomem *desc = NULL; + + spin_lock_irqsave(&pool->lock, flags); + + index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0, + num_desc, 0); + if (index < pool->num_desc) { + bitmap_set(pool->bitmap, index, num_desc); + desc = pool->iomap + pool->desc_size * index; + pool->used_desc++; + } + + spin_unlock_irqrestore(&pool->lock, flags); + return desc; +} + +static void cpdma_desc_free(struct cpdma_desc_pool *pool, + struct cpdma_desc __iomem *desc, int num_desc) +{ + unsigned long flags, index; + + index = ((unsigned long)desc - (unsigned long)pool->iomap) / + pool->desc_size; + spin_lock_irqsave(&pool->lock, flags); + bitmap_clear(pool->bitmap, index, num_desc); + pool->used_desc--; + spin_unlock_irqrestore(&pool->lock, flags); +} + +struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params) +{ + struct cpdma_ctlr *ctlr; + + ctlr = kzalloc(sizeof(*ctlr), GFP_KERNEL); + if (!ctlr) + return NULL; + + ctlr->state = CPDMA_STATE_IDLE; + ctlr->params = *params; + ctlr->dev = params->dev; + spin_lock_init(&ctlr->lock); + + ctlr->pool = cpdma_desc_pool_create(ctlr->dev, + ctlr->params.desc_mem_phys, + ctlr->params.desc_mem_size, + ctlr->params.desc_align); + if (!ctlr->pool) { + kfree(ctlr); + return NULL; + } + + if (WARN_ON(ctlr->num_chan > CPDMA_MAX_CHANNELS)) + ctlr->num_chan = CPDMA_MAX_CHANNELS; + return ctlr; +} + +int cpdma_ctlr_start(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_IDLE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EBUSY; + } + + if (ctlr->params.has_soft_reset) { + unsigned long timeout = jiffies + HZ/10; + + dma_reg_write(ctlr, CPDMA_SOFTRESET, 1); + while (time_before(jiffies, timeout)) { + if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0) + break; + } + WARN_ON(!time_before(jiffies, timeout)); + } + + for (i = 0; i < ctlr->num_chan; i++) { + __raw_writel(0, ctlr->params.txhdp + 4 * i); + __raw_writel(0, ctlr->params.rxhdp + 4 * i); + __raw_writel(0, ctlr->params.txcp + 4 * i); + __raw_writel(0, ctlr->params.rxcp + 4 * i); + } + + dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); + dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); + + dma_reg_write(ctlr, CPDMA_TXCONTROL, 1); + dma_reg_write(ctlr, CPDMA_RXCONTROL, 1); + + ctlr->state = CPDMA_STATE_ACTIVE; + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_start(ctlr->channels[i]); + } + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EINVAL; + } + + ctlr->state = CPDMA_STATE_TEARDOWN; + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_stop(ctlr->channels[i]); + } + + dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); + dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); + + dma_reg_write(ctlr, CPDMA_TXCONTROL, 0); + dma_reg_write(ctlr, CPDMA_RXCONTROL, 0); + + ctlr->state = CPDMA_STATE_IDLE; + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int ret = 0, i; + + if (!ctlr) + return -EINVAL; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_IDLE) + cpdma_ctlr_stop(ctlr); + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_destroy(ctlr->channels[i]); + } + + cpdma_desc_pool_destroy(ctlr->pool); + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(ctlr); + return ret; +} + +int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable) +{ + unsigned long flags; + int i, reg; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EINVAL; + } + + reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR; + dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR); + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_int_ctrl(ctlr->channels[i], enable); + } + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr) +{ + dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0); +} + +struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, + cpdma_handler_fn handler) +{ + struct cpdma_chan *chan; + int ret, offset = (chan_num % CPDMA_MAX_CHANNELS) * 4; + unsigned long flags; + + if (__chan_linear(chan_num) >= ctlr->num_chan) + return NULL; + + ret = -ENOMEM; + chan = kzalloc(sizeof(*chan), GFP_KERNEL); + if (!chan) + goto err_chan_alloc; + + spin_lock_irqsave(&ctlr->lock, flags); + ret = -EBUSY; + if (ctlr->channels[chan_num]) + goto err_chan_busy; + + chan->ctlr = ctlr; + chan->state = CPDMA_STATE_IDLE; + chan->chan_num = chan_num; + chan->handler = handler; + + if (is_rx_chan(chan)) { + chan->hdp = ctlr->params.rxhdp + offset; + chan->cp = ctlr->params.rxcp + offset; + chan->rxfree = ctlr->params.rxfree + offset; + chan->int_set = CPDMA_RXINTMASKSET; + chan->int_clear = CPDMA_RXINTMASKCLEAR; + chan->td = CPDMA_RXTEARDOWN; + chan->dir = DMA_FROM_DEVICE; + } else { + chan->hdp = ctlr->params.txhdp + offset; + chan->cp = ctlr->params.txcp + offset; + chan->int_set = CPDMA_TXINTMASKSET; + chan->int_clear = CPDMA_TXINTMASKCLEAR; + chan->td = CPDMA_TXTEARDOWN; + chan->dir = DMA_TO_DEVICE; + } + chan->mask = BIT(chan_linear(chan)); + + spin_lock_init(&chan->lock); + + ctlr->channels[chan_num] = chan; + spin_unlock_irqrestore(&ctlr->lock, flags); + return chan; + +err_chan_busy: + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(chan); +err_chan_alloc: + return ERR_PTR(ret); +} + +int cpdma_chan_destroy(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + unsigned long flags; + + if (!chan) + return -EINVAL; + + spin_lock_irqsave(&ctlr->lock, flags); + if (chan->state != CPDMA_STATE_IDLE) + cpdma_chan_stop(chan); + ctlr->channels[chan->chan_num] = NULL; + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(chan); + return 0; +} + +int cpdma_chan_get_stats(struct cpdma_chan *chan, + struct cpdma_chan_stats *stats) +{ + unsigned long flags; + if (!chan) + return -EINVAL; + spin_lock_irqsave(&chan->lock, flags); + memcpy(stats, &chan->stats, sizeof(*stats)); + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +static void __cpdma_chan_submit(struct cpdma_chan *chan, + struct cpdma_desc __iomem *desc) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *prev = chan->tail; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t desc_dma; + + desc_dma = desc_phys(pool, desc); + + /* simple case - idle channel */ + if (!chan->head) { + chan->stats.head_enqueue++; + chan->head = desc; + chan->tail = desc; + if (chan->state == CPDMA_STATE_ACTIVE) + chan_write(chan, hdp, desc_dma); + return; + } + + /* first chain the descriptor at the tail of the list */ + desc_write(prev, hw_next, desc_dma); + chan->tail = desc; + chan->stats.tail_enqueue++; + + /* next check if EOQ has been triggered already */ + if (desc_read(prev, hw_mode) & CPDMA_DESC_EOQ && + chan->state == CPDMA_STATE_ACTIVE) { + chan_write(chan, hdp, desc_dma); + chan->stats.misqueued++; + } +} + +int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, + int len, gfp_t gfp_mask) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *desc; + dma_addr_t buffer; + unsigned long flags; + u32 mode; + int ret = 0; + + spin_lock_irqsave(&chan->lock, flags); + + if (chan->state == CPDMA_STATE_TEARDOWN) { + ret = -EINVAL; + goto unlock_ret; + } + + desc = cpdma_desc_alloc(ctlr->pool, 1); + if (!desc) { + chan->stats.desc_alloc_fail++; + ret = -ENOMEM; + goto unlock_ret; + } + + if (len < ctlr->params.min_packet_size) { + len = ctlr->params.min_packet_size; + chan->stats.runt_transmit_buff++; + } + + buffer = dma_map_single(ctlr->dev, data, len, chan->dir); + mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP; + + desc_write(desc, hw_next, 0); + desc_write(desc, hw_buffer, buffer); + desc_write(desc, hw_len, len); + desc_write(desc, hw_mode, mode | len); + desc_write(desc, sw_token, token); + desc_write(desc, sw_buffer, buffer); + desc_write(desc, sw_len, len); + + __cpdma_chan_submit(chan, desc); + + if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree) + chan_write(chan, rxfree, 1); + + chan->count++; + +unlock_ret: + spin_unlock_irqrestore(&chan->lock, flags); + return ret; +} + +static void __cpdma_chan_free(struct cpdma_chan *chan, + struct cpdma_desc __iomem *desc, + int outlen, int status) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t buff_dma; + int origlen; + void *token; + + token = (void *)desc_read(desc, sw_token); + buff_dma = desc_read(desc, sw_buffer); + origlen = desc_read(desc, sw_len); + + dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir); + cpdma_desc_free(pool, desc, 1); + (*chan->handler)(token, outlen, status); +} + +static int __cpdma_chan_process(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *desc; + int status, outlen; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t desc_dma; + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + + desc = chan->head; + if (!desc) { + chan->stats.empty_dequeue++; + status = -ENOENT; + goto unlock_ret; + } + desc_dma = desc_phys(pool, desc); + + status = __raw_readl(&desc->hw_mode); + outlen = status & 0x7ff; + if (status & CPDMA_DESC_OWNER) { + chan->stats.busy_dequeue++; + status = -EBUSY; + goto unlock_ret; + } + status = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE); + + chan->head = desc_from_phys(pool, desc_read(desc, hw_next)); + chan_write(chan, cp, desc_dma); + chan->count--; + chan->stats.good_dequeue++; + + spin_unlock_irqrestore(&chan->lock, flags); + + __cpdma_chan_free(chan, desc, outlen, status); + return status; + +unlock_ret: + spin_unlock_irqrestore(&chan->lock, flags); + return status; +} + +int cpdma_chan_process(struct cpdma_chan *chan, int quota) +{ + int used = 0, ret = 0; + + if (chan->state != CPDMA_STATE_ACTIVE) + return -EINVAL; + + while (used < quota) { + ret = __cpdma_chan_process(chan); + if (ret < 0) + break; + used++; + } + return used; +} + +int cpdma_chan_start(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_IDLE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EBUSY; + } + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + dma_reg_write(ctlr, chan->int_set, chan->mask); + chan->state = CPDMA_STATE_ACTIVE; + if (chan->head) { + chan_write(chan, hdp, desc_phys(pool, chan->head)); + if (chan->rxfree) + chan_write(chan, rxfree, chan->count); + } + + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +int cpdma_chan_stop(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + unsigned long flags; + int ret; + unsigned long timeout; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + + chan->state = CPDMA_STATE_TEARDOWN; + dma_reg_write(ctlr, chan->int_clear, chan->mask); + + /* trigger teardown */ + dma_reg_write(ctlr, chan->td, chan->chan_num); + + /* wait for teardown complete */ + timeout = jiffies + HZ/10; /* 100 msec */ + while (time_before(jiffies, timeout)) { + u32 cp = chan_read(chan, cp); + if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE) + break; + cpu_relax(); + } + WARN_ON(!time_before(jiffies, timeout)); + chan_write(chan, cp, CPDMA_TEARDOWN_VALUE); + + /* handle completed packets */ + do { + ret = __cpdma_chan_process(chan); + if (ret < 0) + break; + } while ((ret & CPDMA_DESC_TD_COMPLETE) == 0); + + /* remaining packets haven't been tx/rx'ed, clean them up */ + while (chan->head) { + struct cpdma_desc __iomem *desc = chan->head; + dma_addr_t next_dma; + + next_dma = desc_read(desc, hw_next); + chan->head = desc_from_phys(pool, next_dma); + chan->stats.teardown_dequeue++; + + /* issue callback without locks held */ + spin_unlock_irqrestore(&chan->lock, flags); + __cpdma_chan_free(chan, desc, 0, -ENOSYS); + spin_lock_irqsave(&chan->lock, flags); + } + + chan->state = CPDMA_STATE_IDLE; + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable) +{ + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + + dma_reg_write(chan->ctlr, enable ? chan->int_set : chan->int_clear, + chan->mask); + spin_unlock_irqrestore(&chan->lock, flags); + + return 0; +} + +struct cpdma_control_info { + u32 reg; + u32 shift, mask; + int access; +#define ACCESS_RO BIT(0) +#define ACCESS_WO BIT(1) +#define ACCESS_RW (ACCESS_RO | ACCESS_WO) +}; + +struct cpdma_control_info controls[] = { + [CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO}, + [CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL, 4, 1, ACCESS_RW}, + [CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL, 2, 1, ACCESS_RW}, + [CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL, 1, 1, ACCESS_RW}, + [CPDMA_TX_PRIO_FIXED] = {CPDMA_DMACONTROL, 0, 1, ACCESS_RW}, + [CPDMA_STAT_IDLE] = {CPDMA_DMASTATUS, 31, 1, ACCESS_RO}, + [CPDMA_STAT_TX_ERR_CODE] = {CPDMA_DMASTATUS, 20, 0xf, ACCESS_RW}, + [CPDMA_STAT_TX_ERR_CHAN] = {CPDMA_DMASTATUS, 16, 0x7, ACCESS_RW}, + [CPDMA_STAT_RX_ERR_CODE] = {CPDMA_DMASTATUS, 12, 0xf, ACCESS_RW}, + [CPDMA_STAT_RX_ERR_CHAN] = {CPDMA_DMASTATUS, 8, 0x7, ACCESS_RW}, + [CPDMA_RX_BUFFER_OFFSET] = {CPDMA_RXBUFFOFS, 0, 0xffff, ACCESS_RW}, +}; + +int cpdma_control_get(struct cpdma_ctlr *ctlr, int control) +{ + unsigned long flags; + struct cpdma_control_info *info = &controls[control]; + int ret; + + spin_lock_irqsave(&ctlr->lock, flags); + + ret = -ENOTSUPP; + if (!ctlr->params.has_ext_regs) + goto unlock_ret; + + ret = -EINVAL; + if (ctlr->state != CPDMA_STATE_ACTIVE) + goto unlock_ret; + + ret = -ENOENT; + if (control < 0 || control >= ARRAY_SIZE(controls)) + goto unlock_ret; + + ret = -EPERM; + if ((info->access & ACCESS_RO) != ACCESS_RO) + goto unlock_ret; + + ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask; + +unlock_ret: + spin_unlock_irqrestore(&ctlr->lock, flags); + return ret; +} + +int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value) +{ + unsigned long flags; + struct cpdma_control_info *info = &controls[control]; + int ret; + u32 val; + + spin_lock_irqsave(&ctlr->lock, flags); + + ret = -ENOTSUPP; + if (!ctlr->params.has_ext_regs) + goto unlock_ret; + + ret = -EINVAL; + if (ctlr->state != CPDMA_STATE_ACTIVE) + goto unlock_ret; + + ret = -ENOENT; + if (control < 0 || control >= ARRAY_SIZE(controls)) + goto unlock_ret; + + ret = -EPERM; + if ((info->access & ACCESS_WO) != ACCESS_WO) + goto unlock_ret; + + val = dma_reg_read(ctlr, info->reg); + val &= ~(info->mask << info->shift); + val |= (value & info->mask) << info->shift; + dma_reg_write(ctlr, info->reg, val); + ret = 0; + +unlock_ret: + spin_unlock_irqrestore(&ctlr->lock, flags); + return ret; +} diff --git a/drivers/net/davinci_cpdma.h b/drivers/net/davinci_cpdma.h new file mode 100644 index 0000000..d50ee35 --- /dev/null +++ b/drivers/net/davinci_cpdma.h @@ -0,0 +1,105 @@ +/* + * Texas Instruments CPDMA Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __DAVINCI_CPDMA_H__ +#define __DAVINCI_CPDMA_H__ + +#define CPDMA_MAX_CHANNELS BITS_PER_LONG + +#define tx_chan_num(chan) (chan) +#define rx_chan_num(chan) ((chan) + CPDMA_MAX_CHANNELS) +#define is_rx_chan(chan) ((chan)->chan_num >= CPDMA_MAX_CHANNELS) +#define is_tx_chan(chan) (!is_rx_chan(chan)) +#define __chan_linear(chan_num) ((chan_num) & (CPDMA_MAX_CHANNELS - 1)) +#define chan_linear(chan) __chan_linear((chan)->chan_num) + +struct cpdma_params { + struct device *dev; + void __iomem *dmaregs; + void __iomem *txhdp, *rxhdp, *txcp, *rxcp; + void __iomem *rxthresh, *rxfree; + int num_chan; + bool has_soft_reset; + int min_packet_size; + u32 desc_mem_phys; + int desc_mem_size; + int desc_align; + + /* + * Some instances of embedded cpdma controllers have extra control and + * status registers. The following flag enables access to these + * "extended" registers. + */ + bool has_ext_regs; +}; + +struct cpdma_chan_stats { + u32 head_enqueue; + u32 tail_enqueue; + u32 pad_enqueue; + u32 misqueued; + u32 desc_alloc_fail; + u32 pad_alloc_fail; + u32 runt_receive_buff; + u32 runt_transmit_buff; + u32 empty_dequeue; + u32 busy_dequeue; + u32 good_dequeue; + u32 teardown_dequeue; +}; + +struct cpdma_ctlr; +struct cpdma_chan; + +typedef void (*cpdma_handler_fn)(void *token, int len, int status); + +struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params); +int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_start(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr); + +struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, + cpdma_handler_fn handler); +int cpdma_chan_destroy(struct cpdma_chan *chan); +int cpdma_chan_start(struct cpdma_chan *chan); +int cpdma_chan_stop(struct cpdma_chan *chan); + +int cpdma_chan_get_stats(struct cpdma_chan *chan, + struct cpdma_chan_stats *stats); +int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, + int len, gfp_t gfp_mask); +int cpdma_chan_process(struct cpdma_chan *chan, int quota); + +int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable); +void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr); +int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable); + +enum cpdma_control { + CPDMA_CMD_IDLE, /* write-only */ + CPDMA_COPY_ERROR_FRAMES, /* read-write */ + CPDMA_RX_OFF_LEN_UPDATE, /* read-write */ + CPDMA_RX_OWNERSHIP_FLIP, /* read-write */ + CPDMA_TX_PRIO_FIXED, /* read-write */ + CPDMA_STAT_IDLE, /* read-only */ + CPDMA_STAT_TX_ERR_CHAN, /* read-only */ + CPDMA_STAT_TX_ERR_CODE, /* read-only */ + CPDMA_STAT_RX_ERR_CHAN, /* read-only */ + CPDMA_STAT_RX_ERR_CODE, /* read-only */ + CPDMA_RX_BUFFER_OFFSET, /* read-write */ +}; + +int cpdma_control_get(struct cpdma_ctlr *ctlr, int control); +int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value); + +#endif -- 1.7.0.4 From cyril at ti.com Thu Sep 2 17:03:28 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 2 Sep 2010 18:03:28 -0400 Subject: [PATCH v2 10/10] net: davinci_emac: cleanup unused cpdma code In-Reply-To: <1283465008-18606-1-git-send-email-cyril@ti.com> References: <1283465008-18606-1-git-send-email-cyril@ti.com> Message-ID: <1283465008-18606-11-git-send-email-cyril@ti.com> Having switched over to the newly introduced cpdma layer, this patch now removes a whole bunch of code that is now unused. This patch has been maintained separate strictly for reasons of readability. Signed-off-by: Cyril Chemparathy --- drivers/net/davinci_emac.c | 930 -------------------------------------------- 1 files changed, 0 insertions(+), 930 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 4147d32..525b84c 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -127,7 +127,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; /* EMAC register related defines */ #define EMAC_ALL_MULTI_REG_VALUE (0xFFFFFFFF) #define EMAC_NUM_MULTICAST_BITS (64) -#define EMAC_TEARDOWN_VALUE (0xFFFFFFFC) #define EMAC_TX_CONTROL_TX_ENABLE_VAL (0x1) #define EMAC_RX_CONTROL_RX_ENABLE_VAL (0x1) #define EMAC_MAC_HOST_ERR_INTMASK_VAL (0x2) @@ -214,24 +213,10 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */ /* EMAC Peripheral Device Register Memory Layout structure */ -#define EMAC_TXIDVER 0x0 -#define EMAC_TXCONTROL 0x4 -#define EMAC_TXTEARDOWN 0x8 -#define EMAC_RXIDVER 0x10 -#define EMAC_RXCONTROL 0x14 -#define EMAC_RXTEARDOWN 0x18 -#define EMAC_TXINTSTATRAW 0x80 -#define EMAC_TXINTSTATMASKED 0x84 -#define EMAC_TXINTMASKSET 0x88 -#define EMAC_TXINTMASKCLEAR 0x8C #define EMAC_MACINVECTOR 0x90 #define EMAC_DM646X_MACEOIVECTOR 0x94 -#define EMAC_RXINTSTATRAW 0xA0 -#define EMAC_RXINTSTATMASKED 0xA4 -#define EMAC_RXINTMASKSET 0xA8 -#define EMAC_RXINTMASKCLEAR 0xAC #define EMAC_MACINTSTATRAW 0xB0 #define EMAC_MACINTSTATMASKED 0xB4 #define EMAC_MACINTMASKSET 0xB8 @@ -258,12 +243,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_MACADDRHI 0x504 #define EMAC_MACINDEX 0x508 -/* EMAC HDP and Completion registors */ -#define EMAC_TXHDP(ch) (0x600 + (ch * 4)) -#define EMAC_RXHDP(ch) (0x620 + (ch * 4)) -#define EMAC_TXCP(ch) (0x640 + (ch * 4)) -#define EMAC_RXCP(ch) (0x660 + (ch * 4)) - /* EMAC statistics registers */ #define EMAC_RXGOODFRAMES 0x200 #define EMAC_RXBCASTFRAMES 0x204 @@ -328,120 +307,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; /* EMAC Stats Clear Mask */ #define EMAC_STATS_CLR_MASK (0xFFFFFFFF) -/** net_buf_obj: EMAC network bufferdata structure - * - * EMAC network buffer data structure - */ -struct emac_netbufobj { - void *buf_token; - char *data_ptr; - int length; -}; - -/** net_pkt_obj: EMAC network packet data structure - * - * EMAC network packet data structure - supports buffer list (for future) - */ -struct emac_netpktobj { - void *pkt_token; /* data token may hold tx/rx chan id */ - struct emac_netbufobj *buf_list; /* array of network buffer objects */ - int num_bufs; - int pkt_length; -}; - -/** emac_tx_bd: EMAC TX Buffer descriptor data structure - * - * EMAC TX Buffer descriptor data structure - */ -struct emac_tx_bd { - int h_next; - int buff_ptr; - int off_b_len; - int mode; /* SOP, EOP, ownership, EOQ, teardown,Qstarv, length */ - struct emac_tx_bd __iomem *next; - void *buf_token; -}; - -/** emac_txch: EMAC TX Channel data structure - * - * EMAC TX Channel data structure - */ -struct emac_txch { - /* Config related */ - u32 num_bd; - u32 service_max; - - /* CPPI specific */ - u32 alloc_size; - void __iomem *bd_mem; - struct emac_tx_bd __iomem *bd_pool_head; - struct emac_tx_bd __iomem *active_queue_head; - struct emac_tx_bd __iomem *active_queue_tail; - struct emac_tx_bd __iomem *last_hw_bdprocessed; - u32 queue_active; - u32 teardown_pending; - u32 *tx_complete; - - /** statistics */ - u32 proc_count; /* TX: # of times emac_tx_bdproc is called */ - u32 mis_queued_packets; - u32 queue_reinit; - u32 end_of_queue_add; - u32 out_of_tx_bd; - u32 no_active_pkts; /* IRQ when there were no packets to process */ - u32 active_queue_count; -}; - -/** emac_rx_bd: EMAC RX Buffer descriptor data structure - * - * EMAC RX Buffer descriptor data structure - */ -struct emac_rx_bd { - int h_next; - int buff_ptr; - int off_b_len; - int mode; - struct emac_rx_bd __iomem *next; - void *data_ptr; - void *buf_token; -}; - -/** emac_rxch: EMAC RX Channel data structure - * - * EMAC RX Channel data structure - */ -struct emac_rxch { - /* configuration info */ - u32 num_bd; - u32 service_max; - u32 buf_size; - char mac_addr[6]; - - /** CPPI specific */ - u32 alloc_size; - void __iomem *bd_mem; - struct emac_rx_bd __iomem *bd_pool_head; - struct emac_rx_bd __iomem *active_queue_head; - struct emac_rx_bd __iomem *active_queue_tail; - u32 queue_active; - u32 teardown_pending; - - /* packet and buffer objects */ - struct emac_netpktobj pkt_queue; - struct emac_netbufobj buf_queue; - - /** statistics */ - u32 proc_count; /* number of times emac_rx_bdproc is called */ - u32 processed_bd; - u32 recycled_bd; - u32 out_of_rx_bd; - u32 out_of_rx_buffers; - u32 queue_reinit; - u32 end_of_queue_add; - u32 end_of_queue; - u32 mis_queued_packets; -}; - /* emac_priv: EMAC private data structure * * EMAC adapter private data structure @@ -452,17 +317,10 @@ struct emac_priv { struct platform_device *pdev; struct napi_struct napi; char mac_addr[6]; - spinlock_t tx_lock; - spinlock_t rx_lock; void __iomem *remap_addr; u32 emac_base_phys; void __iomem *emac_base; void __iomem *ctrl_base; - void __iomem *emac_ctrl_ram; - u32 ctrl_ram_size; - u32 hw_ram_addr; - struct emac_txch *txch[EMAC_DEF_MAX_TX_CH]; - struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH]; struct cpdma_ctlr *dma; struct cpdma_chan *txchan; struct cpdma_chan *rxchan; @@ -491,18 +349,6 @@ struct emac_priv { static struct clk *emac_clk; static unsigned long emac_bus_frequency; -#define emac_virt_to_phys(addr, priv) \ - (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \ - + priv->hw_ram_addr) - -/* Cache macros - Packet buffers would be from skb pool which is cached */ -#define EMAC_VIRT_NOCACHE(addr) (addr) - -/* DM644x does not have BD's in cached memory - so no cache functions */ -#define BD_CACHE_INVALIDATE(addr, size) -#define BD_CACHE_WRITEBACK(addr, size) -#define BD_CACHE_WRITEBACK_INVALIDATE(addr, size) - /* EMAC TX Host Error description strings */ static char *emac_txhost_errcodes[16] = { "No error", "SOP error", "Ownership bit not set in SOP buffer", @@ -545,20 +391,6 @@ static void emac_dump_regs(struct emac_priv *priv) emac_ctrl_read(EMAC_CTRL_EWCTL), emac_ctrl_read(EMAC_CTRL_EWINTTCNT)); } - dev_info(emac_dev, "EMAC: TXID: %08X %s, RXID: %08X %s\n", - emac_read(EMAC_TXIDVER), - ((emac_read(EMAC_TXCONTROL)) ? "enabled" : "disabled"), - emac_read(EMAC_RXIDVER), - ((emac_read(EMAC_RXCONTROL)) ? "enabled" : "disabled")); - dev_info(emac_dev, "EMAC: TXIntRaw:%08X, TxIntMasked: %08X, "\ - "TxIntMasSet: %08X\n", emac_read(EMAC_TXINTSTATRAW), - emac_read(EMAC_TXINTSTATMASKED), emac_read(EMAC_TXINTMASKSET)); - dev_info(emac_dev, "EMAC: RXIntRaw:%08X, RxIntMasked: %08X, "\ - "RxIntMasSet: %08X\n", emac_read(EMAC_RXINTSTATRAW), - emac_read(EMAC_RXINTSTATMASKED), emac_read(EMAC_RXINTMASKSET)); - dev_info(emac_dev, "EMAC: MacIntRaw:%08X, MacIntMasked: %08X, "\ - "MacInVector=%08X\n", emac_read(EMAC_MACINTSTATRAW), - emac_read(EMAC_MACINTSTATMASKED), emac_read(EMAC_MACINVECTOR)); dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n", emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL)); dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\ @@ -567,8 +399,6 @@ static void emac_dump_regs(struct emac_priv *priv) dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\ "MacConfig=%08X\n", emac_read(EMAC_MACCONTROL), emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG)); - dev_info(emac_dev, "EMAC: TXHDP[0]:%08X, RXHDP[0]: %08X\n", - emac_read(EMAC_TXHDP(0)), emac_read(EMAC_RXHDP(0))); dev_info(emac_dev, "EMAC Statistics\n"); dev_info(emac_dev, "EMAC: rx_good_frames:%d\n", emac_read(EMAC_RXGOODFRAMES)); @@ -1208,373 +1038,6 @@ static void emac_tx_handler(void *token, int len, int status) dev_kfree_skb_any(skb); } -/** EMAC on-chip buffer descriptor memory - * - * WARNING: Please note that the on chip memory is used for both TX and RX - * buffer descriptor queues and is equally divided between TX and RX desc's - * If the number of TX or RX descriptors change this memory pointers need - * to be adjusted. If external memory is allocated then these pointers can - * pointer to the memory - * - */ -#define EMAC_TX_BD_MEM(priv) ((priv)->emac_ctrl_ram) -#define EMAC_RX_BD_MEM(priv) ((priv)->emac_ctrl_ram + \ - (((priv)->ctrl_ram_size) >> 1)) - -/** - * emac_init_txch: TX channel initialization - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device init to setup a TX channel (allocate buffer desc - * create free pool and keep ready for transmission - * - * Returns success(0) or mem alloc failures error code - */ -static int emac_init_txch(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 cnt, bd_size; - void __iomem *mem; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch = NULL; - - txch = kzalloc(sizeof(struct emac_txch), GFP_KERNEL); - if (NULL == txch) { - dev_err(emac_dev, "DaVinci EMAC: TX Ch mem alloc failed"); - return -ENOMEM; - } - priv->txch[ch] = txch; - txch->service_max = EMAC_DEF_TX_MAX_SERVICE; - txch->active_queue_head = NULL; - txch->active_queue_tail = NULL; - txch->queue_active = 0; - txch->teardown_pending = 0; - - /* allocate memory for TX CPPI channel on a 4 byte boundry */ - txch->tx_complete = kzalloc(txch->service_max * sizeof(u32), - GFP_KERNEL); - if (NULL == txch->tx_complete) { - dev_err(emac_dev, "DaVinci EMAC: Tx service mem alloc failed"); - kfree(txch); - return -ENOMEM; - } - - /* allocate buffer descriptor pool align every BD on four word - * boundry for future requirements */ - bd_size = (sizeof(struct emac_tx_bd) + 0xF) & ~0xF; - txch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; - txch->alloc_size = (((bd_size * txch->num_bd) + 0xF) & ~0xF); - - /* alloc TX BD memory */ - txch->bd_mem = EMAC_TX_BD_MEM(priv); - __memzero((void __force *)txch->bd_mem, txch->alloc_size); - - /* initialize the BD linked list */ - mem = (void __force __iomem *) - (((u32 __force) txch->bd_mem + 0xF) & ~0xF); - txch->bd_pool_head = NULL; - for (cnt = 0; cnt < txch->num_bd; cnt++) { - curr_bd = mem + (cnt * bd_size); - curr_bd->next = txch->bd_pool_head; - txch->bd_pool_head = curr_bd; - } - - /* reset statistics counters */ - txch->out_of_tx_bd = 0; - txch->no_active_pkts = 0; - txch->active_queue_count = 0; - - return 0; -} - -/** - * emac_cleanup_txch: Book-keep function to clean TX channel resources - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to clean up TX channel resources - * - */ -static void emac_cleanup_txch(struct emac_priv *priv, u32 ch) -{ - struct emac_txch *txch = priv->txch[ch]; - - if (txch) { - if (txch->bd_mem) - txch->bd_mem = NULL; - kfree(txch->tx_complete); - kfree(txch); - priv->txch[ch] = NULL; - } -} - -/** - * emac_net_tx_complete: TX packet completion function - * @priv: The DaVinci EMAC private adapter structure - * @net_data_tokens: packet token - skb pointer - * @num_tokens: number of skb's to free - * @ch: TX channel number - * - * Frees the skb once packet is transmitted - * - */ -static int emac_net_tx_complete(struct emac_priv *priv, - void **net_data_tokens, - int num_tokens, u32 ch) -{ - struct net_device *ndev = priv->ndev; - u32 cnt; - - if (unlikely(num_tokens && netif_queue_stopped(ndev))) - netif_start_queue(ndev); - for (cnt = 0; cnt < num_tokens; cnt++) { - struct sk_buff *skb = (struct sk_buff *)net_data_tokens[cnt]; - if (skb == NULL) - continue; - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += skb->len; - dev_kfree_skb_any(skb); - } - return 0; -} - -/** - * emac_txch_teardown: TX channel teardown - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to teardown TX channel - * - */ -static void emac_txch_teardown(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ - struct emac_txch *txch = priv->txch[ch]; - struct emac_tx_bd __iomem *curr_bd; - - while ((emac_read(EMAC_TXCP(ch)) & EMAC_TEARDOWN_VALUE) != - EMAC_TEARDOWN_VALUE) { - /* wait till tx teardown complete */ - cpu_relax(); /* TODO: check if this helps ... */ - --teardown_cnt; - if (0 == teardown_cnt) { - dev_err(emac_dev, "EMAC: TX teardown aborted\n"); - break; - } - } - emac_write(EMAC_TXCP(ch), EMAC_TEARDOWN_VALUE); - - /* process sent packets and return skb's to upper layer */ - if (1 == txch->queue_active) { - curr_bd = txch->active_queue_head; - while (curr_bd != NULL) { - dma_unmap_single(emac_dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_TO_DEVICE); - - emac_net_tx_complete(priv, (void __force *) - &curr_bd->buf_token, 1, ch); - if (curr_bd != txch->active_queue_tail) - curr_bd = curr_bd->next; - else - break; - } - txch->bd_pool_head = txch->active_queue_head; - txch->active_queue_head = - txch->active_queue_tail = NULL; - } -} - -/** - * emac_stop_txch: Stop TX channel operation - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to stop TX channel operation - * - */ -static void emac_stop_txch(struct emac_priv *priv, u32 ch) -{ - struct emac_txch *txch = priv->txch[ch]; - - if (txch) { - txch->teardown_pending = 1; - emac_write(EMAC_TXTEARDOWN, 0); - emac_txch_teardown(priv, ch); - txch->teardown_pending = 0; - emac_write(EMAC_TXINTMASKCLEAR, BIT(ch)); - } -} - -/** - * emac_tx_bdproc: TX buffer descriptor (packet) processing - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number to process buffer descriptors for - * @budget: number of packets allowed to process - * @pending: indication to caller that packets are pending to process - * - * Processes TX buffer descriptors after packets are transmitted - checks - * ownership bit on the TX * descriptor and requeues it to free pool & frees - * the SKB buffer. Only "budget" number of packets are processed and - * indication of pending packets provided to the caller - * - * Returns number of packets processed - */ -static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) -{ - struct device *emac_dev = &priv->ndev->dev; - unsigned long flags; - u32 frame_status; - u32 pkts_processed = 0; - u32 tx_complete_cnt = 0; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch = priv->txch[ch]; - u32 *tx_complete_ptr = txch->tx_complete; - - if (unlikely(1 == txch->teardown_pending)) { - if (netif_msg_tx_err(priv) && net_ratelimit()) { - dev_err(emac_dev, "DaVinci EMAC:emac_tx_bdproc: "\ - "teardown pending\n"); - } - return 0; /* dont handle any pkt completions */ - } - - ++txch->proc_count; - spin_lock_irqsave(&priv->tx_lock, flags); - curr_bd = txch->active_queue_head; - if (NULL == curr_bd) { - emac_write(EMAC_TXCP(ch), - emac_virt_to_phys(txch->last_hw_bdprocessed, priv)); - txch->no_active_pkts++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return 0; - } - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - while ((curr_bd) && - ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && - (pkts_processed < budget)) { - emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd, priv)); - txch->active_queue_head = curr_bd->next; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - if (curr_bd->next) { /* misqueued packet */ - emac_write(EMAC_TXHDP(ch), curr_bd->h_next); - ++txch->mis_queued_packets; - } else { - txch->queue_active = 0; /* end of queue */ - } - } - - dma_unmap_single(emac_dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_TO_DEVICE); - - *tx_complete_ptr = (u32) curr_bd->buf_token; - ++tx_complete_ptr; - ++tx_complete_cnt; - curr_bd->next = txch->bd_pool_head; - txch->bd_pool_head = curr_bd; - --txch->active_queue_count; - pkts_processed++; - txch->last_hw_bdprocessed = curr_bd; - curr_bd = txch->active_queue_head; - if (curr_bd) { - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - } - } /* end of pkt processing loop */ - - emac_net_tx_complete(priv, - (void *)&txch->tx_complete[0], - tx_complete_cnt, ch); - spin_unlock_irqrestore(&priv->tx_lock, flags); - return pkts_processed; -} - -#define EMAC_ERR_TX_OUT_OF_BD -1 - -/** - * emac_send: EMAC Transmit function (internal) - * @priv: The DaVinci EMAC private adapter structure - * @pkt: packet pointer (contains skb ptr) - * @ch: TX channel number - * - * Called by the transmit function to queue the packet in EMAC hardware queue - * - * Returns success(0) or error code (typically out of desc's) - */ -static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch) -{ - unsigned long flags; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch; - struct emac_netbufobj *buf_list; - - txch = priv->txch[ch]; - buf_list = pkt->buf_list; /* get handle to the buffer array */ - - /* check packet size and pad if short */ - if (pkt->pkt_length < EMAC_DEF_MIN_ETHPKTSIZE) { - buf_list->length += (EMAC_DEF_MIN_ETHPKTSIZE - pkt->pkt_length); - pkt->pkt_length = EMAC_DEF_MIN_ETHPKTSIZE; - } - - spin_lock_irqsave(&priv->tx_lock, flags); - curr_bd = txch->bd_pool_head; - if (curr_bd == NULL) { - txch->out_of_tx_bd++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return EMAC_ERR_TX_OUT_OF_BD; - } - - txch->bd_pool_head = curr_bd->next; - curr_bd->buf_token = buf_list->buf_token; - curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buf_list->data_ptr, - buf_list->length, DMA_TO_DEVICE); - curr_bd->off_b_len = buf_list->length; - curr_bd->h_next = 0; - curr_bd->next = NULL; - curr_bd->mode = (EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT | - EMAC_CPPI_EOP_BIT | pkt->pkt_length); - - /* flush the packet from cache if write back cache is present */ - BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - - /* send the packet */ - if (txch->active_queue_head == NULL) { - txch->active_queue_head = curr_bd; - txch->active_queue_tail = curr_bd; - if (1 != txch->queue_active) { - emac_write(EMAC_TXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - txch->queue_active = 1; - } - ++txch->queue_reinit; - } else { - register struct emac_tx_bd __iomem *tail_bd; - register u32 frame_status; - - tail_bd = txch->active_queue_tail; - tail_bd->next = curr_bd; - txch->active_queue_tail = curr_bd; - tail_bd = EMAC_VIRT_NOCACHE(tail_bd); - tail_bd->h_next = (int)emac_virt_to_phys(curr_bd, priv); - frame_status = tail_bd->mode; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - emac_write(EMAC_TXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - frame_status &= ~(EMAC_CPPI_EOQ_BIT); - tail_bd->mode = frame_status; - ++txch->end_of_queue_add; - } - } - txch->active_queue_count++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return 0; -} - /** * emac_dev_xmit: EMAC Transmit function * @skb: SKB pointer @@ -1647,207 +1110,6 @@ static void emac_dev_tx_timeout(struct net_device *ndev) } /** - * emac_net_alloc_rx_buf: Allocate a skb for RX - * @priv: The DaVinci EMAC private adapter structure - * @buf_size: size of SKB data buffer to allocate - * @data_token: data token returned (skb handle for storing in buffer desc) - * @ch: RX channel number - * - * Called during RX channel setup - allocates skb buffer of required size - * and provides the skb handle and allocated buffer data pointer to caller - * - * Returns skb data pointer or 0 on failure to alloc skb - */ -static void *emac_net_alloc_rx_buf(struct emac_priv *priv, int buf_size, - void **data_token, u32 ch) -{ - struct net_device *ndev = priv->ndev; - struct device *emac_dev = &ndev->dev; - struct sk_buff *p_skb; - - p_skb = dev_alloc_skb(buf_size); - if (unlikely(NULL == p_skb)) { - if (netif_msg_rx_err(priv) && net_ratelimit()) - dev_err(emac_dev, "DaVinci EMAC: failed to alloc skb"); - return NULL; - } - - /* set device pointer in skb and reserve space for extra bytes */ - p_skb->dev = ndev; - skb_reserve(p_skb, NET_IP_ALIGN); - *data_token = (void *) p_skb; - return p_skb->data; -} - -/** - * emac_init_rxch: RX channel initialization - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * @param: mac address for RX channel - * - * Called during device init to setup a RX channel (allocate buffers and - * buffer descriptors, create queue and keep ready for reception - * - * Returns success(0) or mem alloc failures error code - */ -static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 cnt, bd_size; - void __iomem *mem; - struct emac_rx_bd __iomem *curr_bd; - struct emac_rxch *rxch = NULL; - - rxch = kzalloc(sizeof(struct emac_rxch), GFP_KERNEL); - if (NULL == rxch) { - dev_err(emac_dev, "DaVinci EMAC: RX Ch mem alloc failed"); - return -ENOMEM; - } - priv->rxch[ch] = rxch; - rxch->buf_size = priv->rx_buf_size; - rxch->service_max = EMAC_DEF_RX_MAX_SERVICE; - rxch->queue_active = 0; - rxch->teardown_pending = 0; - - /* save mac address */ - for (cnt = 0; cnt < 6; cnt++) - rxch->mac_addr[cnt] = param[cnt]; - - /* allocate buffer descriptor pool align every BD on four word - * boundry for future requirements */ - bd_size = (sizeof(struct emac_rx_bd) + 0xF) & ~0xF; - rxch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; - rxch->alloc_size = (((bd_size * rxch->num_bd) + 0xF) & ~0xF); - rxch->bd_mem = EMAC_RX_BD_MEM(priv); - __memzero((void __force *)rxch->bd_mem, rxch->alloc_size); - rxch->pkt_queue.buf_list = &rxch->buf_queue; - - /* allocate RX buffer and initialize the BD linked list */ - mem = (void __force __iomem *) - (((u32 __force) rxch->bd_mem + 0xF) & ~0xF); - rxch->active_queue_head = NULL; - rxch->active_queue_tail = mem; - for (cnt = 0; cnt < rxch->num_bd; cnt++) { - curr_bd = mem + (cnt * bd_size); - /* for future use the last parameter contains the BD ptr */ - curr_bd->data_ptr = emac_net_alloc_rx_buf(priv, - rxch->buf_size, - (void __force **)&curr_bd->buf_token, - EMAC_DEF_RX_CH); - if (curr_bd->data_ptr == NULL) { - dev_err(emac_dev, "DaVinci EMAC: RX buf mem alloc " \ - "failed for ch %d\n", ch); - kfree(rxch); - return -ENOMEM; - } - - /* populate the hardware descriptor */ - curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head, - priv); - curr_bd->buff_ptr = dma_map_single(emac_dev, curr_bd->data_ptr, - rxch->buf_size, DMA_FROM_DEVICE); - curr_bd->off_b_len = rxch->buf_size; - curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; - - /* write back to hardware memory */ - BD_CACHE_WRITEBACK_INVALIDATE((u32) curr_bd, - EMAC_BD_LENGTH_FOR_CACHE); - curr_bd->next = rxch->active_queue_head; - rxch->active_queue_head = curr_bd; - } - - /* At this point rxCppi->activeQueueHead points to the first - RX BD ready to be given to RX HDP and rxch->active_queue_tail - points to the last RX BD - */ - return 0; -} - -/** - * emac_rxch_teardown: RX channel teardown - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to teardown RX channel - * - */ -static void emac_rxch_teardown(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ - - while ((emac_read(EMAC_RXCP(ch)) & EMAC_TEARDOWN_VALUE) != - EMAC_TEARDOWN_VALUE) { - /* wait till tx teardown complete */ - cpu_relax(); /* TODO: check if this helps ... */ - --teardown_cnt; - if (0 == teardown_cnt) { - dev_err(emac_dev, "EMAC: RX teardown aborted\n"); - break; - } - } - emac_write(EMAC_RXCP(ch), EMAC_TEARDOWN_VALUE); -} - -/** - * emac_stop_rxch: Stop RX channel operation - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to stop RX channel operation - * - */ -static void emac_stop_rxch(struct emac_priv *priv, u32 ch) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - - if (rxch) { - rxch->teardown_pending = 1; - emac_write(EMAC_RXTEARDOWN, ch); - /* wait for teardown complete */ - emac_rxch_teardown(priv, ch); - rxch->teardown_pending = 0; - emac_write(EMAC_RXINTMASKCLEAR, BIT(ch)); - } -} - -/** - * emac_cleanup_rxch: Book-keep function to clean RX channel resources - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to clean up RX channel resources - * - */ -static void emac_cleanup_rxch(struct emac_priv *priv, u32 ch) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - struct emac_rx_bd __iomem *curr_bd; - - if (rxch) { - /* free the receive buffers previously allocated */ - curr_bd = rxch->active_queue_head; - while (curr_bd) { - if (curr_bd->buf_token) { - dma_unmap_single(&priv->ndev->dev, - curr_bd->buff_ptr, - curr_bd->off_b_len - & EMAC_RX_BD_BUF_SIZE, - DMA_FROM_DEVICE); - - dev_kfree_skb_any((struct sk_buff *)\ - curr_bd->buf_token); - } - curr_bd = curr_bd->next; - } - if (rxch->bd_mem) - rxch->bd_mem = NULL; - kfree(rxch); - priv->rxch[ch] = NULL; - } -} - -/** * emac_set_type0addr: Set EMAC Type0 mac address * @priv: The DaVinci EMAC private adapter structure * @ch: RX channel number @@ -1987,194 +1249,6 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) } /** - * emac_addbd_to_rx_queue: Recycle RX buffer descriptor - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number to process buffer descriptors for - * @curr_bd: current buffer descriptor - * @buffer: buffer pointer for descriptor - * @buf_token: buffer token (stores skb information) - * - * Prepares the recycled buffer descriptor and addes it to hardware - * receive queue - if queue empty this descriptor becomes the head - * else addes the descriptor to end of queue - * - */ -static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch, - struct emac_rx_bd __iomem *curr_bd, - char *buffer, void *buf_token) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - - /* populate the hardware descriptor */ - curr_bd->h_next = 0; - curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buffer, - rxch->buf_size, DMA_FROM_DEVICE); - curr_bd->off_b_len = rxch->buf_size; - curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; - curr_bd->next = NULL; - curr_bd->data_ptr = buffer; - curr_bd->buf_token = buf_token; - - /* write back */ - BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - if (rxch->active_queue_head == NULL) { - rxch->active_queue_head = curr_bd; - rxch->active_queue_tail = curr_bd; - if (0 != rxch->queue_active) { - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(rxch->active_queue_head, priv)); - rxch->queue_active = 1; - } - } else { - struct emac_rx_bd __iomem *tail_bd; - u32 frame_status; - - tail_bd = rxch->active_queue_tail; - rxch->active_queue_tail = curr_bd; - tail_bd->next = curr_bd; - tail_bd = EMAC_VIRT_NOCACHE(tail_bd); - tail_bd->h_next = emac_virt_to_phys(curr_bd, priv); - frame_status = tail_bd->mode; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - frame_status &= ~(EMAC_CPPI_EOQ_BIT); - tail_bd->mode = frame_status; - ++rxch->end_of_queue_add; - } - } - ++rxch->recycled_bd; -} - -/** - * emac_net_rx_cb: Prepares packet and sends to upper layer - * @priv: The DaVinci EMAC private adapter structure - * @net_pkt_list: Network packet list (received packets) - * - * Invalidates packet buffer memory and sends the received packet to upper - * layer - * - * Returns success or appropriate error code (none as of now) - */ -static int emac_net_rx_cb(struct emac_priv *priv, - struct emac_netpktobj *net_pkt_list) -{ - struct net_device *ndev = priv->ndev; - struct sk_buff *p_skb = net_pkt_list->pkt_token; - /* set length of packet */ - skb_put(p_skb, net_pkt_list->pkt_length); - p_skb->protocol = eth_type_trans(p_skb, priv->ndev); - netif_receive_skb(p_skb); - ndev->stats.rx_bytes += net_pkt_list->pkt_length; - ndev->stats.rx_packets++; - return 0; -} - -/** - * emac_rx_bdproc: RX buffer descriptor (packet) processing - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number to process buffer descriptors for - * @budget: number of packets allowed to process - * @pending: indication to caller that packets are pending to process - * - * Processes RX buffer descriptors - checks ownership bit on the RX buffer - * descriptor, sends the receive packet to upper layer, allocates a new SKB - * and recycles the buffer descriptor (requeues it in hardware RX queue). - * Only "budget" number of packets are processed and indication of pending - * packets provided to the caller. - * - * Returns number of packets processed (and indication of pending packets) - */ -static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) -{ - unsigned long flags; - u32 frame_status; - u32 pkts_processed = 0; - char *new_buffer; - struct emac_rx_bd __iomem *curr_bd; - struct emac_rx_bd __iomem *last_bd; - struct emac_netpktobj *curr_pkt, pkt_obj; - struct emac_netbufobj buf_obj; - struct emac_netbufobj *rx_buf_obj; - void *new_buf_token; - struct emac_rxch *rxch = priv->rxch[ch]; - - if (unlikely(1 == rxch->teardown_pending)) - return 0; - ++rxch->proc_count; - spin_lock_irqsave(&priv->rx_lock, flags); - pkt_obj.buf_list = &buf_obj; - curr_pkt = &pkt_obj; - curr_bd = rxch->active_queue_head; - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - - while ((curr_bd) && - ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && - (pkts_processed < budget)) { - - new_buffer = emac_net_alloc_rx_buf(priv, rxch->buf_size, - &new_buf_token, EMAC_DEF_RX_CH); - if (unlikely(NULL == new_buffer)) { - ++rxch->out_of_rx_buffers; - goto end_emac_rx_bdproc; - } - - /* populate received packet data structure */ - rx_buf_obj = &curr_pkt->buf_list[0]; - rx_buf_obj->data_ptr = (char *)curr_bd->data_ptr; - rx_buf_obj->length = curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE; - rx_buf_obj->buf_token = curr_bd->buf_token; - - dma_unmap_single(&priv->ndev->dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_FROM_DEVICE); - - curr_pkt->pkt_token = curr_pkt->buf_list->buf_token; - curr_pkt->num_bufs = 1; - curr_pkt->pkt_length = - (frame_status & EMAC_RX_BD_PKT_LENGTH_MASK); - emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd, priv)); - ++rxch->processed_bd; - last_bd = curr_bd; - curr_bd = last_bd->next; - rxch->active_queue_head = curr_bd; - - /* check if end of RX queue ? */ - if (frame_status & EMAC_CPPI_EOQ_BIT) { - if (curr_bd) { - ++rxch->mis_queued_packets; - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - } else { - ++rxch->end_of_queue; - rxch->queue_active = 0; - } - } - - /* recycle BD */ - emac_addbd_to_rx_queue(priv, ch, last_bd, new_buffer, - new_buf_token); - - /* return the packet to the user - BD ptr passed in - * last parameter for potential *future* use */ - spin_unlock_irqrestore(&priv->rx_lock, flags); - emac_net_rx_cb(priv, curr_pkt); - spin_lock_irqsave(&priv->rx_lock, flags); - curr_bd = rxch->active_queue_head; - if (curr_bd) { - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - } - ++pkts_processed; - } - -end_emac_rx_bdproc: - spin_unlock_irqrestore(&priv->rx_lock, flags); - return pkts_processed; -} - -/** * emac_hw_enable: Enable EMAC hardware for packet transmission/reception * @priv: The DaVinci EMAC private adapter structure * @@ -2700,8 +1774,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->ndev = ndev; priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG); - spin_lock_init(&priv->tx_lock); - spin_lock_init(&priv->rx_lock); spin_lock_init(&priv->lock); pdata = pdev->dev.platform_data; @@ -2749,8 +1821,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) ndev->base_addr = (unsigned long)priv->remap_addr; priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset; - priv->ctrl_ram_size = pdata->ctrl_ram_size; - priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset; hw_ram_addr = pdata->hw_ram_addr; if (!hw_ram_addr) -- 1.7.0.4 From vm.rod25 at gmail.com Thu Sep 2 17:10:54 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Thu, 2 Sep 2010 17:10:54 -0500 Subject: [PATCH v3] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <87fwxs6n6b.fsf@deeprootsystems.com> References: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> <87fwxs6n6b.fsf@deeprootsystems.com> Message-ID: On Thu, Sep 2, 2010 at 1:00 PM, Kevin Hilman wrote: > Victor Rodriguez writes: > >> This patch adds initial support for the Hawkboard-L138 system >> It is under the machine name "omapl138_hawkboard". >> This system is based on the da850 davinci CPU architecture. >> Information on these system may be found at http://www.hawkboard.org. >> Basic support for the console UART is included in this patch. >> Depends on Michael Williamson patches: >> http://alturl.com/hha7u and http://alturl.com/qy4cr >> >> Signed-off-by: Victor Rodriguez >> >> Changes since v2: >> 1) Correct number of characters per line in patch description. >> 2) Correct board description in Kconfig file >> 3) Correct da8xx_omapl_defconfig >> 4) Correct issue with CONFIG_SERIAL_8250_CONSOLE >> based on Michael Williamson patch http://alturl.com/hha7u >> 5) Correct issue with voltage regulator control >> based on Michael Williamson patch http://alturl.com/qy4cr > > [...] > >> +static __init void omapl138_hawk_init(void) >> +{ >> + >> + ? ? davinci_serial_init(&omapl138_hawk_uart_config); >> + >> + ? ? /* >> + ? ? ?* shut down uart 0 and 1; they are not used on the board and >> + ? ? ?* accessing them causes endless "too much work in irq53" messages >> + ? ? ?* with arago fs >> + ? ? ?*/ >> + ? ? __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >> + ? ? __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); > > I still dont' want to merge this until this issue is understood and > described in the changelog (or the code removed.) > > Kevin > Hi Kevin I found this in the hardware documentation Just UART 2 and UART 0 are enable for the user UART 1 is multiplexed for Ethernet communication (LAN8710A-EZK) it is not even aloud in expansion connector for the user. The expansion connector table explain that UART 0 Pin # 7 is for SPI0_SCS[2] / UART0_RTS / GP8[1] / MII_RXD[0] /SATA_CP_DET Pin # 8 is for SPI0_SCS[3] / UART0_CTS / GP8[2] / MII_RXD[1]/SATA_MP SWITCH Pin # 9 is for SPI0_SCS[4] / UART0_TXD / GP8[3] / MII_RXD[2] Pin # 10 is for SPI0_SCS[5] / UART0_RXD / GP8[4] / MII_RXD[3] and UART 1 Pin # 17 is for SPI1_SCS[4] / UART2_TXD /I2C1_SDA /GP1[2] Pin # 18 is for SPI1_SCS[5] / UART2_RXD /I2C1_SCL /GP1[3 So I propose these options 1) just enable UART 0 and 2 since the beginning 2 ) eneble the tree UARTs and then disable just UART 1 both proved and works fine Thanks Victor From caglarakyuz at gmail.com Thu Sep 2 17:18:10 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Fri, 3 Sep 2010 01:18:10 +0300 Subject: [PATCH v3] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <87fwxs6n6b.fsf@deeprootsystems.com> References: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> <87fwxs6n6b.fsf@deeprootsystems.com> Message-ID: <201009030118.10100.caglarakyuz@gmail.com> On Thursday 02 September 2010 09:00:12 pm Kevin Hilman wrote: > Victor Rodriguez writes: > > This patch adds initial support for the Hawkboard-L138 system > > It is under the machine name "omapl138_hawkboard". > > This system is based on the da850 davinci CPU architecture. > > Information on these system may be found at http://www.hawkboard.org. > > Basic support for the console UART is included in this patch. > > Depends on Michael Williamson patches: > > http://alturl.com/hha7u and http://alturl.com/qy4cr > > > > Signed-off-by: Victor Rodriguez > > > > Changes since v2: > > 1) Correct number of characters per line in patch description. > > 2) Correct board description in Kconfig file > > 3) Correct da8xx_omapl_defconfig > > 4) Correct issue with CONFIG_SERIAL_8250_CONSOLE > > based on Michael Williamson patch http://alturl.com/hha7u > > 5) Correct issue with voltage regulator control > > based on Michael Williamson patch http://alturl.com/qy4cr > > [...] > > > +static __init void omapl138_hawk_init(void) > > +{ > > + > > + davinci_serial_init(&omapl138_hawk_uart_config); > > + > > + /* > > + * shut down uart 0 and 1; they are not used on the board and > > + * accessing them causes endless "too much work in irq53" messages > > + * with arago fs > > + */ > > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > > + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); > > I still dont' want to merge this until this issue is understood and > described in the changelog (or the code removed.) > Registering only 3rd uart(.enabled_uarts = 0x4) and removing these hacks works. However, existing user-space relies system console to be on ttyS2. Besides this hack also exists in board-da850-evm.c so file-systems prepared for EVM will not work on Hawkboard without modification. I think this is a da850 issue, not a Hawk one. Do you think Michael Williamson's explanation is good enough to go as comment above? Best Regards, Caglar From vm.rod25 at gmail.com Thu Sep 2 17:18:11 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Thu, 2 Sep 2010 17:18:11 -0500 Subject: [PATCH v3] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <201009030118.10100.caglarakyuz@gmail.com> References: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> <87fwxs6n6b.fsf@deeprootsystems.com> <201009030118.10100.caglarakyuz@gmail.com> Message-ID: On Thu, Sep 2, 2010 at 5:18 PM, Caglar Akyuz wrote: > On Thursday 02 September 2010 09:00:12 pm Kevin Hilman wrote: >> Victor Rodriguez writes: >> > This patch adds initial support for the Hawkboard-L138 system >> > It is under the machine name "omapl138_hawkboard". >> > This system is based on the da850 davinci CPU architecture. >> > Information on these system may be found at http://www.hawkboard.org. >> > Basic support for the console UART is included in this patch. >> > Depends on Michael Williamson patches: >> > http://alturl.com/hha7u and http://alturl.com/qy4cr >> > >> > Signed-off-by: Victor Rodriguez >> > >> > Changes since v2: >> > 1) Correct number of characters per line in patch description. >> > 2) Correct board description in Kconfig file >> > 3) Correct da8xx_omapl_defconfig >> > 4) Correct issue with CONFIG_SERIAL_8250_CONSOLE >> > based on Michael Williamson patch http://alturl.com/hha7u >> > 5) Correct issue with voltage regulator control >> > based on Michael Williamson patch http://alturl.com/qy4cr >> >> [...] >> >> > +static __init void omapl138_hawk_init(void) >> > +{ >> > + >> > + ? davinci_serial_init(&omapl138_hawk_uart_config); >> > + >> > + ? /* >> > + ? ?* shut down uart 0 and 1; they are not used on the board and >> > + ? ?* accessing them causes endless "too much work in irq53" messages >> > + ? ?* with arago fs >> > + ? ?*/ >> > + ? __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >> > + ? __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); >> >> I still dont' want to merge this until this issue is understood and >> described in the changelog (or the code removed.) >> > > Registering only 3rd uart(.enabled_uarts = 0x4) and removing these hacks > works. > > However, existing user-space relies system console to be on ttyS2. Besides > this hack also exists in board-da850-evm.c so file-systems prepared for EVM > will not work on Hawkboard without modification. > > I think this is a da850 issue, not a Hawk one. Do you think Michael > Williamson's explanation is good enough to go as comment above? Sorry I did not see Michael explanation when i was sending my message but I think that is a good way to fix, how does Michael explain. > Best Regards, > Caglar > From joshh at imsar.com Thu Sep 2 18:13:14 2010 From: joshh at imsar.com (Joshua Hintze) Date: Thu, 2 Sep 2010 17:13:14 -0600 Subject: Inconsistent ATA write speeds between different boards Message-ID: <011a01cb4af4$6c084cb0$4418e610$@com> I have two different development kits for the DM6446. The first is running the old MontaVista 2.6.10 on a 3rd party demo board. The second is running using the PSP 3.0.1 (linux 2.6.32) from the Arago project running on the EVM-6446. On the first 2.6.10 I can get a sustained write speed of about 20 MBps using a JFS filesystem. One the second (2.6.32) I can get peak 20 MBps, however it fluctuates all over the place dropping down to 8MBps sometimes. This is all using UDMA Mode 4, the highest the Davinci 6446 supports. With that being said I have dived deep into this problem looking at the differences between the palm chip drivers. There are quite a few changes so I decided to hook up a logic analyzer to the the DMA signaling lines. Now bear with me while I talk low level. On the ATA interface the DMARQ line signals to the host that the device is ready to receive data. Sometime during a large file transfer the DDMARDY asserts telling the host that the drive needs to pause communication. The ATA specification says that the device will eventually de-assert DDMARDY when its ready to receive more data. There is an additional STOP line that the host can assert to tell the device that it is done sending data or terminate. Now here is what I am seeing. On the 3d-party 2.6.10 kernel board when the DDMARDY line asserts (telling the host to wait), the host stops sending data and waits, but after about 200 uS I see the STOP line assert and de-assert, then it toggles 8 times and another 50 uS later it toggles again and the DMARQ line from the device finally goes high saying more data can be transferred. This scenario is presented exactly the same on the EVM-6446 however instead of ~200uS before the STOP line from the host starts toggling, it's more like 8millseconds! This is quite puzzling to me, first why does the host even initiate a STOP when the device told it to pause, and second what is controlling this sort of timeout? I've looked through all the registers in the ATA spru document and I didn't see anything related to a timeout. There doesn't seem to be anything on the ATA specification that says a host should stop the DMA burst out when it has waited for too long. Any thoughts? I'm pretty sure that this is the cause for slower write speeds on the newer kernel or this EVM board. Thanks in advance -------------- next part -------------- An HTML attachment was scrubbed... URL: From vm.rod25 at gmail.com Thu Sep 2 19:23:53 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Thu, 2 Sep 2010 19:23:53 -0500 Subject: [PATCH v4] davinci: Initial support for Omapl138-Hawkboard Message-ID: <1283473433-9343-1-git-send-email-vm.rod25@gmail.com> This patch adds initial support for the Hawkboard-L138 system It is under the machine name "omapl138_hawkboard". This system is based on the da850 davinci CPU architecture. Information on these system may be found at http://www.hawkboard.org. Basic support for the console UART is included in this patch. Depends on Michael Williamson patches: http://alturl.com/hha7u and http://alturl.com/qy4cr Signed-off-by: Victor Rodriguez --- Changes since v3: 1) Registering only UART 2 in davinci uart configuration Notes: This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 from Kernel development tree for TI DaVinci family of processors. This patch works with da8xx_omapl_defconfig plus this patch. Depens on patches http://alturl.com/hha7u and http://alturl.com/qy4cr This patch just works for UART 2 arch/arm/configs/da8xx_omapl_defconfig | 1 + arch/arm/mach-davinci/Kconfig | 8 +++ arch/arm/mach-davinci/Makefile | 1 + arch/arm/mach-davinci/board-da850-hawk.c | 56 +++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/uncompress.h | 1 + 5 files changed, 67 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/board-da850-hawk.c diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig index 3952a4e..d7cb4b8 100644 --- a/arch/arm/configs/da8xx_omapl_defconfig +++ b/arch/arm/configs/da8xx_omapl_defconfig @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y CONFIG_ARCH_DAVINCI=y CONFIG_ARCH_DAVINCI_DA830=y CONFIG_ARCH_DAVINCI_DA850=y +CONFIG_MACH_OMAPL138_HAWKBOARD=y CONFIG_DAVINCI_RESET_CLOCKS=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 2bf03e9..985c261 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -185,6 +185,14 @@ config MACH_TNETV107X help Say Y here to select the TI TNETV107X Evaluation Module. +config MACH_OMAPL138_HAWKBOARD + bool "TI AM1808 / OMAPL138 Hawkboard platform" + depends on ARCH_DAVINCI_DA850 + help + Say Y here to select the TI AM1808 / OMAPL138 Hawkboard platform . + Information of this board may be found at + http://www.hawkboard.org/ + config DAVINCI_MUX bool "DAVINCI multiplexing support" depends on ARCH_DAVINCI diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 77a0f71..484071d 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-da850-hawk.o # Power Management obj-$(CONFIG_CPU_FREQ) += cpufreq.o diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c new file mode 100644 index 0000000..ba54672 --- /dev/null +++ b/arch/arm/mach-davinci/board-da850-hawk.c @@ -0,0 +1,56 @@ +/* + * Hawkboard.org based on TI's OMAP-L138 Platform + * + * Initial code: Syed Mohammed Khasim + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 +#include +#include +#include + +#include +#include + +#include +#include + +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { + .enabled_uarts = 0x4, +}; + +static __init void omapl138_hawk_init(void) +{ + davinci_serial_init(&omapl138_hawk_uart_config); +} + +#ifdef CONFIG_SERIAL_8250_CONSOLE +static int __init omapl138_hawk_console_init(void) +{ + if (!machine_is_omapl138_hawkboard()) + return 0; + + return add_preferred_console("ttyS", 2, "115200"); +} +console_initcall(omapl138_hawk_console_init); +#endif + +static void __init omapl138_hawk_map_io(void) +{ + da850_init(); +} + +MACHINE_START(OMAPL138_HAWKBOARD, "OMAP-L138") + .phys_io = IO_PHYS, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, + .boot_params = (DA8XX_DDR_BASE + 0x100), + .map_io = omapl138_hawk_map_io, + .init_irq = cp_intc_init, + .timer = &davinci_timer, + .init_machine = omapl138_hawk_init, +MACHINE_END diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h index 15a6192..640f834 100644 --- a/arch/arm/mach-davinci/include/mach/uncompress.h +++ b/arch/arm/mach-davinci/include/mach/uncompress.h @@ -88,6 +88,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) /* DA8xx boards */ DEBUG_LL_DA8XX(davinci_da830_evm, 2); DEBUG_LL_DA8XX(davinci_da850_evm, 2); + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); /* TNETV107x boards */ DEBUG_LL_TNETV107X(tnetv107x, 1); -- 1.6.0.5 From vm.rod25 at gmail.com Thu Sep 2 19:29:51 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Thu, 2 Sep 2010 19:29:51 -0500 Subject: [PATCH v3] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: References: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> <87fwxs6n6b.fsf@deeprootsystems.com> <201009030118.10100.caglarakyuz@gmail.com> Message-ID: On Thu, Sep 2, 2010 at 5:18 PM, Victor Rodriguez wrote: > On Thu, Sep 2, 2010 at 5:18 PM, Caglar Akyuz wrote: >> On Thursday 02 September 2010 09:00:12 pm Kevin Hilman wrote: >>> Victor Rodriguez writes: >>> > This patch adds initial support for the Hawkboard-L138 system >>> > It is under the machine name "omapl138_hawkboard". >>> > This system is based on the da850 davinci CPU architecture. >>> > Information on these system may be found at http://www.hawkboard.org. >>> > Basic support for the console UART is included in this patch. >>> > Depends on Michael Williamson patches: >>> > http://alturl.com/hha7u and http://alturl.com/qy4cr >>> > >>> > Signed-off-by: Victor Rodriguez >>> > >>> > Changes since v2: >>> > 1) Correct number of characters per line in patch description. >>> > 2) Correct board description in Kconfig file >>> > 3) Correct da8xx_omapl_defconfig >>> > 4) Correct issue with CONFIG_SERIAL_8250_CONSOLE >>> > based on Michael Williamson patch http://alturl.com/hha7u >>> > 5) Correct issue with voltage regulator control >>> > based on Michael Williamson patch http://alturl.com/qy4cr >>> >>> [...] >>> >>> > +static __init void omapl138_hawk_init(void) >>> > +{ >>> > + >>> > + ? davinci_serial_init(&omapl138_hawk_uart_config); >>> > + >>> > + ? /* >>> > + ? ?* shut down uart 0 and 1; they are not used on the board and >>> > + ? ?* accessing them causes endless "too much work in irq53" messages >>> > + ? ?* with arago fs >>> > + ? ?*/ >>> > + ? __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >>> > + ? __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); >>> >>> I still dont' want to merge this until this issue is understood and >>> described in the changelog (or the code removed.) >>> >> >> Registering only 3rd uart(.enabled_uarts = 0x4) and removing these hacks >> works. >> >> However, existing user-space relies system console to be on ttyS2. Besides >> this hack also exists in board-da850-evm.c so file-systems prepared for EVM >> will not work on Hawkboard without modification. >> >> I think this is a da850 issue, not a Hawk one. Do you think Michael >> Williamson's explanation is good enough to go as comment above? > > Sorry I did not see Michael explanation when i was sending my message > but I think that is a good way to fix, how does Michael explain. > > > >> Best Regards, >> Caglar >> > I have one question even if we let just the third UART, what happen whit UART 0, if some one need to access to this UART, it is available in the hardware, Until I understand we need to enable both, but is just my opinion Thanks VIctor Rodriguez From michael.williamson at criticallink.com Thu Sep 2 20:14:25 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Thu, 02 Sep 2010 21:14:25 -0400 Subject: Querying PSC status? Message-ID: <4C804BF1.6060701@criticallink.com> Is there an easy way to query the PSC status for a module? (e.g., to see what the MDSTATn is)? -Mike From michael.williamson at criticallink.com Thu Sep 2 21:19:40 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Thu, 02 Sep 2010 22:19:40 -0400 Subject: [PATCH v2 05/10] davinci: cleanup unused davinci mdio arch code In-Reply-To: <1283465008-18606-6-git-send-email-cyril@ti.com> References: <1283465008-18606-1-git-send-email-cyril@ti.com> <1283465008-18606-6-git-send-email-cyril@ti.com> Message-ID: <4C805B3C.9040804@criticallink.com> On 09/02/2010 06:03 PM, Cyril Chemparathy wrote: > This patch removes davinci architecture code that has now been rendered > useless by the previous patches in the MDIO separation series. > > Signed-off-by: Cyril Chemparathy > --- > arch/arm/mach-davinci/board-da830-evm.c | 5 ----- > arch/arm/mach-davinci/board-da850-evm.c | 6 ------ > arch/arm/mach-davinci/board-dm365-evm.c | 7 ------- > arch/arm/mach-davinci/board-dm644x-evm.c | 7 ------- > arch/arm/mach-davinci/board-dm646x-evm.c | 8 -------- > arch/arm/mach-davinci/board-neuros-osd2.c | 7 ------- > arch/arm/mach-davinci/board-sffsdr.c | 7 ------- [snip] There is a new/pending board file in the davinci-linux tree that will also need to be updated in similar fashion as the board-da850-evm. arch/arm/mach-davinci/board-mityomapl138.c -Mike From nsekhar at ti.com Fri Sep 3 00:39:15 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Fri, 3 Sep 2010 11:09:15 +0530 Subject: [PATCH v3] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <4C801DBC.5050105@criticallink.com> References: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> <87fwxs6n6b.fsf@deeprootsystems.com> <4C801DBC.5050105@criticallink.com> Message-ID: On Fri, Sep 03, 2010 at 03:27:16, Michael Williamson wrote: > On 09/02/2010 02:00 PM, Kevin Hilman wrote: > > Victor Rodriguez writes: > > > [...] > > > > [...] > > > >> +static __init void omapl138_hawk_init(void) > >> +{ > >> + > >> + davinci_serial_init(&omapl138_hawk_uart_config); > >> + > >> + /* > >> + * shut down uart 0 and 1; they are not used on the board and > >> + * accessing them causes endless "too much work in irq53" messages > >> + * with arago fs > >> + */ > >> + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > >> + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); > > > > I still dont' want to merge this until this issue is understood and > > described in the changelog (or the code removed.) > > > > Looking at the schametic, neither UART0 or UART1 are ever hooked up, so it seems > like the "enabled_uarts" fields should just be set to 0x4 (UART2) and these lines > that pound the controller removed. > > I'm fairly certain the "too much work in irq53" issue here has to > do with the fact that the pins for the UART0 Rx line and output flow control > line, which share pin-mux duties with the MII data lines, are hooked up > externally to the LAN8710 chip on the hawkboard. > > Turns out, the pin-mux controls don't appear to really disconnect inputs from > devices having input ports that share a pin via the muxing logic (only outputs > are truly "muxed" at the pin level). > > The LAN interface is probably causing serial interrupts based on receive data or > flow control logic firing for UART0, because you're enabling it in the enable_uarts > mask and enumerating the device. > > We actually have seen a similar problem with trying to use UART1 with no HW flow > control and and the McASP. The UART1 CTS/RTS lines pin-mux-share lines with the > McASP AHCLKX and AHCLKR. The minute you try to enable the McASP, the serial driver > gets pounded with flow control interrupts. There's no provision, that I can find > in the kernel anyway, that allows for disabling CTS/RTS interrupts in the > platform definition. (looking at a patch for this...) Also, this problem is only seen on Arago filesystem (will probably be seen with Angstrom and other OE based filesystems). This is because this filesystem tries to open UART 0, 1 and 2 irrespective of what is specified as the console. If the UART is not opened, you should not see the messages. This is the case with MontaVista Pro 5.0 filesystem. I guess ideally only UART2 should have been registered with Linux. Changing that now on the EVM will cause everyone to update their boot params. Thanks, Sekhar From nsekhar at ti.com Fri Sep 3 01:25:18 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Fri, 3 Sep 2010 11:55:18 +0530 Subject: [PATCH] davinci: Add machine checks to DA8XX serial console init routines In-Reply-To: <87r5hc834e.fsf@deeprootsystems.com> References: <1283279415-25678-1-git-send-email-michael.williamson@criticallink.com> <87r5hc9iv5.fsf@deeprootsystems.com> <4C7FDD77.3010204@mvista.com> <87r5hc834e.fsf@deeprootsystems.com> Message-ID: On Thu, Sep 02, 2010 at 23:00:25, Kevin Hilman wrote: > Sergei Shtylyov writes: > > > Hello. > > > > Kevin Hilman wrote: > > > >>> This patch adds machine checks in the serial console init routines > >>> for the DA8XX EVM boards. This is needed because there are other > >>> DA8XX based machines that use a different UART/tty as the console > >>> and may be included in a common kernel build. > > > >>> Signed-off-by: Michael Williamson > > > >> Applied, queueing for 2.6.37 in davinci-next branch. > > > > But this is a bugfix, no? > > > > True, but we're already at -rc3 and Linus only wants true regression > fixes after -rc3. Technically, it's not a regresssion since it's been > there all along. ;) (lame excuse, I know) > > The real reason is that I don't have any other davinci fixes queued, so > I'm choosing to be lazy and queue this with the rest of the stuff for > .37. Also this actually affects only MityDSP board functionality which will only show up in 2.6.37. Thanks, Sekhar From sudhakar.raj at ti.com Fri Sep 3 06:12:22 2010 From: sudhakar.raj at ti.com (Sudhakar Rajashekhara) Date: Fri, 3 Sep 2010 16:42:22 +0530 Subject: [PATCH] nand/davinci: relax a timeout for ECC-initialization In-Reply-To: <1283510137-23573-1-git-send-email-w.sang@pengutronix.de> References: <1283382898.2209.62.camel@brekeke> <1283510137-23573-1-git-send-email-w.sang@pengutronix.de> Message-ID: <030d01cb4b58$e18cafd0$a4a60f70$@raj@ti.com> Hi Wolfram Sang, On Fri, Sep 03, 2010 at 16:05:37, Wolfram Sang wrote: > Sudhakar found out that 100us are enough. Sadly, his updated patch was > overlooked and an older version still using 100ms was merged. Fix this. > > Reference: http://patchwork.ozlabs.org/patch/59180/ > > Signed-off-by: Wolfram Sang > Cc: Sudhakar Rajashekhara > Cc: Sneha Narnakaje > Cc: Artem Bityutskiy > --- > > Artem, if you pick up this one, too, then we have what Sudhakar sent as > v3 of his original patch. Except for some minor rewording in the comment. > > Sudhakar, I hope it is okay if I send this patch now. I just want to have > the confusion about the different versions gone. I was tied up for the past few days, so couldn't work on this patch. Thanks for taking this up. Can you modify the comment also to match my patch and re-submit this again? Thanks, Sudhakar From khilman at deeprootsystems.com Fri Sep 3 09:40:21 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Fri, 03 Sep 2010 07:40:21 -0700 Subject: [PATCH v3] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: (Victor Rodriguez's message of "Thu, 2 Sep 2010 19:29:51 -0500") References: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> <87fwxs6n6b.fsf@deeprootsystems.com> <201009030118.10100.caglarakyuz@gmail.com> Message-ID: <871v9azy96.fsf@deeprootsystems.com> Victor Rodriguez writes: > On Thu, Sep 2, 2010 at 5:18 PM, Victor Rodriguez wrote: >> On Thu, Sep 2, 2010 at 5:18 PM, Caglar Akyuz wrote: >>> On Thursday 02 September 2010 09:00:12 pm Kevin Hilman wrote: >>>> Victor Rodriguez writes: >>>> > This patch adds initial support for the Hawkboard-L138 system >>>> > It is under the machine name "omapl138_hawkboard". >>>> > This system is based on the da850 davinci CPU architecture. >>>> > Information on these system may be found at http://www.hawkboard.org. >>>> > Basic support for the console UART is included in this patch. >>>> > Depends on Michael Williamson patches: >>>> > http://alturl.com/hha7u and http://alturl.com/qy4cr >>>> > >>>> > Signed-off-by: Victor Rodriguez >>>> > >>>> > Changes since v2: >>>> > 1) Correct number of characters per line in patch description. >>>> > 2) Correct board description in Kconfig file >>>> > 3) Correct da8xx_omapl_defconfig >>>> > 4) Correct issue with CONFIG_SERIAL_8250_CONSOLE >>>> > based on Michael Williamson patch http://alturl.com/hha7u >>>> > 5) Correct issue with voltage regulator control >>>> > based on Michael Williamson patch http://alturl.com/qy4cr >>>> >>>> [...] >>>> >>>> > +static __init void omapl138_hawk_init(void) >>>> > +{ >>>> > + >>>> > + ? davinci_serial_init(&omapl138_hawk_uart_config); >>>> > + >>>> > + ? /* >>>> > + ? ?* shut down uart 0 and 1; they are not used on the board and >>>> > + ? ?* accessing them causes endless "too much work in irq53" messages >>>> > + ? ?* with arago fs >>>> > + ? ?*/ >>>> > + ? __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >>>> > + ? __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); >>>> >>>> I still dont' want to merge this until this issue is understood and >>>> described in the changelog (or the code removed.) >>>> >>> >>> Registering only 3rd uart(.enabled_uarts = 0x4) and removing these hacks >>> works. >>> >>> However, existing user-space relies system console to be on ttyS2. Besides >>> this hack also exists in board-da850-evm.c so file-systems prepared for EVM >>> will not work on Hawkboard without modification. >>> >>> I think this is a da850 issue, not a Hawk one. Do you think Michael >>> Williamson's explanation is good enough to go as comment above? >> >> Sorry I did not see Michael explanation when i was sending my message >> but I think that is a good way to fix, how does Michael explain. >> >> >> >>> Best Regards, >>> Caglar >>> >> > > I have one question even if we let just the third UART, what happen > whit UART 0, if some one need to access to this UART, it is available > in the hardware, Until I understand we need to enable both, but is > just my opinion Michael suggested that UART0 was not hooked up in hardware either. In any case, I'm OK with disabling one (or both) UARTs if they are not hooked up in hardware. Just replace the comment about 'too much work in irq...' with a descripion about shared pins and the need for them to be disabled. As Sekhar suggested, ideally we would only register one UART, but unfortunately, there is no way to have one UART registered as ttyS2, so the best way to handle it is to register them all and disable the unused/unconnected ones. I'm OK with this workaround, as long as it's clearly documented. If the same problem exists on the EVM, I suggest you separate out this change from your hawkboard patch and add it as a 2nd patch that also fixes the EVM. Kevin From khilman at deeprootsystems.com Fri Sep 3 12:24:34 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Fri, 03 Sep 2010 10:24:34 -0700 Subject: [PATCH v2 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <1283465008-18606-1-git-send-email-cyril@ti.com> (Cyril Chemparathy's message of "Thu, 2 Sep 2010 18:03:18 -0400") References: <1283465008-18606-1-git-send-email-cyril@ti.com> Message-ID: <87eida3fl9.fsf@deeprootsystems.com> Cyril Chemparathy writes: [...] > Although am3517 (omap) board support code has been updated as needed, > emac does not work on this platform. Just to clarify... did EMAC work on AM3517 before this series? Kevin From cyril at ti.com Fri Sep 3 13:20:47 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Fri, 03 Sep 2010 14:20:47 -0400 Subject: [PATCH v2 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <87eida3fl9.fsf@deeprootsystems.com> References: <1283465008-18606-1-git-send-email-cyril@ti.com> <87eida3fl9.fsf@deeprootsystems.com> Message-ID: <4C813C7F.5090602@ti.com> Hi Kevin, [...] >> Although am3517 (omap) board support code has been updated as needed, >> emac does not work on this platform. > > Just to clarify... did EMAC work on AM3517 before this series? No. It didn't work before this series. To get AM3517 EMAC working, the driver needs another patch to enable the interface clock in addition to the functional clock. Regards Cyril. From khilman at deeprootsystems.com Fri Sep 3 13:32:42 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Fri, 03 Sep 2010 11:32:42 -0700 Subject: [PATCH v2 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C813C7F.5090602@ti.com> (Cyril Chemparathy's message of "Fri, 03 Sep 2010 14:20:47 -0400") References: <1283465008-18606-1-git-send-email-cyril@ti.com> <87eida3fl9.fsf@deeprootsystems.com> <4C813C7F.5090602@ti.com> Message-ID: <87eidaznhx.fsf@deeprootsystems.com> Cyril Chemparathy writes: > Hi Kevin, > > [...] >>> Although am3517 (omap) board support code has been updated as needed, >>> emac does not work on this platform. >> >> Just to clarify... did EMAC work on AM3517 before this series? > > No. It didn't work before this series. To get AM3517 EMAC working, the > driver needs another patch to enable the interface clock in addition to > the functional clock. Thanks for the clarification. Kevin From cyril at ti.com Fri Sep 3 15:01:59 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Fri, 3 Sep 2010 16:01:59 -0400 Subject: [PATCH] davinci: add idcode for tnetv107x rev 1.1/1.2 Message-ID: <1283544119-29194-1-git-send-email-cyril@ti.com> This patch adds an entry into the idcode table for tnetv107x silicon revision 1.1 and 1.2 devices. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/tnetv107x.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-davinci/tnetv107x.c b/arch/arm/mach-davinci/tnetv107x.c index 06d2ac9..daeae06 100644 --- a/arch/arm/mach-davinci/tnetv107x.c +++ b/arch/arm/mach-davinci/tnetv107x.c @@ -581,7 +581,14 @@ static struct davinci_id ids[] = { .part_no = 0xb8a1, .manufacturer = 0x017, .cpu_id = DAVINCI_CPU_ID_TNETV107X, - .name = "tnetv107x rev1.0", + .name = "tnetv107x rev 1.0", + }, + { + .variant = 0x1, + .part_no = 0xb8a1, + .manufacturer = 0x017, + .cpu_id = DAVINCI_CPU_ID_TNETV107X, + .name = "tnetv107x rev 1.1/1.2", }, }; -- 1.7.0.4 From santosh.shilimkar at ti.com Sat Sep 4 04:01:39 2010 From: santosh.shilimkar at ti.com (Shilimkar, Santosh) Date: Sat, 4 Sep 2010 14:31:39 +0530 Subject: [PATCH 3/3] davinci: Map sram using MT_MEMORY_NONCACHED instead of MT_DEVICE In-Reply-To: References: <1281262702-27732-1-git-send-email-santosh.shilimkar@ti.com> <87hbih2gyv.fsf@deeprootsystems.com> Message-ID: Tony, > -----Original Message----- > From: linux-omap-owner at vger.kernel.org [mailto:linux-omap- > owner at vger.kernel.org] On Behalf Of Shilimkar, Santosh > Sent: Friday, August 27, 2010 10:17 AM > To: Kevin Hilman > Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org; > davinci-linux-open-source at linux.davincidsp.com > Subject: RE: [PATCH 3/3] davinci: Map sram using MT_MEMORY_NONCACHED > instead of MT_DEVICE > > > -----Original Message----- > > From: Kevin Hilman [mailto:khilman at deeprootsystems.com] > > Sent: Friday, August 27, 2010 3:07 AM > > To: Shilimkar, Santosh > > Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org; > > davinci-linux-open-source at linux.davincidsp.com > > Subject: Re: [PATCH 3/3] davinci: Map sram using MT_MEMORY_NONCACHED > > instead of MT_DEVICE > > > > Kevin Hilman writes: > > > > > On Sun, Aug 8, 2010 at 3:18 AM, Santosh Shilimkar > > > wrote: > > >> On Davinci SRAM is mapped as MT_DEVICE becasue of the section > > >> mapping pre-requisite instead of intended MT_MEMORY_NONCACHED > > >> > > >> Since the section mapping limitation gets fixed with first > > >> patch in this series, the MT_MEMORY_NONCACHED can be used now. > > >> > > >> Have not tested this, so somebody with Davinci hardware can > > >> try this out > > >> > > >> Signed-off-by: Santosh Shilimkar > > >> Cc: davinci-linux-open-source at linux.davincidsp.com > > >> Cc: Kevin Hilman > > > > > > Acked-by: Kevin Hilman > > > > Also, FYI... while not a very thorough test, I boot-tested this series > > on DaVinci (dm355, omapl138) and it worked fine. > > > > I'll include in davinci git (in the davinci-testing branch) so it gets a > > bit more testing. > > Thanks a lot Kevin!! > > Tony, > Can you merge this in lo master as well. Actually I want all these > 3 patches go together so that it doesn't break OMAP/DAVINCI. > Ping Regards, Santosh From michael.williamson at criticallink.com Sat Sep 4 11:11:41 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Sat, 4 Sep 2010 12:11:41 -0400 Subject: [PATCH] davinci: Add I2C0 devices to MityDSP-L138/MityARM-1808 platform Message-ID: <1283616701-6418-1-git-send-email-michael.williamson@criticallink.com> This patch adds the i2c0 bus and attached devices to the MityDSP-L138 and MityARM-1808 davinci SoM. Included is a TPS65023 voltage regulator needed for power management and a small 24c02 EPROM that contains factory configuration data. Signed-off-by: Michael Williamson --- This is based on 08f143b7cdbe9705f6856c2a63b6d3b14b5a8eee of davinci-linux tree. arch/arm/mach-davinci/board-mityomapl138.c | 145 ++++++++++++++++++++++++++++ 1 files changed, 145 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index 7146916..03820ce 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -25,6 +27,141 @@ #define MITYOMAPL138_PHY_MASK 0x08 /* hardcoded for now */ #define MITYOMAPL138_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ +static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = { + .bus_freq = 100, /* kHz */ + .bus_delay = 0, /* usec */ +}; + +/* TPS65023 voltage regulator support */ +/* 1.2V Core */ +struct regulator_consumer_supply tps65023_dcdc1_consumers[] = { + { + .supply = "cvdd", + }, +}; + +/* 1.8V */ +struct regulator_consumer_supply tps65023_dcdc2_consumers[] = { + { + .supply = "usb0_vdda18", + }, + { + .supply = "usb1_vdda18", + }, + { + .supply = "ddr_dvdd18", + }, + { + .supply = "sata_vddr", + }, +}; + +/* 1.2V */ +struct regulator_consumer_supply tps65023_dcdc3_consumers[] = { + { + .supply = "sata_vdd", + }, + { + .supply = "usb_cvdd", + }, + { + .supply = "pll0_vdda", + }, + { + .supply = "pll1_vdda", + }, +}; + +/* 1.8V Aux LDO, not used */ +struct regulator_consumer_supply tps65023_ldo1_consumers[] = { + { + .supply = "1.8v_aux", + }, +}; + +/* FPGA VCC Aux (2.5 or 3.3) LDO */ +struct regulator_consumer_supply tps65023_ldo2_consumers[] = { + { + .supply = "vccaux", + }, +}; + +struct regulator_init_data tps65023_regulator_data[] = { + /* dcdc1 */ + { + .constraints = { + .min_uV = 1150000, + .max_uV = 1350000, + .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS), + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc1_consumers), + .consumer_supplies = tps65023_dcdc1_consumers, + }, + /* dcdc2 */ + { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .valid_ops_mask = (REGULATOR_CHANGE_STATUS), + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc2_consumers), + .consumer_supplies = tps65023_dcdc2_consumers, + }, + /* dcdc3 */ + { + .constraints = { + .min_uV = 1200000, + .max_uV = 1200000, + .valid_ops_mask = (REGULATOR_CHANGE_STATUS), + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc3_consumers), + .consumer_supplies = tps65023_dcdc3_consumers, + }, + /* ldo1 */ + { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .valid_ops_mask = (REGULATOR_CHANGE_STATUS), + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65023_ldo1_consumers), + .consumer_supplies = tps65023_ldo1_consumers, + }, + /* ldo2 */ + { + .constraints = { + .min_uV = 2500000, + .max_uV = 3300000, + .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS), + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65023_ldo2_consumers), + .consumer_supplies = tps65023_ldo2_consumers, + }, +}; + +static struct i2c_board_info __initdata mityomap_tps65023_info[] = { + { + I2C_BOARD_INFO("tps65023", 0x48), + .platform_data = &tps65023_regulator_data[0], + }, + { + I2C_BOARD_INFO("24c02", 0x50), + }, +}; + +static int __init pmic_tps65023_init(void) +{ + return i2c_register_board_info(1, mityomap_tps65023_info, + ARRAY_SIZE(mityomap_tps65023_info)); +} + /* * MityDSP-L138 includes a 256 MByte large-page NAND flash * (128K blocks). @@ -172,6 +309,14 @@ static void __init mityomapl138_init(void) davinci_serial_init(&mityomapl138_uart_config); + ret = da8xx_register_i2c(0, &mityomap_i2c_0_pdata); + if (ret) + pr_warning("i2c0 registration failed %d\n", ret); + + ret = pmic_tps65023_init(); + if (ret) + pr_warning("TPS65023 PMIC init failed: %d\n", ret); + mityomapl138_setup_nand(); mityomapl138_config_emac(); -- 1.7.0.4 From sshtylyov at mvista.com Sun Sep 5 05:31:49 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Sun, 05 Sep 2010 14:31:49 +0400 Subject: [PATCH] davinci: Add I2C0 devices to MityDSP-L138/MityARM-1808 platform In-Reply-To: <1283616701-6418-1-git-send-email-michael.williamson@criticallink.com> References: <1283616701-6418-1-git-send-email-michael.williamson@criticallink.com> Message-ID: <4C837195.2040100@mvista.com> Hello. On 04-09-2010 20:11, Michael Williamson wrote: > This patch adds the i2c0 bus and attached devices to the MityDSP-L138 > and MityARM-1808 davinci SoM. Included is a TPS65023 voltage regulator > needed for power management and a small 24c02 EPROM that contains > factory configuration data. > Signed-off-by: Michael Williamson [...] > diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c > index 7146916..03820ce 100644 > --- a/arch/arm/mach-davinci/board-mityomapl138.c > +++ b/arch/arm/mach-davinci/board-mityomapl138.c [...] > @@ -25,6 +27,141 @@ [...] > +struct regulator_init_data tps65023_regulator_data[] = { > + /* dcdc1 */ > + { > + .constraints = { > + .min_uV = 1150000, > + .max_uV = 1350000, > + .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE | > + REGULATOR_CHANGE_STATUS), Would look better if you aligned it. And parens are useless here. > + .boot_on = 1, > + }, > + .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc1_consumers), > + .consumer_supplies = tps65023_dcdc1_consumers, > + }, > + /* dcdc2 */ > + { > + .constraints = { > + .min_uV = 1800000, > + .max_uV = 1800000, > + .valid_ops_mask = (REGULATOR_CHANGE_STATUS), Useless parens. > + .boot_on = 1, > + }, > + .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc2_consumers), > + .consumer_supplies = tps65023_dcdc2_consumers, > + }, > + /* dcdc3 */ > + { > + .constraints = { > + .min_uV = 1200000, > + .max_uV = 1200000, > + .valid_ops_mask = (REGULATOR_CHANGE_STATUS), Again... > + .boot_on = 1, > + }, > + .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc3_consumers), > + .consumer_supplies = tps65023_dcdc3_consumers, > + }, > + /* ldo1 */ > + { > + .constraints = { > + .min_uV = 1800000, > + .max_uV = 1800000, > + .valid_ops_mask = (REGULATOR_CHANGE_STATUS), And again... > + .boot_on = 1, > + }, > + .num_consumer_supplies = ARRAY_SIZE(tps65023_ldo1_consumers), > + .consumer_supplies = tps65023_ldo1_consumers, > + }, > + /* ldo2 */ > + { > + .constraints = { > + .min_uV = 2500000, > + .max_uV = 3300000, > + .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE | > + REGULATOR_CHANGE_STATUS), Would look better if you aligned it. And parens are useless here. > @@ -172,6 +309,14 @@ static void __init mityomapl138_init(void) > > davinci_serial_init(&mityomapl138_uart_config); > > + ret = da8xx_register_i2c(0,&mityomap_i2c_0_pdata); > + if (ret) > + pr_warning("i2c0 registration failed %d\n", ret); You probably forgot semicolon after "failed" here... > + > + ret = pmic_tps65023_init(); > + if (ret) > + pr_warning("TPS65023 PMIC init failed: %d\n", ret); > + WBR, Sergei From michael.williamson at criticallink.com Sun Sep 5 07:02:52 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Sun, 05 Sep 2010 08:02:52 -0400 Subject: [PATCH] davinci: Add I2C0 devices to MityDSP-L138/MityARM-1808 platform In-Reply-To: <4C837195.2040100@mvista.com> References: <1283616701-6418-1-git-send-email-michael.williamson@criticallink.com> <4C837195.2040100@mvista.com> Message-ID: <4C8386EC.50002@criticallink.com> On 09/05/2010 06:31 AM, Sergei Shtylyov wrote: > Hello. > > On 04-09-2010 20:11, Michael Williamson wrote: > >> This patch adds the i2c0 bus and attached devices to the MityDSP-L138 >> and MityARM-1808 davinci SoM. Included is a TPS65023 voltage regulator >> needed for power management and a small 24c02 EPROM that contains >> factory configuration data. > >> Signed-off-by: Michael Williamson > [...] >> diff --git a/arch/arm/mach-davinci/board-mityomapl138.c >> b/arch/arm/mach-davinci/board-mityomapl138.c >> index 7146916..03820ce 100644 >> --- a/arch/arm/mach-davinci/board-mityomapl138.c >> +++ b/arch/arm/mach-davinci/board-mityomapl138.c > [...] >> @@ -25,6 +27,141 @@ > [...] >> +struct regulator_init_data tps65023_regulator_data[] = { >> + /* dcdc1 */ >> + { >> + .constraints = { >> + .min_uV = 1150000, >> + .max_uV = 1350000, >> + .valid_ops_mask = (REGULATOR_CHANGE_VOLTAGE | >> + REGULATOR_CHANGE_STATUS), > > Would look better if you aligned it. And parens are useless here. > I'll clean it up, but I pretty much lifted it from board-da850-evm.c. The next time someone's in there, I suppose it should also be addressed. Thanks for the comments. From michael.williamson at criticallink.com Sun Sep 5 12:29:39 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Sun, 5 Sep 2010 13:29:39 -0400 Subject: [PATCH v1] davinci: Add I2C0 devices to MityDSP-L138/MityARM-1808 platform Message-ID: <1283707779-23204-1-git-send-email-michael.williamson@criticallink.com> This patch adds the i2c0 bus and attached devices to the MityDSP-L138 and MityARM-1808 davinci SoM. Included is a TPS65023 voltage regulator needed for power management and a small 24c02 EPROM that contains factory configuration data. Signed-off-by: Michael Williamson --- This is based on 08f143b7cdbe9705f6856c2a63b6d3b14b5a8eee of davinci-linux tree. Changes since v0: 1. Misc formatting arch/arm/mach-davinci/board-mityomapl138.c | 145 ++++++++++++++++++++++++++++ 1 files changed, 145 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index 7146916..84d5aff 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -25,6 +27,141 @@ #define MITYOMAPL138_PHY_MASK 0x08 /* hardcoded for now */ #define MITYOMAPL138_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ +static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = { + .bus_freq = 100, /* kHz */ + .bus_delay = 0, /* usec */ +}; + +/* TPS65023 voltage regulator support */ +/* 1.2V Core */ +struct regulator_consumer_supply tps65023_dcdc1_consumers[] = { + { + .supply = "cvdd", + }, +}; + +/* 1.8V */ +struct regulator_consumer_supply tps65023_dcdc2_consumers[] = { + { + .supply = "usb0_vdda18", + }, + { + .supply = "usb1_vdda18", + }, + { + .supply = "ddr_dvdd18", + }, + { + .supply = "sata_vddr", + }, +}; + +/* 1.2V */ +struct regulator_consumer_supply tps65023_dcdc3_consumers[] = { + { + .supply = "sata_vdd", + }, + { + .supply = "usb_cvdd", + }, + { + .supply = "pll0_vdda", + }, + { + .supply = "pll1_vdda", + }, +}; + +/* 1.8V Aux LDO, not used */ +struct regulator_consumer_supply tps65023_ldo1_consumers[] = { + { + .supply = "1.8v_aux", + }, +}; + +/* FPGA VCC Aux (2.5 or 3.3) LDO */ +struct regulator_consumer_supply tps65023_ldo2_consumers[] = { + { + .supply = "vccaux", + }, +}; + +struct regulator_init_data tps65023_regulator_data[] = { + /* dcdc1 */ + { + .constraints = { + .min_uV = 1150000, + .max_uV = 1350000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc1_consumers), + .consumer_supplies = tps65023_dcdc1_consumers, + }, + /* dcdc2 */ + { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc2_consumers), + .consumer_supplies = tps65023_dcdc2_consumers, + }, + /* dcdc3 */ + { + .constraints = { + .min_uV = 1200000, + .max_uV = 1200000, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc3_consumers), + .consumer_supplies = tps65023_dcdc3_consumers, + }, + /* ldo1 */ + { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65023_ldo1_consumers), + .consumer_supplies = tps65023_ldo1_consumers, + }, + /* ldo2 */ + { + .constraints = { + .min_uV = 2500000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + .boot_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(tps65023_ldo2_consumers), + .consumer_supplies = tps65023_ldo2_consumers, + }, +}; + +static struct i2c_board_info __initdata mityomap_tps65023_info[] = { + { + I2C_BOARD_INFO("tps65023", 0x48), + .platform_data = &tps65023_regulator_data[0], + }, + { + I2C_BOARD_INFO("24c02", 0x50), + }, +}; + +static int __init pmic_tps65023_init(void) +{ + return i2c_register_board_info(1, mityomap_tps65023_info, + ARRAY_SIZE(mityomap_tps65023_info)); +} + /* * MityDSP-L138 includes a 256 MByte large-page NAND flash * (128K blocks). @@ -172,6 +309,14 @@ static void __init mityomapl138_init(void) davinci_serial_init(&mityomapl138_uart_config); + ret = da8xx_register_i2c(0, &mityomap_i2c_0_pdata); + if (ret) + pr_warning("i2c0 registration failed: %d\n", ret); + + ret = pmic_tps65023_init(); + if (ret) + pr_warning("TPS65023 PMIC init failed: %d\n", ret); + mityomapl138_setup_nand(); mityomapl138_config_emac(); From krunal.patil at einfochips.com Mon Sep 6 02:36:26 2010 From: krunal.patil at einfochips.com (Krunal Patil) Date: Mon, 6 Sep 2010 13:06:26 +0530 (IST) Subject: DM6467 AAC audio encoding process fails with -Os compiler flag. In-Reply-To: <1686118544.55484.1283758183043.JavaMail.root@ahm.einfochips.com> Message-ID: <1682614857.55500.1283758586813.JavaMail.root@ahm.einfochips.com> Hi All, These days I am working with DM6467 AAC codecs in which I am facing a strange issue. I have written a sample application for encoding. If I use -Os complier flag to within my makefile to compile the application the process call for encoding fails with error: -1 and extended error: 0x4008 . If I remove -Os flag from the application makefile everything works well. Well the solution is there that I should not use -Os flag :) but I want to figure out why this is the case. Can anyone tell me what can be the issue? Software Packages Used: - MVL 5.0 - dvsdk_2_00_00_22 - dm6467_dvsdk_combos_2_05 - Kernel 2.6.18 Thanks in advance! -- Regards, Krunal -------------- next part -------------- An HTML attachment was scrubbed... URL: From vm.rod25 at gmail.com Mon Sep 6 12:45:52 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Mon, 6 Sep 2010 12:45:52 -0500 Subject: [PATCH v3] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <871v9azy96.fsf@deeprootsystems.com> References: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> <87fwxs6n6b.fsf@deeprootsystems.com> <201009030118.10100.caglarakyuz@gmail.com> <871v9azy96.fsf@deeprootsystems.com> Message-ID: On Fri, Sep 3, 2010 at 9:40 AM, Kevin Hilman wrote: > Victor Rodriguez writes: > >> On Thu, Sep 2, 2010 at 5:18 PM, Victor Rodriguez wrote: >>> On Thu, Sep 2, 2010 at 5:18 PM, Caglar Akyuz wrote: >>>> On Thursday 02 September 2010 09:00:12 pm Kevin Hilman wrote: >>>>> Victor Rodriguez writes: >>>>> > This patch adds initial support for the Hawkboard-L138 system >>>>> > It is under the machine name "omapl138_hawkboard". >>>>> > This system is based on the da850 davinci CPU architecture. >>>>> > Information on these system may be found at http://www.hawkboard.org. >>>>> > Basic support for the console UART is included in this patch. >>>>> > Depends on Michael Williamson patches: >>>>> > http://alturl.com/hha7u and http://alturl.com/qy4cr >>>>> > >>>>> > Signed-off-by: Victor Rodriguez >>>>> > >>>>> > Changes since v2: >>>>> > 1) Correct number of characters per line in patch description. >>>>> > 2) Correct board description in Kconfig file >>>>> > 3) Correct da8xx_omapl_defconfig >>>>> > 4) Correct issue with CONFIG_SERIAL_8250_CONSOLE >>>>> > based on Michael Williamson patch http://alturl.com/hha7u >>>>> > 5) Correct issue with voltage regulator control >>>>> > based on Michael Williamson patch http://alturl.com/qy4cr >>>>> >>>>> [...] >>>>> >>>>> > +static __init void omapl138_hawk_init(void) >>>>> > +{ >>>>> > + >>>>> > + ? davinci_serial_init(&omapl138_hawk_uart_config); >>>>> > + >>>>> > + ? /* >>>>> > + ? ?* shut down uart 0 and 1; they are not used on the board and >>>>> > + ? ?* accessing them causes endless "too much work in irq53" messages >>>>> > + ? ?* with arago fs >>>>> > + ? ?*/ >>>>> > + ? __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >>>>> > + ? __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); >>>>> >>>>> I still dont' want to merge this until this issue is understood and >>>>> described in the changelog (or the code removed.) >>>>> >>>> >>>> Registering only 3rd uart(.enabled_uarts = 0x4) and removing these hacks >>>> works. >>>> >>>> However, existing user-space relies system console to be on ttyS2. Besides >>>> this hack also exists in board-da850-evm.c so file-systems prepared for EVM >>>> will not work on Hawkboard without modification. >>>> >>>> I think this is a da850 issue, not a Hawk one. Do you think Michael >>>> Williamson's explanation is good enough to go as comment above? >>> >>> Sorry I did not see Michael explanation when i was sending my message >>> but I think that is a good way to fix, how does Michael explain. >>> >>> >>> >>>> Best Regards, >>>> Caglar >>>> >>> >> >> I have one question even if we let just the third UART, what happen >> whit UART 0, if some one need to access to this UART, it is available >> in the hardware, Until I understand we need to enable both, but is >> just my opinion Hi > Michael suggested that UART0 was not hooked up in hardware either. I have checked in http://www.hawkboard.org/ and in the User Guide , page 18 and it specify that the UART 0 and 2 are enable in external pins 7,8,9 and 10 for UART 0 so in my opinion UART 0 and UART 2 should be available because they are hooked up in hardware, if it is ok i could send the v5 of the patch with UART0 and UART2, with a correct description of the shared pins with LAN Thanks VIctor Rodriguez > In any case, I'm OK with disabling one (or both) UARTs if they are not > hooked up in hardware. ?Just replace the comment about 'too much work in > irq...' with a descripion about shared pins and the need for them to be > disabled. > > As Sekhar suggested, ideally we would only register one UART, but > unfortunately, there is no way to have one UART registered as ttyS2, so > the best way to handle it is to register them all and disable the > unused/unconnected ones. > > I'm OK with this workaround, as long as it's clearly documented. > > If the same problem exists on the EVM, I suggest you separate out this > change from your hawkboard patch and add it as a 2nd patch that also > fixes the EVM. > > Kevin > From davem at davemloft.net Mon Sep 6 15:28:02 2010 From: davem at davemloft.net (David Miller) Date: Mon, 06 Sep 2010 13:28:02 -0700 (PDT) Subject: [PATCH v2 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C813C7F.5090602@ti.com> References: <1283465008-18606-1-git-send-email-cyril@ti.com> <87eida3fl9.fsf@deeprootsystems.com> <4C813C7F.5090602@ti.com> Message-ID: <20100906.132802.260095799.davem@davemloft.net> From: Cyril Chemparathy Date: Fri, 03 Sep 2010 14:20:47 -0400 > Hi Kevin, > > [...] >>> Although am3517 (omap) board support code has been updated as needed, >>> emac does not work on this platform. >> >> Just to clarify... did EMAC work on AM3517 before this series? > > No. It didn't work before this series. To get AM3517 EMAC working, the > driver needs another patch to enable the interface clock in addition to > the functional clock. Since this has dependencies on davinci board files and whatnot, why don't you merge this via the davinci tree and add my: Acked-by: David S. Miller Ok? From sugumar at ti.com Tue Sep 7 01:36:30 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Tue, 7 Sep 2010 12:06:30 +0530 Subject: [PATCH 1/2] davinci: Add generic PWM support for the PWM control Message-ID: <1283841390-27071-1-git-send-email-sugumar@ti.com> This patch adds generic PWM support where it maintains the list of PWM control devices that can be added or removed. The interface provides a list of functions that can be accessed by the PWM control driver module and the generic PWM driver. The PWM control driver module such as eCAP uses the interface to register and add itself to the list as a PWM control device. The generic PWM driver uses the interface to search for a PWM control device and if present, uses the device for PWM control. Signed-off-by: Sugumar Natarajan --- arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/davinci_pwm.c | 116 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 32 ++++++ 3 files changed, 151 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/davinci_pwm.c create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index a7a70d1..90ca821 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_SUSPEND) += pm.o sleep.o + +# Generic PWM control support +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o diff --git a/arch/arm/mach-davinci/davinci_pwm.c b/arch/arm/mach-davinci/davinci_pwm.c new file mode 100644 index 0000000..378f4f0 --- /dev/null +++ b/arch/arm/mach-davinci/davinci_pwm.c @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + unsigned int clock_freq; + unsigned int period_cycles; + unsigned int duty_cycle; + + if (pwm == NULL || pwm->pwm_config_device == NULL || period_ns == 0 || + duty_ns > period_ns) + return -EINVAL; + + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; + pwm->pwm_config_device(pwm, period_cycles, duty_cycle); + return 0; +} +EXPORT_SYMBOL(pwm_config); + +int pwm_enable(struct pwm_device *pwm) +{ + clk_enable(pwm->clk); + return 0; +} +EXPORT_SYMBOL(pwm_enable); + +void pwm_disable(struct pwm_device *pwm) +{ + clk_disable(pwm->clk); +} +EXPORT_SYMBOL(pwm_disable); + +static DEFINE_MUTEX(pwm_lock); +static LIST_HEAD(pwm_list); + +struct pwm_device *pwm_request(int pwm_id, const char *label) +{ + struct pwm_device *pwm; + int found = 0; + + mutex_lock(&pwm_lock); + + list_for_each_entry(pwm, &pwm_list, node) { + if (pwm->pwm_id == pwm_id) { + found = 1; + break; + } + } + + if (found) { + if (pwm->use_count == 0) { + pwm->use_count++; + pwm->label = label; + } else { + pwm = ERR_PTR(-EBUSY); + } + } else { + pwm = ERR_PTR(-ENOENT); + } + + mutex_unlock(&pwm_lock); + return pwm; +} +EXPORT_SYMBOL(pwm_request); + +void pwm_free(struct pwm_device *pwm) +{ + mutex_lock(&pwm_lock); + + if (pwm->use_count) { + pwm->use_count--; + pwm->label = NULL; + } else { + dev_warn(&pwm->pdev->dev, "PWM device already freed\n"); + } + + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_free); + +void add_pwm(struct pwm_device *pwm) +{ + mutex_lock(&pwm_lock); + list_add_tail(&pwm->node, &pwm_list); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(add_pwm); + +void remove_pwm(struct pwm_device *pwm) +{ + mutex_lock(&pwm_lock); + list_del(&pwm->node); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(remove_pwm); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h new file mode 100644 index 0000000..b89e823 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __DAVINCI_PWM_H +#define __DAVINCI_PWM_H + +struct pwm_device { + struct list_head node; + struct platform_device *pdev; + void (*pwm_config_device)(struct pwm_device *pwm, + unsigned int period, unsigned int dutycycle); + const char *label; + struct clk *clk; + unsigned int use_count; + unsigned int pwm_id; +}; + +void add_pwm(struct pwm_device *pwm); +void remove_pwm(struct pwm_device *pwm); + +#endif -- 1.5.6 From sugumar at ti.com Tue Sep 7 01:38:04 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Tue, 7 Sep 2010 12:08:04 +0530 Subject: [PATCH 2/2] DA850/OMAPL138: eCAP driver support for PWM signal generation Message-ID: <1283841484-27121-1-git-send-email-sugumar@ti.com> OMAPL138/DA850 contains three instances of eCAP module. Each eCAP module has one dedicated pin that can be used either in capture mode(input) or in PWM mode. For more information on eCAP module operation, please refer to the following url. http://focus.ti.com/lit/ug/sprufl2a/sprufl2a.pdf This patch adds eCAP driver support for PWM signal generation. Signed-off-by: Sugumar Natarajan --- arch/arm/mach-davinci/Kconfig | 7 + arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/ecap.c | 131 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 1 + 4 files changed, 142 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/ecap.c diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 9aca60c..3e821b4 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -40,6 +40,7 @@ config ARCH_DAVINCI_DA850 select CP_INTC select ARCH_DAVINCI_DA8XX select ARCH_HAS_CPUFREQ + select HAVE_PWM config ARCH_DAVINCI_DA8XX select CPU_ARM926T @@ -230,6 +231,12 @@ config DAVINCI_RESET_CLOCKS probably do not want this option enabled until your device drivers work properly. +config DAVINCI_ECAP_PWM + bool + depends on ARCH_DAVINCI_DA8XX + depends on HAVE_PWM + default y + endmenu endif diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 90ca821..90bd88e 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -42,3 +42,6 @@ obj-$(CONFIG_SUSPEND) += pm.o sleep.o # Generic PWM control support obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o + +# eCAP driver support for PWM +obj-$(CONFIG_DAVINCI_ECAP_PWM) += ecap.o diff --git a/arch/arm/mach-davinci/ecap.c b/arch/arm/mach-davinci/ecap.c new file mode 100644 index 0000000..7032009 --- /dev/null +++ b/arch/arm/mach-davinci/ecap.c @@ -0,0 +1,131 @@ +/* + * DA850/OMAP-L138 eCAP driver for PWM output generation + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CAPTURE_1_REG 0x8 +#define CAPTURE_2_REG 0xC +#define CAPTURE_3_REG 0x10 +#define CAPTURE_4_REG 0x14 +#define CAPTURE_CTRL2_REG 0x2A +#define PWM_CONFIG 0x290 + +/* + * ecap_config_pwm - configures the eCAP Module for the PWM output with given + * period and duty cycle. + * + * Maximum brightness is obtained when the duty cycle value is one greater than + * period ie duty cycle >= period + 1 + * + */ + +static void ecap_config_pwm(struct pwm_device *pwm, unsigned int period_cycles, + unsigned int duty_cycle) +{ + __raw_writew(PWM_CONFIG, pwm->mmio_base + CAPTURE_CTRL2_REG); + __raw_writel(period_cycles, pwm->mmio_base + CAPTURE_3_REG); + __raw_writel(duty_cycle + 1, pwm->mmio_base + CAPTURE_4_REG); +} + +static int __devinit ecap_probe(struct platform_device *pdev) +{ + struct pwm_device *pwm = NULL; + struct resource *r; + int ret = 0; + + pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); + if (pwm == NULL) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + pwm->clk = clk_get(&pdev->dev, "ecap"); + if (IS_ERR(pwm->clk)) { + ret = PTR_ERR(pwm->clk); + goto err_free; + } + + pwm->pwm_id = pdev->id; + pwm->pdev = pdev; + pwm->pwm_config_device = ecap_config_pwm; + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (r == NULL) { + dev_err(&pdev->dev, "no memory resource defined\n"); + ret = -ENODEV; + goto err_free_clk; + } + + pwm->mmio_base = ioremap(r->start, resource_size(r)); + if (pwm->mmio_base == NULL) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + ret = -ENODEV; + goto err_free_clk; + } + + clk_enable(pwm->clk); + add_pwm(pwm); + platform_set_drvdata(pdev, pwm); + return 0; + +err_free_clk: + clk_put(pwm->clk); +err_free: + kfree(pwm); + return ret; +} + +static int __devexit ecap_remove(struct platform_device *pdev) +{ + struct pwm_device *pwm; + + pwm = platform_get_drvdata(pdev); + remove_pwm(pwm); + iounmap(pwm->mmio_base); + clk_put(pwm->clk); + kfree(pwm); + return 0; +} + +static struct platform_driver ecap_driver = { + .driver = { + .name = "ecap", + .owner = THIS_MODULE, + }, + .probe = ecap_probe, + .remove = __devexit_p(ecap_remove), +}; + +static int __init ecap_init(void) +{ + return platform_driver_register(&ecap_driver); +} + +static void __exit ecap_exit(void) +{ + platform_driver_unregister(&ecap_driver); +} + +module_init(ecap_init); +module_exit(ecap_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h index b89e823..9f66ae7 100644 --- a/arch/arm/mach-davinci/include/mach/davinci_pwm.h +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -22,6 +22,7 @@ struct pwm_device { unsigned int period, unsigned int dutycycle); const char *label; struct clk *clk; + void __iomem *mmio_base; unsigned int use_count; unsigned int pwm_id; }; -- 1.5.6 From khasim at ti.com Tue Sep 7 09:02:07 2010 From: khasim at ti.com (Syed Mohammed, Khasim) Date: Tue, 7 Sep 2010 19:32:07 +0530 Subject: [PATCH] hawkboard v_2 References: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> <87y6bk9j2z.fsf@deeprootsystems.com> Message-ID: <0680EC522D0CC943BC586913CF3768C003C2018961@dbde02.ent.ti.com> > -----Original Message----- > From: Syed Mohammed, Khasim > Sent: Thursday, September 02, 2010 10:35 PM > To: 'Kevin Hilman'; Victor Rodriguez > Cc: davinci-linux-open-source at linux.davincidsp.com > Subject: RE: [PATCH] hawkboard v_2 > > Kevin, > > > -----Original Message----- > > From: davinci-linux-open-source-bounces+khasim=ti.com at linux.davincidsp.com > > [mailto:davinci-linux-open-source- > bounces+khasim=ti.com at linux.davincidsp.com] > > On Behalf Of Kevin Hilman > > Sent: Thursday, September 02, 2010 10:30 PM > > To: Victor Rodriguez > > Cc: davinci-linux-open-source at linux.davincidsp.com > > Subject: Re: [PATCH] hawkboard v_2 > > > > Victor Rodriguez writes: > > > > > Basic support for Hawkboard OMAPL138 just UART cominication is included > > > > > > Signed-off-by: Victor Rodriguez > > > > > > > [...] > > > > > +static __init void omapl138_hawk_init(void) > > > +{ > > > + > > > + davinci_serial_init(&omapl138_hawk_uart_config); > > > + > > > + /* > > > + * shut down uart 0 and 1; they are not used on the board and > > > + * accessing them causes endless "too much work in irq53" messages > > > + * with arago fs > > > + */ > > > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > > > + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); > > > > This hack/workaround needs to be removed and/or better described so we > > know *why* such a thing is needed. > > > > Khasim, do you know what the root cause is here? > I will have to look into this, I will get back to you in a day or two. > These lines were directly copied from da850 board file, I am still trying to figure out if this is true for hawk as well. Looks like some thing is not handled properly in driver that is causing this irq 53, we had similar issue in OMAP3 with irq33. I will have to discuss this with Sekhar, he is on vacation this week. Will keep you updated as soon as I get more info into this. For now can we put a big disclaimer on this (TBD) and move forward? - this is just a request. Regards, Khasim From vm.rod25 at gmail.com Tue Sep 7 09:35:07 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Tue, 7 Sep 2010 09:35:07 -0500 Subject: [PATCH] hawkboard v_2 In-Reply-To: <0680EC522D0CC943BC586913CF3768C003C2018961@dbde02.ent.ti.com> References: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> <87y6bk9j2z.fsf@deeprootsystems.com> <0680EC522D0CC943BC586913CF3768C003C2018961@dbde02.ent.ti.com> Message-ID: On Tue, Sep 7, 2010 at 9:02 AM, Syed Mohammed, Khasim wrote: > > >> -----Original Message----- >> From: Syed Mohammed, Khasim >> Sent: Thursday, September 02, 2010 10:35 PM >> To: 'Kevin Hilman'; Victor Rodriguez >> Cc: davinci-linux-open-source at linux.davincidsp.com >> Subject: RE: [PATCH] hawkboard v_2 >> >> Kevin, >> >> > -----Original Message----- >> > From: davinci-linux-open-source-bounces+khasim=ti.com at linux.davincidsp.com >> > [mailto:davinci-linux-open-source- >> bounces+khasim=ti.com at linux.davincidsp.com] >> > On Behalf Of Kevin Hilman >> > Sent: Thursday, September 02, 2010 10:30 PM >> > To: Victor Rodriguez >> > Cc: davinci-linux-open-source at linux.davincidsp.com >> > Subject: Re: [PATCH] hawkboard v_2 >> > >> > Victor Rodriguez writes: >> > >> > > Basic support for Hawkboard OMAPL138 just UART cominication is included >> > > >> > > Signed-off-by: Victor Rodriguez >> > > >> > >> > [...] >> > >> > > +static __init void omapl138_hawk_init(void) >> > > +{ >> > > + >> > > + davinci_serial_init(&omapl138_hawk_uart_config); >> > > + >> > > + /* >> > > + ?* shut down uart 0 and 1; they are not used on the board and >> > > + ?* accessing them causes endless "too much work in irq53" messages >> > > + ?* with arago fs >> > > + ?*/ >> > > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >> > > + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); >> > >> > This hack/workaround needs to be removed and/or better described so we >> > know *why* such a thing is needed. >> > >> > Khasim, do you know what the root cause is here? >> I will have to look into this, I will get back to you in a day or two. >> > These lines were directly copied from da850 board file, I am still trying to figure out if this is true for hawk as well. > > Looks like some thing is not handled properly in driver that is causing this irq 53, we had similar issue in OMAP3 with irq33. > > I will have to discuss this with Sekhar, he is on vacation this week. Will keep you updated as soon as I get more info into this. > > For now can we put a big disclaimer on this (TBD) and move forward? - this is just a request. > > Regards, > Khasim > I agree if Kevin is ok I could propose one more version of the patch and keep working in the other things to rebase like USB, MMC and so on Thanks Victor Rodriguez From benxuelan0402 at gmail.com Tue Sep 7 09:43:20 2010 From: benxuelan0402 at gmail.com (Jammy Dane) Date: Tue, 7 Sep 2010 22:43:20 +0800 Subject: If TVP5150 has industrial edition References: Message-ID: <201009072243151870639@gmail.com> Hi all, I want to know if TVP5150 has industrial edition, any one can help me? 2010-09-07 Jammy Dane -------------- next part -------------- An HTML attachment was scrubbed... URL: From khilman at deeprootsystems.com Tue Sep 7 10:22:14 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Tue, 07 Sep 2010 08:22:14 -0700 Subject: [PATCH v2 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <20100906.132802.260095799.davem@davemloft.net> (David Miller's message of "Mon, 06 Sep 2010 13:28:02 -0700 (PDT)") References: <1283465008-18606-1-git-send-email-cyril@ti.com> <87eida3fl9.fsf@deeprootsystems.com> <4C813C7F.5090602@ti.com> <20100906.132802.260095799.davem@davemloft.net> Message-ID: <87iq2hk28p.fsf@deeprootsystems.com> David Miller writes: > From: Cyril Chemparathy > Date: Fri, 03 Sep 2010 14:20:47 -0400 > >> Hi Kevin, >> >> [...] >>>> Although am3517 (omap) board support code has been updated as needed, >>>> emac does not work on this platform. >>> >>> Just to clarify... did EMAC work on AM3517 before this series? >> >> No. It didn't work before this series. To get AM3517 EMAC working, the >> driver needs another patch to enable the interface clock in addition to >> the functional clock. > > Since this has dependencies on davinci board files and whatnot, why don't > you merge this via the davinci tree and add my: > > Acked-by: David S. Miller > > Ok? OK, will do. Thanks, Kevin From khilman at deeprootsystems.com Tue Sep 7 10:23:43 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Tue, 07 Sep 2010 08:23:43 -0700 Subject: [PATCH v2 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <1283465008-18606-1-git-send-email-cyril@ti.com> (Cyril Chemparathy's message of "Thu, 2 Sep 2010 18:03:18 -0400") References: <1283465008-18606-1-git-send-email-cyril@ti.com> Message-ID: <87aantk268.fsf@deeprootsystems.com> Cyril Chemparathy writes: > Davinci's EMAC device has an in-built MDIO controller and a CPDMA engine. > These hardware modules are not restricted to EMAC device alone. For example, > CPSW3G (3-port gigabit ethernet switch) hardware uses these very same modules > internally. This patch series separates out EMAC's MDIO and CPDMA > functionality, allowing these individual pieces to be reused across TI > hardware. Tony, The AM3517 also uses this davinci EMAC driver and is modified by this series. With your ack, I'll merge the OMAP changes along with this series via the davinci tree. OK with you? Kevin From khilman at deeprootsystems.com Tue Sep 7 10:35:29 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Tue, 07 Sep 2010 08:35:29 -0700 Subject: [PATCH] hawkboard v_2 In-Reply-To: (Victor Rodriguez's message of "Tue, 7 Sep 2010 09:35:07 -0500") References: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> <87y6bk9j2z.fsf@deeprootsystems.com> <0680EC522D0CC943BC586913CF3768C003C2018961@dbde02.ent.ti.com> Message-ID: <8739tlk1mm.fsf@deeprootsystems.com> Victor Rodriguez writes: > On Tue, Sep 7, 2010 at 9:02 AM, Syed Mohammed, Khasim wrote: >> >> >>> -----Original Message----- >>> From: Syed Mohammed, Khasim >>> Sent: Thursday, September 02, 2010 10:35 PM >>> To: 'Kevin Hilman'; Victor Rodriguez >>> Cc: davinci-linux-open-source at linux.davincidsp.com >>> Subject: RE: [PATCH] hawkboard v_2 >>> >>> Kevin, >>> >>> > -----Original Message----- >>> > From: davinci-linux-open-source-bounces+khasim=ti.com at linux.davincidsp.com >>> > [mailto:davinci-linux-open-source- >>> bounces+khasim=ti.com at linux.davincidsp.com] >>> > On Behalf Of Kevin Hilman >>> > Sent: Thursday, September 02, 2010 10:30 PM >>> > To: Victor Rodriguez >>> > Cc: davinci-linux-open-source at linux.davincidsp.com >>> > Subject: Re: [PATCH] hawkboard v_2 >>> > >>> > Victor Rodriguez writes: >>> > >>> > > Basic support for Hawkboard OMAPL138 just UART cominication is included >>> > > >>> > > Signed-off-by: Victor Rodriguez >>> > > >>> > >>> > [...] >>> > >>> > > +static __init void omapl138_hawk_init(void) >>> > > +{ >>> > > + >>> > > + davinci_serial_init(&omapl138_hawk_uart_config); >>> > > + >>> > > + /* >>> > > + ?* shut down uart 0 and 1; they are not used on the board and >>> > > + ?* accessing them causes endless "too much work in irq53" messages >>> > > + ?* with arago fs >>> > > + ?*/ >>> > > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >>> > > + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); >>> > >>> > This hack/workaround needs to be removed and/or better described so we >>> > know *why* such a thing is needed. >>> > >>> > Khasim, do you know what the root cause is here? >>> I will have to look into this, I will get back to you in a day or two. >>> >> These lines were directly copied from da850 board file, I am still trying to figure out if this is true for hawk as well. >> >> Looks like some thing is not handled properly in driver that is causing this irq 53, we had similar issue in OMAP3 with irq33. >> >> I will have to discuss this with Sekhar, he is on vacation this week. Will keep you updated as soon as I get more info into this. >> >> For now can we put a big disclaimer on this (TBD) and move forward? - this is just a request. >> >> Regards, >> Khasim >> > > I agree if Kevin is ok I could propose one more version of the patch > and keep working in the other things to rebase like USB, MMC and so on Yes, that's OK. I hadn't noticed it came from the da850 EVM board file. What I'd like is for the da850 EVM board file to be cleaned up with a better description of the problem as well, but that can be done by TI (Sekhar?) as a separate patch. Kevin From khilman at deeprootsystems.com Tue Sep 7 10:39:23 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Tue, 07 Sep 2010 08:39:23 -0700 Subject: [PATCH] davinci: add idcode for tnetv107x rev 1.1/1.2 In-Reply-To: <1283544119-29194-1-git-send-email-cyril@ti.com> (Cyril Chemparathy's message of "Fri, 3 Sep 2010 16:01:59 -0400") References: <1283544119-29194-1-git-send-email-cyril@ti.com> Message-ID: <87wrqximvo.fsf@deeprootsystems.com> Cyril Chemparathy writes: > This patch adds an entry into the idcode table for tnetv107x silicon revision > 1.1 and 1.2 devices. > > Signed-off-by: Cyril Chemparathy Applying and queuing for 2.6.37 in davinci-next. Thanks, Kevin > --- > arch/arm/mach-davinci/tnetv107x.c | 9 ++++++++- > 1 files changed, 8 insertions(+), 1 deletions(-) > > diff --git a/arch/arm/mach-davinci/tnetv107x.c b/arch/arm/mach-davinci/tnetv107x.c > index 06d2ac9..daeae06 100644 > --- a/arch/arm/mach-davinci/tnetv107x.c > +++ b/arch/arm/mach-davinci/tnetv107x.c > @@ -581,7 +581,14 @@ static struct davinci_id ids[] = { > .part_no = 0xb8a1, > .manufacturer = 0x017, > .cpu_id = DAVINCI_CPU_ID_TNETV107X, > - .name = "tnetv107x rev1.0", > + .name = "tnetv107x rev 1.0", > + }, > + { > + .variant = 0x1, > + .part_no = 0xb8a1, > + .manufacturer = 0x017, > + .cpu_id = DAVINCI_CPU_ID_TNETV107X, > + .name = "tnetv107x rev 1.1/1.2", > }, > }; From khilman at deeprootsystems.com Tue Sep 7 10:39:43 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Tue, 07 Sep 2010 08:39:43 -0700 Subject: [PATCH v1] davinci: Add I2C0 devices to MityDSP-L138/MityARM-1808 platform In-Reply-To: <1283707779-23204-1-git-send-email-michael.williamson@criticallink.com> (Michael Williamson's message of "Sun, 5 Sep 2010 13:29:39 -0400") References: <1283707779-23204-1-git-send-email-michael.williamson@criticallink.com> Message-ID: <87r5h5imv4.fsf@deeprootsystems.com> Michael Williamson writes: > This patch adds the i2c0 bus and attached devices to the MityDSP-L138 > and MityARM-1808 davinci SoM. Included is a TPS65023 voltage regulator > needed for power management and a small 24c02 EPROM that contains > factory configuration data. > > Signed-off-by: Michael Williamson Applying and queing for 2.6.37 in davinci-next. Kevin > --- > This is based on 08f143b7cdbe9705f6856c2a63b6d3b14b5a8eee of davinci-linux > tree. > > Changes since v0: > 1. Misc formatting > > arch/arm/mach-davinci/board-mityomapl138.c | 145 ++++++++++++++++++++++++++++ > 1 files changed, 145 insertions(+), 0 deletions(-) > > diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c > index 7146916..84d5aff 100644 > --- a/arch/arm/mach-davinci/board-mityomapl138.c > +++ b/arch/arm/mach-davinci/board-mityomapl138.c > @@ -13,6 +13,8 @@ > #include > #include > #include > +#include > +#include > > #include > #include > @@ -25,6 +27,141 @@ > #define MITYOMAPL138_PHY_MASK 0x08 /* hardcoded for now */ > #define MITYOMAPL138_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ > > +static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = { > + .bus_freq = 100, /* kHz */ > + .bus_delay = 0, /* usec */ > +}; > + > +/* TPS65023 voltage regulator support */ > +/* 1.2V Core */ > +struct regulator_consumer_supply tps65023_dcdc1_consumers[] = { > + { > + .supply = "cvdd", > + }, > +}; > + > +/* 1.8V */ > +struct regulator_consumer_supply tps65023_dcdc2_consumers[] = { > + { > + .supply = "usb0_vdda18", > + }, > + { > + .supply = "usb1_vdda18", > + }, > + { > + .supply = "ddr_dvdd18", > + }, > + { > + .supply = "sata_vddr", > + }, > +}; > + > +/* 1.2V */ > +struct regulator_consumer_supply tps65023_dcdc3_consumers[] = { > + { > + .supply = "sata_vdd", > + }, > + { > + .supply = "usb_cvdd", > + }, > + { > + .supply = "pll0_vdda", > + }, > + { > + .supply = "pll1_vdda", > + }, > +}; > + > +/* 1.8V Aux LDO, not used */ > +struct regulator_consumer_supply tps65023_ldo1_consumers[] = { > + { > + .supply = "1.8v_aux", > + }, > +}; > + > +/* FPGA VCC Aux (2.5 or 3.3) LDO */ > +struct regulator_consumer_supply tps65023_ldo2_consumers[] = { > + { > + .supply = "vccaux", > + }, > +}; > + > +struct regulator_init_data tps65023_regulator_data[] = { > + /* dcdc1 */ > + { > + .constraints = { > + .min_uV = 1150000, > + .max_uV = 1350000, > + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | > + REGULATOR_CHANGE_STATUS, > + .boot_on = 1, > + }, > + .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc1_consumers), > + .consumer_supplies = tps65023_dcdc1_consumers, > + }, > + /* dcdc2 */ > + { > + .constraints = { > + .min_uV = 1800000, > + .max_uV = 1800000, > + .valid_ops_mask = REGULATOR_CHANGE_STATUS, > + .boot_on = 1, > + }, > + .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc2_consumers), > + .consumer_supplies = tps65023_dcdc2_consumers, > + }, > + /* dcdc3 */ > + { > + .constraints = { > + .min_uV = 1200000, > + .max_uV = 1200000, > + .valid_ops_mask = REGULATOR_CHANGE_STATUS, > + .boot_on = 1, > + }, > + .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc3_consumers), > + .consumer_supplies = tps65023_dcdc3_consumers, > + }, > + /* ldo1 */ > + { > + .constraints = { > + .min_uV = 1800000, > + .max_uV = 1800000, > + .valid_ops_mask = REGULATOR_CHANGE_STATUS, > + .boot_on = 1, > + }, > + .num_consumer_supplies = ARRAY_SIZE(tps65023_ldo1_consumers), > + .consumer_supplies = tps65023_ldo1_consumers, > + }, > + /* ldo2 */ > + { > + .constraints = { > + .min_uV = 2500000, > + .max_uV = 3300000, > + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | > + REGULATOR_CHANGE_STATUS, > + .boot_on = 1, > + }, > + .num_consumer_supplies = ARRAY_SIZE(tps65023_ldo2_consumers), > + .consumer_supplies = tps65023_ldo2_consumers, > + }, > +}; > + > +static struct i2c_board_info __initdata mityomap_tps65023_info[] = { > + { > + I2C_BOARD_INFO("tps65023", 0x48), > + .platform_data = &tps65023_regulator_data[0], > + }, > + { > + I2C_BOARD_INFO("24c02", 0x50), > + }, > +}; > + > +static int __init pmic_tps65023_init(void) > +{ > + return i2c_register_board_info(1, mityomap_tps65023_info, > + ARRAY_SIZE(mityomap_tps65023_info)); > +} > + > /* > * MityDSP-L138 includes a 256 MByte large-page NAND flash > * (128K blocks). > @@ -172,6 +309,14 @@ static void __init mityomapl138_init(void) > > davinci_serial_init(&mityomapl138_uart_config); > > + ret = da8xx_register_i2c(0, &mityomap_i2c_0_pdata); > + if (ret) > + pr_warning("i2c0 registration failed: %d\n", ret); > + > + ret = pmic_tps65023_init(); > + if (ret) > + pr_warning("TPS65023 PMIC init failed: %d\n", ret); > + > mityomapl138_setup_nand(); > > mityomapl138_config_emac(); From khilman at deeprootsystems.com Tue Sep 7 10:52:13 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Tue, 07 Sep 2010 08:52:13 -0700 Subject: [PATCH 1/2] davinci: Add generic PWM support for the PWM control In-Reply-To: <1283841390-27071-1-git-send-email-sugumar@ti.com> (Sugumar Natarajan's message of "Tue, 7 Sep 2010 12:06:30 +0530") References: <1283841390-27071-1-git-send-email-sugumar@ti.com> Message-ID: <87iq2himaa.fsf@deeprootsystems.com> Sugumar Natarajan writes: > This patch adds generic PWM support where it maintains the > list of PWM control devices that can be added or removed. > > The interface provides a list of functions that can be accessed > by the PWM control driver module and the generic PWM driver. > > The PWM control driver module such as eCAP uses the interface to > register and add itself to the list as a PWM control device. > The generic PWM driver uses the interface to search for a PWM control > device and if present, uses the device for PWM control. > > Signed-off-by: Sugumar Natarajan Looks OK, but I have a minor nit below... [...] > + > +void add_pwm(struct pwm_device *pwm) > +{ > + mutex_lock(&pwm_lock); > + list_add_tail(&pwm->node, &pwm_list); > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(add_pwm); > + > +void remove_pwm(struct pwm_device *pwm) > +{ > + mutex_lock(&pwm_lock); > + list_del(&pwm->node); > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(remove_pwm); These new functions should follow the naming convention of the rest of the API. Namely, pwm_add(), pwm_remove() Kevin From vm.rod25 at gmail.com Tue Sep 7 15:02:04 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Tue, 7 Sep 2010 15:02:04 -0500 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard Message-ID: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> This patch adds initial support for the Hawkboard-L138 system It is under the machine name "omapl138_hawkboard". This system is based on the da850 davinci CPU architecture. Information on these system may be found at http://www.hawkboard.org. Basic support for the UART console is included in this patch. Depends on Michael Williamson patches: http://alturl.com/hha7u and http://alturl.com/qy4cr Signed-off-by: Victor Rodriguez --- Changes since v4: 1) Registering UART 0 and UART 2, UART 1 is not available on hardware 2) Add Watch dog timer function Notes: This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 from Kernel development tree for TI DaVinci family of processors. This patch works with da8xx_omapl_defconfig plus this patch. Depens on patches http://alturl.com/hha7u and http://alturl.com/qy4cr arch/arm/configs/da8xx_omapl_defconfig | 1 + arch/arm/mach-davinci/Kconfig | 8 +++ arch/arm/mach-davinci/Makefile | 1 + arch/arm/mach-davinci/board-da850-hawk.c | 66 +++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/uncompress.h | 1 + 5 files changed, 77 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/board-da850-hawk.c diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig index 3952a4e..d7cb4b8 100644 --- a/arch/arm/configs/da8xx_omapl_defconfig +++ b/arch/arm/configs/da8xx_omapl_defconfig @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y CONFIG_ARCH_DAVINCI=y CONFIG_ARCH_DAVINCI_DA830=y CONFIG_ARCH_DAVINCI_DA850=y +CONFIG_MACH_OMAPL138_HAWKBOARD=y CONFIG_DAVINCI_RESET_CLOCKS=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 2bf03e9..985c261 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -185,6 +185,14 @@ config MACH_TNETV107X help Say Y here to select the TI TNETV107X Evaluation Module. +config MACH_OMAPL138_HAWKBOARD + bool "TI AM1808 / OMAPL138 Hawkboard platform" + depends on ARCH_DAVINCI_DA850 + help + Say Y here to select the TI AM1808 / OMAPL138 Hawkboard platform . + Information of this board may be found at + http://www.hawkboard.org/ + config DAVINCI_MUX bool "DAVINCI multiplexing support" depends on ARCH_DAVINCI diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 77a0f71..484071d 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-da850-hawk.o # Power Management obj-$(CONFIG_CPU_FREQ) += cpufreq.o diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c new file mode 100644 index 0000000..b71a6a7 --- /dev/null +++ b/arch/arm/mach-davinci/board-da850-hawk.c @@ -0,0 +1,66 @@ +/* + * Hawkboard.org based on TI's OMAP-L138 Platform + * + * Initial code: Syed Mohammed Khasim + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 +#include +#include +#include + +#include +#include + +#include +#include + +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { + .enabled_uarts = 0x7, +}; + +static __init void omapl138_hawk_init(void) +{ + int ret; + + davinci_serial_init(&omapl138_hawk_uart_config); + + /*shut down uart 1; It is not implemented in hardware */ + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); + + ret = da8xx_register_watchdog(); + if (ret) + pr_warning("evm_init: watchdog registration failed: %d\n", + ret); +} + +#ifdef CONFIG_SERIAL_8250_CONSOLE +static int __init omapl138_hawk_console_init(void) +{ + if (!machine_is_omapl138_hawkboard()) + return 0; + + return add_preferred_console("ttyS", 2, "115200"); +} +console_initcall(omapl138_hawk_console_init); +#endif + +static void __init omapl138_hawk_map_io(void) +{ + da850_init(); +} + +MACHINE_START(OMAPL138_HAWKBOARD, "OMAP-L138") + .phys_io = IO_PHYS, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, + .boot_params = (DA8XX_DDR_BASE + 0x100), + .map_io = omapl138_hawk_map_io, + .init_irq = cp_intc_init, + .timer = &davinci_timer, + .init_machine = omapl138_hawk_init, +MACHINE_END diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h index 15a6192..640f834 100644 --- a/arch/arm/mach-davinci/include/mach/uncompress.h +++ b/arch/arm/mach-davinci/include/mach/uncompress.h @@ -88,6 +88,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) /* DA8xx boards */ DEBUG_LL_DA8XX(davinci_da830_evm, 2); DEBUG_LL_DA8XX(davinci_da850_evm, 2); + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); /* TNETV107x boards */ DEBUG_LL_TNETV107X(tnetv107x, 1); -- 1.6.0.5 From cyril at ti.com Tue Sep 7 15:25:32 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 7 Sep 2010 16:25:32 -0400 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse Message-ID: <1283891142-15522-1-git-send-email-cyril@ti.com> Davinci's EMAC device has an in-built MDIO controller and a CPDMA engine. These hardware modules are not restricted to EMAC device alone. For example, CPSW3G (3-port gigabit ethernet switch) hardware uses these very same modules internally. This patch series separates out EMAC's MDIO and CPDMA functionality, allowing these individual pieces to be reused across TI hardware. This patch series has been broadly organized as follows: MDIO: - Add new functionality netdev: separate out davinci mdio controller code - Hookup new functionality davinci: add mdio platform devices omap: add mdio platform devices netdev: switch davinci emac to new mdio driver - Cleanup left over cruft davinci: cleanup unused davinci mdio arch code omap: cleanup unused davinci mdio arch code netdev: cleanup unused davinci mdio emac code CPDMA: - Add new functionality netdev: separate out davinci cpdma controller code - Hookup new functionality netdev: switch davinci emac to new cpdma layer - Cleanup left over cruft netdev: cleanup unused davinci emac cpdma code This series has been tested on dm365 and tnetv107x (with additional cpsw patches) hardware. Although am3517 (omap) board support code has been updated as needed, emac does not work on this platform. Changes from v1: 1. Fixed memory leak in cpdma_chan_create() failure case 2. Included new omap patches for am3517, avoids build breakage Changes from v2: 1. Updated series to include mityomapl138 board 2. Minor white-space fixes Cyril Chemparathy (10): net: davinci_emac: separate out davinci mdio davinci: add mdio platform devices omap: add mdio platform devices net: davinci_emac: switch to new mdio davinci: cleanup unused davinci mdio arch code omap: cleanup unused davinci mdio arch code net: davinci_emac: cleanup unused mdio emac code net: davinci_emac: separate out cpdma code net: davinci_emac: switch to new cpdma layer net: davinci_emac: cleanup unused cpdma code arch/arm/mach-davinci/board-da830-evm.c | 5 - arch/arm/mach-davinci/board-da850-evm.c | 6 - arch/arm/mach-davinci/board-dm365-evm.c | 7 - arch/arm/mach-davinci/board-dm644x-evm.c | 7 - arch/arm/mach-davinci/board-dm646x-evm.c | 8 - arch/arm/mach-davinci/board-mityomapl138.c | 7 - arch/arm/mach-davinci/board-neuros-osd2.c | 7 - arch/arm/mach-davinci/board-sffsdr.c | 7 - arch/arm/mach-davinci/devices-da8xx.c | 31 +- arch/arm/mach-davinci/dm365.c | 23 +- arch/arm/mach-davinci/dm644x.c | 23 +- arch/arm/mach-davinci/dm646x.c | 22 +- arch/arm/mach-davinci/include/mach/dm365.h | 2 +- arch/arm/mach-davinci/include/mach/dm644x.h | 2 +- arch/arm/mach-davinci/include/mach/dm646x.h | 2 +- arch/arm/mach-omap2/board-am3517evm.c | 31 +- drivers/net/Kconfig | 21 + drivers/net/Makefile | 2 + drivers/net/davinci_cpdma.c | 837 +++++++++++++++++ drivers/net/davinci_cpdma.h | 105 +++ drivers/net/davinci_emac.c | 1325 ++++----------------------- drivers/net/davinci_mdio.c | 386 ++++++++ include/linux/davinci_emac.h | 8 +- 23 files changed, 1635 insertions(+), 1239 deletions(-) create mode 100644 drivers/net/davinci_cpdma.c create mode 100644 drivers/net/davinci_cpdma.h create mode 100644 drivers/net/davinci_mdio.c From cyril at ti.com Tue Sep 7 15:25:38 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 7 Sep 2010 16:25:38 -0400 Subject: [PATCH v3 06/10] omap: cleanup unused davinci mdio arch code In-Reply-To: <1283891142-15522-1-git-send-email-cyril@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> Message-ID: <1283891142-15522-7-git-send-email-cyril@ti.com> This patch removes davinci architecture code that has now been rendered useless by the previous patches in the MDIO separation series. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller --- arch/arm/mach-omap2/board-am3517evm.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 5dd1b73..5225df6 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -39,7 +39,6 @@ #include "mux.h" -#define AM35XX_EVM_PHY_MASK (0xF) #define AM35XX_EVM_MDIO_FREQUENCY (1000000) static struct mdio_platform_data am3517_evm_mdio_pdata = { @@ -64,8 +63,6 @@ static struct platform_device am3517_mdio_device = { }; static struct emac_platform_data am3517_evm_emac_pdata = { - .phy_mask = AM35XX_EVM_PHY_MASK, - .mdio_max_freq = AM35XX_EVM_MDIO_FREQUENCY, .rmii_en = 1, }; @@ -135,7 +132,6 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata) pdata->ctrl_reg_offset = AM35XX_EMAC_CNTRL_OFFSET; pdata->ctrl_mod_reg_offset = AM35XX_EMAC_CNTRL_MOD_OFFSET; pdata->ctrl_ram_offset = AM35XX_EMAC_CNTRL_RAM_OFFSET; - pdata->mdio_reg_offset = AM35XX_EMAC_MDIO_OFFSET; pdata->ctrl_ram_size = AM35XX_EMAC_CNTRL_RAM_SIZE; pdata->version = EMAC_VERSION_2; pdata->hw_ram_addr = AM35XX_EMAC_HW_RAM_ADDR; -- 1.7.0.4 From cyril at ti.com Tue Sep 7 15:25:35 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 7 Sep 2010 16:25:35 -0400 Subject: [PATCH v3 03/10] omap: add mdio platform devices In-Reply-To: <1283891142-15522-1-git-send-email-cyril@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> Message-ID: <1283891142-15522-4-git-send-email-cyril@ti.com> This patch adds mdio platform devices on SoCs that have the necessary hardware. Clock lookup entries (aliases) have also been added, so that the MDIO and EMAC drivers can independently enable/disable a shared underlying clock. Further, the EMAC MMR region has been split down into separate MDIO and EMAC regions. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller --- arch/arm/mach-omap2/board-am3517evm.c | 27 ++++++++++++++++++++++++++- 1 files changed, 26 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 4d0f585..5dd1b73 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,27 @@ #define AM35XX_EVM_PHY_MASK (0xF) #define AM35XX_EVM_MDIO_FREQUENCY (1000000) +static struct mdio_platform_data am3517_evm_mdio_pdata = { + .bus_freq = AM35XX_EVM_MDIO_FREQUENCY, +}; + +static struct resource am3517_mdio_resources[] = { + { + .start = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET, + .end = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET + + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device am3517_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(am3517_mdio_resources), + .resource = am3517_mdio_resources, + .dev.platform_data = &am3517_evm_mdio_pdata, +}; + static struct emac_platform_data am3517_evm_emac_pdata = { .phy_mask = AM35XX_EVM_PHY_MASK, .mdio_max_freq = AM35XX_EVM_MDIO_FREQUENCY, @@ -50,7 +72,7 @@ static struct emac_platform_data am3517_evm_emac_pdata = { static struct resource am3517_emac_resources[] = { { .start = AM35XX_IPSS_EMAC_BASE, - .end = AM35XX_IPSS_EMAC_BASE + 0x3FFFF, + .end = AM35XX_IPSS_EMAC_BASE + 0x2FFFF, .flags = IORESOURCE_MEM, }, { @@ -121,6 +143,9 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata) pdata->interrupt_disable = am3517_disable_ethernet_int; am3517_emac_device.dev.platform_data = pdata; platform_device_register(&am3517_emac_device); + platform_device_register(&am3517_mdio_device); + clk_add_alias(NULL, dev_name(&am3517_mdio_device.dev), + NULL, &am3517_emac_device.dev); regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); regval = regval & (~(AM35XX_CPGMACSS_SW_RST)); -- 1.7.0.4 From cyril at ti.com Tue Sep 7 15:25:34 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 7 Sep 2010 16:25:34 -0400 Subject: [PATCH v3 02/10] davinci: add mdio platform devices In-Reply-To: <1283891142-15522-1-git-send-email-cyril@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> Message-ID: <1283891142-15522-3-git-send-email-cyril@ti.com> This patch adds mdio platform devices on SoCs that have the necessary hardware. Clock lookup entries (aliases) have also been added, so that the MDIO and EMAC drivers can independently enable/disable a shared underlying clock. Further, the EMAC MMR region has been split down into separate MDIO and EMAC regions. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller --- arch/arm/mach-davinci/devices-da8xx.c | 29 +++++++++++++++++++++++++- arch/arm/mach-davinci/dm365.c | 22 +++++++++++++++++++- arch/arm/mach-davinci/dm644x.c | 22 +++++++++++++++++++- arch/arm/mach-davinci/dm646x.c | 21 ++++++++++++++++++- arch/arm/mach-davinci/include/mach/dm365.h | 1 + arch/arm/mach-davinci/include/mach/dm644x.h | 1 + arch/arm/mach-davinci/include/mach/dm646x.h | 1 + 7 files changed, 92 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index caeb7f4..9039221 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -352,7 +352,7 @@ int __init da8xx_register_watchdog(void) static struct resource da8xx_emac_resources[] = { { .start = DA8XX_EMAC_CPPI_PORT_BASE, - .end = DA8XX_EMAC_CPPI_PORT_BASE + 0x5000 - 1, + .end = DA8XX_EMAC_CPPI_PORT_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -396,9 +396,34 @@ static struct platform_device da8xx_emac_device = { .resource = da8xx_emac_resources, }; +static struct resource da8xx_mdio_resources[] = { + { + .start = DA8XX_EMAC_MDIO_BASE, + .end = DA8XX_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device da8xx_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(da8xx_mdio_resources), + .resource = da8xx_mdio_resources, +}; + int __init da8xx_register_emac(void) { - return platform_device_register(&da8xx_emac_device); + int ret; + + ret = platform_device_register(&da8xx_mdio_device); + if (ret < 0) + return ret; + ret = platform_device_register(&da8xx_emac_device); + if (ret < 0) + return ret; + ret = clk_add_alias(NULL, dev_name(&da8xx_mdio_device.dev), + NULL, &da8xx_emac_device.dev); + return ret; } static struct resource da830_mcasp1_resources[] = { diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 7781e35..0add1ca 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -699,7 +699,7 @@ static struct emac_platform_data dm365_emac_pdata = { static struct resource dm365_emac_resources[] = { { .start = DM365_EMAC_BASE, - .end = DM365_EMAC_BASE + 0x47ff, + .end = DM365_EMAC_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -734,6 +734,21 @@ static struct platform_device dm365_emac_device = { .resource = dm365_emac_resources, }; +static struct resource dm365_mdio_resources[] = { + { + .start = DM365_EMAC_MDIO_BASE, + .end = DM365_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device dm365_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(dm365_mdio_resources), + .resource = dm365_mdio_resources, +}; + static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = { [IRQ_VDINT0] = 2, [IRQ_VDINT1] = 6, @@ -1219,7 +1234,12 @@ static int __init dm365_init_devices(void) davinci_cfg_reg(DM365_INT_EDMA_CC); platform_device_register(&dm365_edma_device); + + platform_device_register(&dm365_mdio_device); platform_device_register(&dm365_emac_device); + clk_add_alias(NULL, dev_name(&dm365_mdio_device.dev), + NULL, &dm365_emac_device.dev); + /* Add isif clock alias */ clk_add_alias("master", dm365_isif_dev.name, "vpss_master", NULL); platform_device_register(&dm365_vpss_device); diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 5e5b0a7..22166a5 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -330,7 +330,7 @@ static struct emac_platform_data dm644x_emac_pdata = { static struct resource dm644x_emac_resources[] = { { .start = DM644X_EMAC_BASE, - .end = DM644X_EMAC_BASE + 0x47ff, + .end = DM644X_EMAC_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -350,6 +350,21 @@ static struct platform_device dm644x_emac_device = { .resource = dm644x_emac_resources, }; +static struct resource dm644x_mdio_resources[] = { + { + .start = DM644X_EMAC_MDIO_BASE, + .end = DM644X_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device dm644x_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(dm644x_mdio_resources), + .resource = dm644x_mdio_resources, +}; + /* * Device specific mux setup * @@ -776,7 +791,12 @@ static int __init dm644x_init_devices(void) clk_add_alias("master", dm644x_ccdc_dev.name, "vpss_master", NULL); clk_add_alias("slave", dm644x_ccdc_dev.name, "vpss_slave", NULL); platform_device_register(&dm644x_edma_device); + + platform_device_register(&dm644x_mdio_device); platform_device_register(&dm644x_emac_device); + clk_add_alias(NULL, dev_name(&dm644x_mdio_device.dev), + NULL, &dm644x_emac_device.dev); + platform_device_register(&dm644x_vpss_device); platform_device_register(&dm644x_ccdc_dev); platform_device_register(&vpfe_capture_dev); diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 26e8a9c..3d636b2 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -366,7 +366,7 @@ static struct emac_platform_data dm646x_emac_pdata = { static struct resource dm646x_emac_resources[] = { { .start = DM646X_EMAC_BASE, - .end = DM646X_EMAC_BASE + 0x47ff, + .end = DM646X_EMAC_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -401,6 +401,21 @@ static struct platform_device dm646x_emac_device = { .resource = dm646x_emac_resources, }; +static struct resource dm646x_mdio_resources[] = { + { + .start = DM646X_EMAC_MDIO_BASE, + .end = DM646X_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device dm646x_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(dm646x_mdio_resources), + .resource = dm646x_mdio_resources, +}; + /* * Device specific mux setup * @@ -896,7 +911,11 @@ static int __init dm646x_init_devices(void) if (!cpu_is_davinci_dm646x()) return 0; + platform_device_register(&dm646x_mdio_device); platform_device_register(&dm646x_emac_device); + clk_add_alias(NULL, dev_name(&dm646x_mdio_device.dev), + NULL, &dm646x_emac_device.dev); + return 0; } postcore_initcall(dm646x_init_devices); diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h index ea5df3b..dbb5052 100644 --- a/arch/arm/mach-davinci/include/mach/dm365.h +++ b/arch/arm/mach-davinci/include/mach/dm365.h @@ -21,6 +21,7 @@ #include #define DM365_EMAC_BASE (0x01D07000) +#define DM365_EMAC_MDIO_BASE (DM365_EMAC_BASE + 0x4000) #define DM365_EMAC_CNTRL_OFFSET (0x0000) #define DM365_EMAC_CNTRL_MOD_OFFSET (0x3000) #define DM365_EMAC_CNTRL_RAM_OFFSET (0x1000) diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h index 6fca568..5159117 100644 --- a/arch/arm/mach-davinci/include/mach/dm644x.h +++ b/arch/arm/mach-davinci/include/mach/dm644x.h @@ -28,6 +28,7 @@ #include #define DM644X_EMAC_BASE (0x01C80000) +#define DM644X_EMAC_MDIO_BASE (DM644X_EMAC_BASE + 0x4000) #define DM644X_EMAC_CNTRL_OFFSET (0x0000) #define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000) diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h index 0a27ee9..1c4dca9 100644 --- a/arch/arm/mach-davinci/include/mach/dm646x.h +++ b/arch/arm/mach-davinci/include/mach/dm646x.h @@ -19,6 +19,7 @@ #include #define DM646X_EMAC_BASE (0x01C80000) +#define DM646X_EMAC_MDIO_BASE (DM646X_EMAC_BASE + 0x4000) #define DM646X_EMAC_CNTRL_OFFSET (0x0000) #define DM646X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM646X_EMAC_CNTRL_RAM_OFFSET (0x2000) -- 1.7.0.4 From cyril at ti.com Tue Sep 7 15:25:33 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 7 Sep 2010 16:25:33 -0400 Subject: [PATCH v3 01/10] net: davinci_emac: separate out davinci mdio In-Reply-To: <1283891142-15522-1-git-send-email-cyril@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> Message-ID: <1283891142-15522-2-git-send-email-cyril@ti.com> Davinci's MDIO controller is present on other TI devices, without an accompanying EMAC. For example, on tnetv107x, the same MDIO module is used in conjunction with a 3-port switch hardware. By separating the MDIO controller code into its own platform driver, this patch allows common logic to be reused on such platforms. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller --- drivers/net/Kconfig | 10 + drivers/net/Makefile | 1 + drivers/net/davinci_mdio.c | 386 ++++++++++++++++++++++++++++++++++++++++++ include/linux/davinci_emac.h | 4 + 4 files changed, 401 insertions(+), 0 deletions(-) create mode 100644 drivers/net/davinci_mdio.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2cc81a5..c5c86e0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -958,6 +958,16 @@ config TI_DAVINCI_EMAC To compile this driver as a module, choose M here: the module will be called davinci_emac_driver. This is recommended. +config TI_DAVINCI_MDIO + tristate "TI DaVinci MDIO Support" + depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + select PHYLIB + help + This driver supports TI's DaVinci MDIO module. + + To compile this driver as a module, choose M here: the module + will be called davinci_mdio. This is recommended. + config DM9000 tristate "DM9000 support" depends on ARM || BLACKFIN || MIPS diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 3e8f150..d38a7ab 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_MDIO) += mdio.o obj-$(CONFIG_PHYLIB) += phy/ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o +obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_E1000E) += e1000e/ diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c new file mode 100644 index 0000000..d34a53a --- /dev/null +++ b/drivers/net/davinci_mdio.c @@ -0,0 +1,386 @@ +/* + * DaVinci MDIO Module driver + * + * Copyright (C) 2010 Texas Instruments. + * + * Shamelessly ripped out of davinci_emac.c, original copyrights follow: + * + * Copyright (C) 2009 Texas Instruments. + * + * --------------------------------------------------------------------------- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * --------------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PHY_REG_MASK 0x1f +#define PHY_ID_MASK 0x1f + +#define DEF_OUT_FREQ 2200000 /* 2.2 MHz */ + +struct davinci_mdio_regs { + u32 version; + u32 control; +#define CONTROL_IDLE BIT(31) +#define CONTROL_ENABLE BIT(30) +#define CONTROL_MAX_DIV (0xff) + + u32 alive; + u32 link; + u32 linkintraw; + u32 linkintmasked; + u32 __reserved_0[2]; + u32 userintraw; + u32 userintmasked; + u32 userintmaskset; + u32 userintmaskclr; + u32 __reserved_1[20]; + + struct { + u32 access; +#define USERACCESS_GO BIT(31) +#define USERACCESS_WRITE BIT(30) +#define USERACCESS_ACK BIT(29) +#define USERACCESS_READ (0) +#define USERACCESS_DATA (0xffff) + + u32 physel; + } user[0]; +}; + +struct mdio_platform_data default_pdata = { + .bus_freq = DEF_OUT_FREQ, +}; + +struct davinci_mdio_data { + struct mdio_platform_data pdata; + struct davinci_mdio_regs __iomem *regs; + spinlock_t lock; + struct clk *clk; + struct device *dev; + struct mii_bus *bus; + bool suspended; +}; + +/* wait until hardware is ready for another user access */ +static inline u32 wait_for_user_access(struct davinci_mdio_data *data) +{ + struct davinci_mdio_regs __iomem *regs = data->regs; + u32 reg; + + while ((reg = __raw_readl(®s->user[0].access)) & USERACCESS_GO) + ; + + return reg; +} + +/* wait until hardware state machine is idle */ +static inline void wait_for_idle(struct davinci_mdio_data *data) +{ + struct davinci_mdio_regs __iomem *regs = data->regs; + + while ((__raw_readl(®s->control) & CONTROL_IDLE) == 0) + ; +} + +static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg) +{ + struct davinci_mdio_data *data = bus->priv; + u32 reg; + + if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) + return -EINVAL; + + spin_lock(&data->lock); + + if (data->suspended) { + spin_unlock(&data->lock); + return -ENODEV; + } + + wait_for_user_access(data); + reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) | + (phy_id << 16)); + __raw_writel(reg, &data->regs->user[0].access); + reg = wait_for_user_access(data); + spin_unlock(&data->lock); + + return (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO; +} + +static int davinci_mdio_write(struct mii_bus *bus, int phy_id, + int phy_reg, u16 phy_data) +{ + struct davinci_mdio_data *data = bus->priv; + u32 reg; + + if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) + return -EINVAL; + + spin_lock(&data->lock); + + if (data->suspended) { + spin_unlock(&data->lock); + return -ENODEV; + } + + wait_for_user_access(data); + reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) | + (phy_id << 16) | (phy_data & USERACCESS_DATA)); + __raw_writel(reg, &data->regs->user[0].access); + wait_for_user_access(data); + spin_unlock(&data->lock); + + return 0; +} + +static int __devinit davinci_mdio_probe(struct platform_device *pdev) +{ + struct mdio_platform_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct davinci_mdio_data *data; + struct resource *res; + u32 mdio_in_freq, mdio_out_freq, div, phy_mask, ver; + struct phy_device *phy; + int ret, addr; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + dev_err(dev, "failed to alloc device data\n"); + return -ENOMEM; + } + + data->pdata = pdata ? (*pdata) : default_pdata; + + data->bus = mdiobus_alloc(); + if (!data->bus) { + dev_err(dev, "failed to alloc mii bus\n"); + ret = -ENOMEM; + goto bail_out; + } + + data->bus->name = dev_name(dev); + data->bus->read = davinci_mdio_read, + data->bus->write = davinci_mdio_write, + data->bus->parent = dev; + data->bus->priv = data; + snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); + + data->clk = clk_get(dev, NULL); + if (IS_ERR(data->clk)) { + data->clk = NULL; + dev_err(dev, "failed to get device clock\n"); + ret = PTR_ERR(data->clk); + goto bail_out; + } + + clk_enable(data->clk); + + dev_set_drvdata(dev, data); + data->dev = dev; + spin_lock_init(&data->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "could not find register map resource\n"); + ret = -ENOENT; + goto bail_out; + } + + res = devm_request_mem_region(dev, res->start, resource_size(res), + dev_name(dev)); + if (!res) { + dev_err(dev, "could not allocate register map resource\n"); + ret = -ENXIO; + goto bail_out; + } + + data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); + if (!data->regs) { + dev_err(dev, "could not map mdio registers\n"); + ret = -ENOMEM; + goto bail_out; + } + + mdio_in_freq = clk_get_rate(data->clk); + div = (mdio_in_freq / data->pdata.bus_freq) - 1; + if (div > CONTROL_MAX_DIV) + div = CONTROL_MAX_DIV; + mdio_out_freq = mdio_in_freq / (div + 1); + + /* set enable and clock divider */ + __raw_writel(div | CONTROL_ENABLE, &data->regs->control); + + /* + * wait for scan logic to settle: + * the scan time consists of (a) a large fixed component, and (b) a + * small component that varies with the mii bus frequency. These + * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x + * silicon. Since the effect of (b) was found to be largely + * negligible, we keep things simple here. + */ + mdelay(1); + + /* dump hardware version info */ + ver = __raw_readl(&data->regs->version); + dev_info(dev, "davinci mdio revision %d.%d\n", + (ver >> 8) & 0xff, ver & 0xff); + + /* get phy mask from the alive register */ + phy_mask = __raw_readl(&data->regs->alive); + if (phy_mask) { + /* restrict mdio bus to live phys only */ + dev_info(dev, "detected phy mask %x\n", ~phy_mask); + phy_mask = ~phy_mask; + } else { + /* desperately scan all phys */ + dev_warn(dev, "failed to detect live phys, scanning all\n"); + phy_mask = 0; + } + data->bus->phy_mask = phy_mask; + + /* register the mii bus */ + ret = mdiobus_register(data->bus); + if (ret) + goto bail_out; + + /* scan and dump the bus */ + for (addr = 0; addr < PHY_MAX_ADDR; addr++) { + phy = data->bus->phy_map[addr]; + if (phy) { + dev_info(dev, "phy[%d]: device %s, driver %s\n", + phy->addr, dev_name(&phy->dev), + phy->drv ? phy->drv->name : "unknown"); + } + } + + return 0; + +bail_out: + if (data->bus) + mdiobus_free(data->bus); + + if (data->clk) { + clk_disable(data->clk); + clk_put(data->clk); + } + + kfree(data); + + return ret; +} + +static int __devexit davinci_mdio_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct davinci_mdio_data *data = dev_get_drvdata(dev); + + if (data->bus) + mdiobus_free(data->bus); + + if (data->clk) { + clk_disable(data->clk); + clk_put(data->clk); + } + + dev_set_drvdata(dev, NULL); + + kfree(data); + + return 0; +} + +static int davinci_mdio_suspend(struct device *dev) +{ + struct davinci_mdio_data *data = dev_get_drvdata(dev); + u32 ctrl; + + spin_lock(&data->lock); + + /* shutdown the scan state machine */ + ctrl = __raw_readl(&data->regs->control); + ctrl &= ~CONTROL_ENABLE; + __raw_writel(ctrl, &data->regs->control); + wait_for_idle(data); + + if (data->clk) + clk_disable(data->clk); + + data->suspended = true; + spin_unlock(&data->lock); + + return 0; +} + +static int davinci_mdio_resume(struct device *dev) +{ + struct davinci_mdio_data *data = dev_get_drvdata(dev); + u32 ctrl; + + spin_lock(&data->lock); + if (data->clk) + clk_enable(data->clk); + + /* restart the scan state machine */ + ctrl = __raw_readl(&data->regs->control); + ctrl |= CONTROL_ENABLE; + __raw_writel(ctrl, &data->regs->control); + + data->suspended = false; + spin_unlock(&data->lock); + + return 0; +} + +static const struct dev_pm_ops davinci_mdio_pm_ops = { + .suspend = davinci_mdio_suspend, + .resume = davinci_mdio_resume, +}; + +static struct platform_driver davinci_mdio_driver = { + .driver = { + .name = "davinci_mdio", + .owner = THIS_MODULE, + .pm = &davinci_mdio_pm_ops, + }, + .probe = davinci_mdio_probe, + .remove = __devexit_p(davinci_mdio_remove), +}; + +static int __init davinci_mdio_init(void) +{ + return platform_driver_register(&davinci_mdio_driver); +} +device_initcall(davinci_mdio_init); + +static void __exit davinci_mdio_exit(void) +{ + platform_driver_unregister(&davinci_mdio_driver); +} +module_exit(davinci_mdio_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("DaVinci MDIO driver"); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index 7c930db..a04fd8c 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -14,6 +14,10 @@ #include #include +struct mdio_platform_data { + unsigned long bus_freq; +}; + struct emac_platform_data { char mac_addr[ETH_ALEN]; u32 ctrl_reg_offset; -- 1.7.0.4 From cyril at ti.com Tue Sep 7 15:25:37 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 7 Sep 2010 16:25:37 -0400 Subject: [PATCH v3 05/10] davinci: cleanup unused davinci mdio arch code In-Reply-To: <1283891142-15522-1-git-send-email-cyril@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> Message-ID: <1283891142-15522-6-git-send-email-cyril@ti.com> This patch removes davinci architecture code that has now been rendered useless by the previous patches in the MDIO separation series. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/board-da830-evm.c | 5 ----- arch/arm/mach-davinci/board-da850-evm.c | 6 ------ arch/arm/mach-davinci/board-dm365-evm.c | 7 ------- arch/arm/mach-davinci/board-dm644x-evm.c | 7 ------- arch/arm/mach-davinci/board-dm646x-evm.c | 8 -------- arch/arm/mach-davinci/board-mityomapl138.c | 7 ------- arch/arm/mach-davinci/board-neuros-osd2.c | 7 ------- arch/arm/mach-davinci/board-sffsdr.c | 7 ------- arch/arm/mach-davinci/devices-da8xx.c | 2 -- arch/arm/mach-davinci/dm365.c | 1 - arch/arm/mach-davinci/dm644x.c | 1 - arch/arm/mach-davinci/dm646x.c | 1 - arch/arm/mach-davinci/include/mach/dm365.h | 1 - arch/arm/mach-davinci/include/mach/dm644x.h | 1 - arch/arm/mach-davinci/include/mach/dm646x.h | 1 - 15 files changed, 0 insertions(+), 62 deletions(-) diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index ef1ab0b..2613324 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -31,9 +31,6 @@ #include #include -#define DA830_EVM_PHY_MASK 0x0 -#define DA830_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ - /* * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4]. */ @@ -558,8 +555,6 @@ static __init void da830_evm_init(void) da830_evm_usb_init(); - soc_info->emac_pdata->phy_mask = DA830_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DA830_EVM_MDIO_FREQUENCY; soc_info->emac_pdata->rmii_en = 1; ret = davinci_cfg_reg_list(da830_cpgmac_pins); diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index ac2297c..9d4dfcb 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -38,9 +38,6 @@ #include #include -#define DA850_EVM_PHY_MASK 0x1 -#define DA850_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ - #define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8) #define DA850_LCD_BL_PIN GPIO_TO_PIN(2, 15) @@ -678,9 +675,6 @@ static int __init da850_evm_config_emac(void) /* Enable/Disable MII MDIO clock */ gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en); - soc_info->emac_pdata->phy_mask = DA850_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DA850_EVM_MDIO_FREQUENCY; - ret = da8xx_register_emac(); if (ret) pr_warning("da850_evm_init: emac registration failed: %d\n", diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index 60c59dd..f697914 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -54,9 +54,6 @@ static inline int have_tvp7002(void) return 0; } -#define DM365_EVM_PHY_MASK (0x2) -#define DM365_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - /* * A MAX-II CPLD is used for various board control functions. */ @@ -530,16 +527,12 @@ fail: /* externally mux MMC1/ENET/AIC33 to imager */ mux |= BIT(6) | BIT(5) | BIT(3); } else { - struct davinci_soc_info *soc_info = &davinci_soc_info; - /* we can use MMC1 ... */ dm365evm_mmc_configure(); davinci_setup_mmc(1, &dm365evm_mmc_config); /* ... and ENET ... */ dm365evm_emac_configure(); - soc_info->emac_pdata->phy_mask = DM365_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DM365_EVM_MDIO_FREQUENCY; resets &= ~BIT(3); /* ... and AIC33 */ diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 65bb940..c86bf23 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -39,9 +39,6 @@ #include #include -#define DM644X_EVM_PHY_MASK (0x2) -#define DM644X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - #define LXT971_PHY_ID (0x001378e2) #define LXT971_PHY_MASK (0xfffffff0) @@ -672,7 +669,6 @@ static int davinci_phy_fixup(struct phy_device *phydev) static __init void davinci_evm_init(void) { struct clk *aemif_clk; - struct davinci_soc_info *soc_info = &davinci_soc_info; aemif_clk = clk_get(NULL, "aemif"); clk_enable(aemif_clk); @@ -707,9 +703,6 @@ static __init void davinci_evm_init(void) davinci_serial_init(&uart_config); dm644x_init_asp(&dm644x_evm_snd_data); - soc_info->emac_pdata->phy_mask = DM644X_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DM644X_EVM_MDIO_FREQUENCY; - /* Register the fixup for PHY on DaVinci */ phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK, davinci_phy_fixup); diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 5a29955..3f34221 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -729,9 +729,6 @@ static struct davinci_uart_config uart_config __initdata = { .enabled_uarts = (1 << 0), }; -#define DM646X_EVM_PHY_MASK (0x2) -#define DM646X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - /* * The following EDMA channels/slots are not being used by drivers (for * example: Timer, GPIO, UART events etc) on dm646x, hence they are being @@ -767,8 +764,6 @@ static struct edma_rsv_info dm646x_edma_rsv[] = { static __init void evm_init(void) { - struct davinci_soc_info *soc_info = &davinci_soc_info; - evm_init_i2c(); davinci_serial_init(&uart_config); dm646x_init_mcasp0(&dm646x_evm_snd_data[0]); @@ -783,9 +778,6 @@ static __init void evm_init(void) if (HAS_ATA) davinci_init_ide(); - - soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY; } #define DM646X_EVM_REF_FREQ 27000000 diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index 7146916..ec5808f 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -22,9 +22,6 @@ #include #include -#define MITYOMAPL138_PHY_MASK 0x08 /* hardcoded for now */ -#define MITYOMAPL138_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - /* * MityDSP-L138 includes a 256 MByte large-page NAND flash * (128K blocks). @@ -136,10 +133,6 @@ static void __init mityomapl138_config_emac(void) /* configure the CFGCHIP3 register for RMII or MII */ __raw_writel(val, cfg_chip3_base); - soc_info->emac_pdata->phy_mask = MITYOMAPL138_PHY_MASK; - pr_debug("setting phy_mask to %x\n", soc_info->emac_pdata->phy_mask); - soc_info->emac_pdata->mdio_max_freq = MITYOMAPL138_MDIO_FREQUENCY; - ret = da8xx_register_emac(); if (ret) pr_warning("emac registration failed: %d\n", ret); diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index 4c30e92..4b32f0a 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -39,9 +39,6 @@ #include #include -#define NEUROS_OSD2_PHY_MASK 0x2 -#define NEUROS_OSD2_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ - #define LXT971_PHY_ID 0x001378e2 #define LXT971_PHY_MASK 0xfffffff0 @@ -218,7 +215,6 @@ static struct davinci_mmc_config davinci_ntosd2_mmc_config = { static __init void davinci_ntosd2_init(void) { struct clk *aemif_clk; - struct davinci_soc_info *soc_info = &davinci_soc_info; int status; aemif_clk = clk_get(NULL, "aemif"); @@ -252,9 +248,6 @@ static __init void davinci_ntosd2_init(void) davinci_serial_init(&uart_config); dm644x_init_asp(&dm644x_ntosd2_snd_data); - soc_info->emac_pdata->phy_mask = NEUROS_OSD2_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = NEUROS_OSD2_MDIO_FREQUENCY; - davinci_setup_usb(1000, 8); /* * Mux the pins to be GPIOs, VLYNQEN is already done at startup. diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 23e664a..b372d7f 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -42,9 +42,6 @@ #include #include -#define SFFSDR_PHY_MASK (0x2) -#define SFFSDR_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - static struct mtd_partition davinci_sffsdr_nandflash_partition[] = { /* U-Boot Environment: Block 0 * UBL: Block 1 @@ -137,14 +134,10 @@ static void __init davinci_sffsdr_map_io(void) static __init void davinci_sffsdr_init(void) { - struct davinci_soc_info *soc_info = &davinci_soc_info; - platform_add_devices(davinci_sffsdr_devices, ARRAY_SIZE(davinci_sffsdr_devices)); sffsdr_init_i2c(); davinci_serial_init(&uart_config); - soc_info->emac_pdata->phy_mask = SFFSDR_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = SFFSDR_MDIO_FREQUENCY; davinci_setup_usb(0, 0); /* We support only peripheral mode. */ /* mux VLYNQ pins */ diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 9039221..9eec630 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -42,7 +42,6 @@ #define DA8XX_EMAC_CTRL_REG_OFFSET 0x3000 #define DA8XX_EMAC_MOD_REG_OFFSET 0x2000 #define DA8XX_EMAC_RAM_OFFSET 0x0000 -#define DA8XX_MDIO_REG_OFFSET 0x4000 #define DA8XX_EMAC_CTRL_RAM_SIZE SZ_8K void __iomem *da8xx_syscfg0_base; @@ -381,7 +380,6 @@ struct emac_platform_data da8xx_emac_pdata = { .ctrl_reg_offset = DA8XX_EMAC_CTRL_REG_OFFSET, .ctrl_mod_reg_offset = DA8XX_EMAC_MOD_REG_OFFSET, .ctrl_ram_offset = DA8XX_EMAC_RAM_OFFSET, - .mdio_reg_offset = DA8XX_MDIO_REG_OFFSET, .ctrl_ram_size = DA8XX_EMAC_CTRL_RAM_SIZE, .version = EMAC_VERSION_2, }; diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 0add1ca..a12065e 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -691,7 +691,6 @@ static struct emac_platform_data dm365_emac_pdata = { .ctrl_reg_offset = DM365_EMAC_CNTRL_OFFSET, .ctrl_mod_reg_offset = DM365_EMAC_CNTRL_MOD_OFFSET, .ctrl_ram_offset = DM365_EMAC_CNTRL_RAM_OFFSET, - .mdio_reg_offset = DM365_EMAC_MDIO_OFFSET, .ctrl_ram_size = DM365_EMAC_CNTRL_RAM_SIZE, .version = EMAC_VERSION_2, }; diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 22166a5..0608dd7 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -322,7 +322,6 @@ static struct emac_platform_data dm644x_emac_pdata = { .ctrl_reg_offset = DM644X_EMAC_CNTRL_OFFSET, .ctrl_mod_reg_offset = DM644X_EMAC_CNTRL_MOD_OFFSET, .ctrl_ram_offset = DM644X_EMAC_CNTRL_RAM_OFFSET, - .mdio_reg_offset = DM644X_EMAC_MDIO_OFFSET, .ctrl_ram_size = DM644X_EMAC_CNTRL_RAM_SIZE, .version = EMAC_VERSION_1, }; diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 3d636b2..1e0f809 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -358,7 +358,6 @@ static struct emac_platform_data dm646x_emac_pdata = { .ctrl_reg_offset = DM646X_EMAC_CNTRL_OFFSET, .ctrl_mod_reg_offset = DM646X_EMAC_CNTRL_MOD_OFFSET, .ctrl_ram_offset = DM646X_EMAC_CNTRL_RAM_OFFSET, - .mdio_reg_offset = DM646X_EMAC_MDIO_OFFSET, .ctrl_ram_size = DM646X_EMAC_CNTRL_RAM_SIZE, .version = EMAC_VERSION_2, }; diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h index dbb5052..2563bf4 100644 --- a/arch/arm/mach-davinci/include/mach/dm365.h +++ b/arch/arm/mach-davinci/include/mach/dm365.h @@ -25,7 +25,6 @@ #define DM365_EMAC_CNTRL_OFFSET (0x0000) #define DM365_EMAC_CNTRL_MOD_OFFSET (0x3000) #define DM365_EMAC_CNTRL_RAM_OFFSET (0x1000) -#define DM365_EMAC_MDIO_OFFSET (0x4000) #define DM365_EMAC_CNTRL_RAM_SIZE (0x2000) /* Base of key scan register bank */ diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h index 5159117..5a1b26d 100644 --- a/arch/arm/mach-davinci/include/mach/dm644x.h +++ b/arch/arm/mach-davinci/include/mach/dm644x.h @@ -32,7 +32,6 @@ #define DM644X_EMAC_CNTRL_OFFSET (0x0000) #define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000) -#define DM644X_EMAC_MDIO_OFFSET (0x4000) #define DM644X_EMAC_CNTRL_RAM_SIZE (0x2000) #define DM644X_ASYNC_EMIF_CONTROL_BASE 0x01E00000 diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h index 1c4dca9..7a27f3f 100644 --- a/arch/arm/mach-davinci/include/mach/dm646x.h +++ b/arch/arm/mach-davinci/include/mach/dm646x.h @@ -23,7 +23,6 @@ #define DM646X_EMAC_CNTRL_OFFSET (0x0000) #define DM646X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM646X_EMAC_CNTRL_RAM_OFFSET (0x2000) -#define DM646X_EMAC_MDIO_OFFSET (0x4000) #define DM646X_EMAC_CNTRL_RAM_SIZE (0x2000) #define DM646X_ASYNC_EMIF_CONTROL_BASE 0x20008000 -- 1.7.0.4 From cyril at ti.com Tue Sep 7 15:25:39 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 7 Sep 2010 16:25:39 -0400 Subject: [PATCH v3 07/10] net: davinci_emac: cleanup unused mdio emac code In-Reply-To: <1283891142-15522-1-git-send-email-cyril@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> Message-ID: <1283891142-15522-8-git-send-email-cyril@ti.com> This patch removes code that has been rendered useless by the previous patches in this series. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller --- drivers/net/davinci_emac.c | 107 ------------------------------------------ include/linux/davinci_emac.h | 3 - 2 files changed, 0 insertions(+), 110 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 6ed779d..036681a 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -113,7 +113,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_FRAME_SIZE (1500 + 14 + 4 + 4) #define EMAC_DEF_TX_CH (0) /* Default 0th channel */ #define EMAC_DEF_RX_CH (0) /* Default 0th channel */ -#define EMAC_DEF_MDIO_TICK_MS (10) /* typically 1 tick=1 ms) */ #define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */ #define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */ #define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */ @@ -303,25 +302,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DM644X_INTMIN_INTVL 0x1 #define EMAC_DM644X_INTMAX_INTVL (EMAC_DM644X_EWINTCNT_MASK) -/* EMAC MDIO related */ -/* Mask & Control defines */ -#define MDIO_CONTROL_CLKDIV (0xFF) -#define MDIO_CONTROL_ENABLE BIT(30) -#define MDIO_USERACCESS_GO BIT(31) -#define MDIO_USERACCESS_WRITE BIT(30) -#define MDIO_USERACCESS_READ (0) -#define MDIO_USERACCESS_REGADR (0x1F << 21) -#define MDIO_USERACCESS_PHYADR (0x1F << 16) -#define MDIO_USERACCESS_DATA (0xFFFF) -#define MDIO_USERPHYSEL_LINKSEL BIT(7) -#define MDIO_VER_MODID (0xFFFF << 16) -#define MDIO_VER_REVMAJ (0xFF << 8) -#define MDIO_VER_REVMIN (0xFF) - -#define MDIO_USERACCESS(inst) (0x80 + (inst * 8)) -#define MDIO_USERPHYSEL(inst) (0x84 + (inst * 8)) -#define MDIO_CONTROL (0x04) - /* EMAC DM646X control module registers */ #define EMAC_DM646X_CMINTCTRL 0x0C #define EMAC_DM646X_CMRXINTEN 0x14 @@ -493,13 +473,6 @@ struct emac_priv { u32 mac_hash2; u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS]; u32 rx_addr_type; - /* periodic timer required for MDIO polling */ - struct timer_list periodic_timer; - u32 periodic_ticks; - u32 timer_active; - u32 phy_mask; - /* mii_bus,phy members */ - struct mii_bus *mii_bus; const char *phy_id; struct phy_device *phydev; spinlock_t lock; @@ -511,7 +484,6 @@ struct emac_priv { /* clock frequency for EMAC */ static struct clk *emac_clk; static unsigned long emac_bus_frequency; -static unsigned long mdio_max_freq; #define emac_virt_to_phys(addr, priv) \ (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \ @@ -549,9 +521,6 @@ static char *emac_rxhost_errcodes[16] = { #define emac_ctrl_read(reg) ioread32((priv->ctrl_base + (reg))) #define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg))) -#define emac_mdio_read(reg) ioread32(bus->priv + (reg)) -#define emac_mdio_write(reg, val) iowrite32(val, (bus->priv + (reg))) - /** * emac_dump_regs: Dump important EMAC registers to debug terminal * @priv: The DaVinci EMAC private adapter structure @@ -657,9 +626,6 @@ static void emac_dump_regs(struct emac_priv *priv) emac_read(EMAC_RXDMAOVERRUNS)); } -/************************************************************************* - * EMAC MDIO/Phy Functionality - *************************************************************************/ /** * emac_get_drvinfo: Get EMAC driver information * @ndev: The DaVinci EMAC network adapter @@ -2349,79 +2315,6 @@ void emac_poll_controller(struct net_device *ndev) } #endif -/* PHY/MII bus related */ - -/* Wait until mdio is ready for next command */ -#define MDIO_WAIT_FOR_USER_ACCESS\ - while ((emac_mdio_read((MDIO_USERACCESS(0))) &\ - MDIO_USERACCESS_GO) != 0) - -static int emac_mii_read(struct mii_bus *bus, int phy_id, int phy_reg) -{ - unsigned int phy_data = 0; - unsigned int phy_control; - - /* Wait until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - phy_control = (MDIO_USERACCESS_GO | - MDIO_USERACCESS_READ | - ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | - ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | - (phy_data & MDIO_USERACCESS_DATA)); - emac_mdio_write(MDIO_USERACCESS(0), phy_control); - - /* Wait until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - return emac_mdio_read(MDIO_USERACCESS(0)) & MDIO_USERACCESS_DATA; - -} - -static int emac_mii_write(struct mii_bus *bus, int phy_id, - int phy_reg, u16 phy_data) -{ - - unsigned int control; - - /* until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - control = (MDIO_USERACCESS_GO | - MDIO_USERACCESS_WRITE | - ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | - ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | - (phy_data & MDIO_USERACCESS_DATA)); - emac_mdio_write(MDIO_USERACCESS(0), control); - - return 0; -} - -static int emac_mii_reset(struct mii_bus *bus) -{ - unsigned int clk_div; - int mdio_bus_freq = emac_bus_frequency; - - if (mdio_max_freq && mdio_bus_freq) - clk_div = ((mdio_bus_freq / mdio_max_freq) - 1); - else - clk_div = 0xFF; - - clk_div &= MDIO_CONTROL_CLKDIV; - - /* Set enable and clock divider in MDIOControl */ - emac_mdio_write(MDIO_CONTROL, (clk_div | MDIO_CONTROL_ENABLE)); - - return 0; - -} - -static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, PHY_POLL }; - -/* emac_driver: EMAC MII bus structure */ - -static struct mii_bus *emac_mii; - static void emac_adjust_link(struct net_device *ndev) { struct emac_priv *priv = netdev_priv(ndev); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index 6bcd247..7508e49 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -24,10 +24,7 @@ struct emac_platform_data { u32 ctrl_mod_reg_offset; u32 ctrl_ram_offset; u32 hw_ram_addr; - u32 mdio_reg_offset; u32 ctrl_ram_size; - u32 phy_mask; - u32 mdio_max_freq; const char *phy_id; u8 rmii_en; u8 version; -- 1.7.0.4 From cyril at ti.com Tue Sep 7 15:25:36 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 7 Sep 2010 16:25:36 -0400 Subject: [PATCH v3 04/10] net: davinci_emac: switch to new mdio In-Reply-To: <1283891142-15522-1-git-send-email-cyril@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> Message-ID: <1283891142-15522-5-git-send-email-cyril@ti.com> This patch switches the emac implementation over to the newly separated MDIO driver. With this, the mdio bus frequency defaults to a safe 2.2MHz. Boards may optionally specify a bus frequency via platform data. The phy identification scheme has been modified to use a phy bus id instead of a mask. This largely serves to eliminate the "phy search" code in emac init. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller --- drivers/net/Kconfig | 1 + drivers/net/davinci_emac.c | 88 ++++++++++++++--------------------------- include/linux/davinci_emac.h | 1 + 3 files changed, 32 insertions(+), 58 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c5c86e0..911e7f1 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -951,6 +951,7 @@ config NET_NETX config TI_DAVINCI_EMAC tristate "TI DaVinci EMAC Support" depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + select TI_DAVINCI_MDIO select PHYLIB help This driver supports TI's DaVinci Ethernet . diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 7fbd052..6ed779d 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -500,6 +500,7 @@ struct emac_priv { u32 phy_mask; /* mii_bus,phy members */ struct mii_bus *mii_bus; + const char *phy_id; struct phy_device *phydev; spinlock_t lock; /*platform specific members*/ @@ -686,7 +687,7 @@ static int emac_get_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) { struct emac_priv *priv = netdev_priv(ndev); - if (priv->phy_mask) + if (priv->phydev) return phy_ethtool_gset(priv->phydev, ecmd); else return -EOPNOTSUPP; @@ -704,7 +705,7 @@ static int emac_get_settings(struct net_device *ndev, static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) { struct emac_priv *priv = netdev_priv(ndev); - if (priv->phy_mask) + if (priv->phydev) return phy_ethtool_sset(priv->phydev, ecmd); else return -EOPNOTSUPP; @@ -841,7 +842,7 @@ static void emac_update_phystatus(struct emac_priv *priv) mac_control = emac_read(EMAC_MACCONTROL); cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ? DUPLEX_FULL : DUPLEX_HALF; - if (priv->phy_mask) + if (priv->phydev) new_duplex = priv->phydev->duplex; else new_duplex = DUPLEX_FULL; @@ -2485,6 +2486,11 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) return -EOPNOTSUPP; } +static int match_first_device(struct device *dev, void *data) +{ + return 1; +} + /** * emac_dev_open: EMAC device open * @ndev: The DaVinci EMAC network adapter @@ -2499,7 +2505,6 @@ static int emac_dev_open(struct net_device *ndev) { struct device *emac_dev = &ndev->dev; u32 rc, cnt, ch; - int phy_addr; struct resource *res; int q, m; int i = 0; @@ -2560,28 +2565,26 @@ static int emac_dev_open(struct net_device *ndev) emac_set_coalesce(ndev, &coal); } - /* find the first phy */ priv->phydev = NULL; - if (priv->phy_mask) { - emac_mii_reset(priv->mii_bus); - for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { - if (priv->mii_bus->phy_map[phy_addr]) { - priv->phydev = priv->mii_bus->phy_map[phy_addr]; - break; - } - } + /* use the first phy on the bus if pdata did not give us a phy id */ + if (!priv->phy_id) { + struct device *phy; - if (!priv->phydev) { - printk(KERN_ERR "%s: no PHY found\n", ndev->name); - return -1; - } + phy = bus_find_device(&mdio_bus_type, NULL, NULL, + match_first_device); + if (phy) + priv->phy_id = dev_name(phy); + } - priv->phydev = phy_connect(ndev, dev_name(&priv->phydev->dev), - &emac_adjust_link, 0, PHY_INTERFACE_MODE_MII); + if (priv->phy_id) { + priv->phydev = phy_connect(ndev, priv->phy_id, + &emac_adjust_link, 0, + PHY_INTERFACE_MODE_MII); if (IS_ERR(priv->phydev)) { - printk(KERN_ERR "%s: Could not attach to PHY\n", - ndev->name); + dev_err(emac_dev, "could not connect to phy %s\n", + priv->phy_id); + priv->phydev = NULL; return PTR_ERR(priv->phydev); } @@ -2589,12 +2592,13 @@ static int emac_dev_open(struct net_device *ndev) priv->speed = 0; priv->duplex = ~0; - printk(KERN_INFO "%s: attached PHY driver [%s] " - "(mii_bus:phy_addr=%s, id=%x)\n", ndev->name, + dev_info(emac_dev, "attached PHY driver [%s] " + "(mii_bus:phy_addr=%s, id=%x)\n", priv->phydev->drv->name, dev_name(&priv->phydev->dev), priv->phydev->phy_id); - } else{ + } else { /* No PHY , fix the link, speed and duplex settings */ + dev_notice(emac_dev, "no phy, defaulting to 100/full\n"); priv->link = 1; priv->speed = SPEED_100; priv->duplex = DUPLEX_FULL; @@ -2607,7 +2611,7 @@ static int emac_dev_open(struct net_device *ndev) if (netif_msg_drv(priv)) dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name); - if (priv->phy_mask) + if (priv->phydev) phy_start(priv->phydev); return 0; @@ -2794,7 +2798,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) /* MAC addr and PHY mask , RMII enable info from platform_data */ memcpy(priv->mac_addr, pdata->mac_addr, 6); - priv->phy_mask = pdata->phy_mask; + priv->phy_id = pdata->phy_id; priv->rmii_en = pdata->rmii_en; priv->version = pdata->version; priv->int_enable = pdata->interrupt_enable; @@ -2871,32 +2875,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) } - /* MII/Phy intialisation, mdio bus registration */ - emac_mii = mdiobus_alloc(); - if (emac_mii == NULL) { - dev_err(emac_dev, "DaVinci EMAC: Error allocating mii_bus\n"); - rc = -ENOMEM; - goto mdio_alloc_err; - } - - priv->mii_bus = emac_mii; - emac_mii->name = "emac-mii", - emac_mii->read = emac_mii_read, - emac_mii->write = emac_mii_write, - emac_mii->reset = emac_mii_reset, - emac_mii->irq = mii_irqs, - emac_mii->phy_mask = ~(priv->phy_mask); - emac_mii->parent = &pdev->dev; - emac_mii->priv = priv->remap_addr + pdata->mdio_reg_offset; - snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", priv->pdev->id); - mdio_max_freq = pdata->mdio_max_freq; - emac_mii->reset(emac_mii); - - /* Register the MII bus */ - rc = mdiobus_register(emac_mii); - if (rc) - goto mdiobus_quit; - if (netif_msg_probe(priv)) { dev_notice(emac_dev, "DaVinci EMAC Probe found device "\ "(regs: %p, irq: %d)\n", @@ -2904,11 +2882,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) } return 0; -mdiobus_quit: - mdiobus_free(emac_mii); - netdev_reg_err: -mdio_alloc_err: clk_disable(emac_clk); no_irq_res: res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -2938,8 +2912,6 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mdiobus_unregister(priv->mii_bus); - mdiobus_free(priv->mii_bus); release_mem_region(res->start, res->end - res->start + 1); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index a04fd8c..6bcd247 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -28,6 +28,7 @@ struct emac_platform_data { u32 ctrl_ram_size; u32 phy_mask; u32 mdio_max_freq; + const char *phy_id; u8 rmii_en; u8 version; void (*interrupt_enable) (void); -- 1.7.0.4 From cyril at ti.com Tue Sep 7 15:25:42 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 7 Sep 2010 16:25:42 -0400 Subject: [PATCH v3 10/10] net: davinci_emac: cleanup unused cpdma code In-Reply-To: <1283891142-15522-1-git-send-email-cyril@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> Message-ID: <1283891142-15522-11-git-send-email-cyril@ti.com> Having switched over to the newly introduced cpdma layer, this patch now removes a whole bunch of code that is now unused. This patch has been maintained separate strictly for reasons of readability. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller --- drivers/net/davinci_emac.c | 930 -------------------------------------------- 1 files changed, 0 insertions(+), 930 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 4147d32..525b84c 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -127,7 +127,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; /* EMAC register related defines */ #define EMAC_ALL_MULTI_REG_VALUE (0xFFFFFFFF) #define EMAC_NUM_MULTICAST_BITS (64) -#define EMAC_TEARDOWN_VALUE (0xFFFFFFFC) #define EMAC_TX_CONTROL_TX_ENABLE_VAL (0x1) #define EMAC_RX_CONTROL_RX_ENABLE_VAL (0x1) #define EMAC_MAC_HOST_ERR_INTMASK_VAL (0x2) @@ -214,24 +213,10 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */ /* EMAC Peripheral Device Register Memory Layout structure */ -#define EMAC_TXIDVER 0x0 -#define EMAC_TXCONTROL 0x4 -#define EMAC_TXTEARDOWN 0x8 -#define EMAC_RXIDVER 0x10 -#define EMAC_RXCONTROL 0x14 -#define EMAC_RXTEARDOWN 0x18 -#define EMAC_TXINTSTATRAW 0x80 -#define EMAC_TXINTSTATMASKED 0x84 -#define EMAC_TXINTMASKSET 0x88 -#define EMAC_TXINTMASKCLEAR 0x8C #define EMAC_MACINVECTOR 0x90 #define EMAC_DM646X_MACEOIVECTOR 0x94 -#define EMAC_RXINTSTATRAW 0xA0 -#define EMAC_RXINTSTATMASKED 0xA4 -#define EMAC_RXINTMASKSET 0xA8 -#define EMAC_RXINTMASKCLEAR 0xAC #define EMAC_MACINTSTATRAW 0xB0 #define EMAC_MACINTSTATMASKED 0xB4 #define EMAC_MACINTMASKSET 0xB8 @@ -258,12 +243,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_MACADDRHI 0x504 #define EMAC_MACINDEX 0x508 -/* EMAC HDP and Completion registors */ -#define EMAC_TXHDP(ch) (0x600 + (ch * 4)) -#define EMAC_RXHDP(ch) (0x620 + (ch * 4)) -#define EMAC_TXCP(ch) (0x640 + (ch * 4)) -#define EMAC_RXCP(ch) (0x660 + (ch * 4)) - /* EMAC statistics registers */ #define EMAC_RXGOODFRAMES 0x200 #define EMAC_RXBCASTFRAMES 0x204 @@ -328,120 +307,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; /* EMAC Stats Clear Mask */ #define EMAC_STATS_CLR_MASK (0xFFFFFFFF) -/** net_buf_obj: EMAC network bufferdata structure - * - * EMAC network buffer data structure - */ -struct emac_netbufobj { - void *buf_token; - char *data_ptr; - int length; -}; - -/** net_pkt_obj: EMAC network packet data structure - * - * EMAC network packet data structure - supports buffer list (for future) - */ -struct emac_netpktobj { - void *pkt_token; /* data token may hold tx/rx chan id */ - struct emac_netbufobj *buf_list; /* array of network buffer objects */ - int num_bufs; - int pkt_length; -}; - -/** emac_tx_bd: EMAC TX Buffer descriptor data structure - * - * EMAC TX Buffer descriptor data structure - */ -struct emac_tx_bd { - int h_next; - int buff_ptr; - int off_b_len; - int mode; /* SOP, EOP, ownership, EOQ, teardown,Qstarv, length */ - struct emac_tx_bd __iomem *next; - void *buf_token; -}; - -/** emac_txch: EMAC TX Channel data structure - * - * EMAC TX Channel data structure - */ -struct emac_txch { - /* Config related */ - u32 num_bd; - u32 service_max; - - /* CPPI specific */ - u32 alloc_size; - void __iomem *bd_mem; - struct emac_tx_bd __iomem *bd_pool_head; - struct emac_tx_bd __iomem *active_queue_head; - struct emac_tx_bd __iomem *active_queue_tail; - struct emac_tx_bd __iomem *last_hw_bdprocessed; - u32 queue_active; - u32 teardown_pending; - u32 *tx_complete; - - /** statistics */ - u32 proc_count; /* TX: # of times emac_tx_bdproc is called */ - u32 mis_queued_packets; - u32 queue_reinit; - u32 end_of_queue_add; - u32 out_of_tx_bd; - u32 no_active_pkts; /* IRQ when there were no packets to process */ - u32 active_queue_count; -}; - -/** emac_rx_bd: EMAC RX Buffer descriptor data structure - * - * EMAC RX Buffer descriptor data structure - */ -struct emac_rx_bd { - int h_next; - int buff_ptr; - int off_b_len; - int mode; - struct emac_rx_bd __iomem *next; - void *data_ptr; - void *buf_token; -}; - -/** emac_rxch: EMAC RX Channel data structure - * - * EMAC RX Channel data structure - */ -struct emac_rxch { - /* configuration info */ - u32 num_bd; - u32 service_max; - u32 buf_size; - char mac_addr[6]; - - /** CPPI specific */ - u32 alloc_size; - void __iomem *bd_mem; - struct emac_rx_bd __iomem *bd_pool_head; - struct emac_rx_bd __iomem *active_queue_head; - struct emac_rx_bd __iomem *active_queue_tail; - u32 queue_active; - u32 teardown_pending; - - /* packet and buffer objects */ - struct emac_netpktobj pkt_queue; - struct emac_netbufobj buf_queue; - - /** statistics */ - u32 proc_count; /* number of times emac_rx_bdproc is called */ - u32 processed_bd; - u32 recycled_bd; - u32 out_of_rx_bd; - u32 out_of_rx_buffers; - u32 queue_reinit; - u32 end_of_queue_add; - u32 end_of_queue; - u32 mis_queued_packets; -}; - /* emac_priv: EMAC private data structure * * EMAC adapter private data structure @@ -452,17 +317,10 @@ struct emac_priv { struct platform_device *pdev; struct napi_struct napi; char mac_addr[6]; - spinlock_t tx_lock; - spinlock_t rx_lock; void __iomem *remap_addr; u32 emac_base_phys; void __iomem *emac_base; void __iomem *ctrl_base; - void __iomem *emac_ctrl_ram; - u32 ctrl_ram_size; - u32 hw_ram_addr; - struct emac_txch *txch[EMAC_DEF_MAX_TX_CH]; - struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH]; struct cpdma_ctlr *dma; struct cpdma_chan *txchan; struct cpdma_chan *rxchan; @@ -491,18 +349,6 @@ struct emac_priv { static struct clk *emac_clk; static unsigned long emac_bus_frequency; -#define emac_virt_to_phys(addr, priv) \ - (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \ - + priv->hw_ram_addr) - -/* Cache macros - Packet buffers would be from skb pool which is cached */ -#define EMAC_VIRT_NOCACHE(addr) (addr) - -/* DM644x does not have BD's in cached memory - so no cache functions */ -#define BD_CACHE_INVALIDATE(addr, size) -#define BD_CACHE_WRITEBACK(addr, size) -#define BD_CACHE_WRITEBACK_INVALIDATE(addr, size) - /* EMAC TX Host Error description strings */ static char *emac_txhost_errcodes[16] = { "No error", "SOP error", "Ownership bit not set in SOP buffer", @@ -545,20 +391,6 @@ static void emac_dump_regs(struct emac_priv *priv) emac_ctrl_read(EMAC_CTRL_EWCTL), emac_ctrl_read(EMAC_CTRL_EWINTTCNT)); } - dev_info(emac_dev, "EMAC: TXID: %08X %s, RXID: %08X %s\n", - emac_read(EMAC_TXIDVER), - ((emac_read(EMAC_TXCONTROL)) ? "enabled" : "disabled"), - emac_read(EMAC_RXIDVER), - ((emac_read(EMAC_RXCONTROL)) ? "enabled" : "disabled")); - dev_info(emac_dev, "EMAC: TXIntRaw:%08X, TxIntMasked: %08X, "\ - "TxIntMasSet: %08X\n", emac_read(EMAC_TXINTSTATRAW), - emac_read(EMAC_TXINTSTATMASKED), emac_read(EMAC_TXINTMASKSET)); - dev_info(emac_dev, "EMAC: RXIntRaw:%08X, RxIntMasked: %08X, "\ - "RxIntMasSet: %08X\n", emac_read(EMAC_RXINTSTATRAW), - emac_read(EMAC_RXINTSTATMASKED), emac_read(EMAC_RXINTMASKSET)); - dev_info(emac_dev, "EMAC: MacIntRaw:%08X, MacIntMasked: %08X, "\ - "MacInVector=%08X\n", emac_read(EMAC_MACINTSTATRAW), - emac_read(EMAC_MACINTSTATMASKED), emac_read(EMAC_MACINVECTOR)); dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n", emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL)); dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\ @@ -567,8 +399,6 @@ static void emac_dump_regs(struct emac_priv *priv) dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\ "MacConfig=%08X\n", emac_read(EMAC_MACCONTROL), emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG)); - dev_info(emac_dev, "EMAC: TXHDP[0]:%08X, RXHDP[0]: %08X\n", - emac_read(EMAC_TXHDP(0)), emac_read(EMAC_RXHDP(0))); dev_info(emac_dev, "EMAC Statistics\n"); dev_info(emac_dev, "EMAC: rx_good_frames:%d\n", emac_read(EMAC_RXGOODFRAMES)); @@ -1208,373 +1038,6 @@ static void emac_tx_handler(void *token, int len, int status) dev_kfree_skb_any(skb); } -/** EMAC on-chip buffer descriptor memory - * - * WARNING: Please note that the on chip memory is used for both TX and RX - * buffer descriptor queues and is equally divided between TX and RX desc's - * If the number of TX or RX descriptors change this memory pointers need - * to be adjusted. If external memory is allocated then these pointers can - * pointer to the memory - * - */ -#define EMAC_TX_BD_MEM(priv) ((priv)->emac_ctrl_ram) -#define EMAC_RX_BD_MEM(priv) ((priv)->emac_ctrl_ram + \ - (((priv)->ctrl_ram_size) >> 1)) - -/** - * emac_init_txch: TX channel initialization - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device init to setup a TX channel (allocate buffer desc - * create free pool and keep ready for transmission - * - * Returns success(0) or mem alloc failures error code - */ -static int emac_init_txch(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 cnt, bd_size; - void __iomem *mem; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch = NULL; - - txch = kzalloc(sizeof(struct emac_txch), GFP_KERNEL); - if (NULL == txch) { - dev_err(emac_dev, "DaVinci EMAC: TX Ch mem alloc failed"); - return -ENOMEM; - } - priv->txch[ch] = txch; - txch->service_max = EMAC_DEF_TX_MAX_SERVICE; - txch->active_queue_head = NULL; - txch->active_queue_tail = NULL; - txch->queue_active = 0; - txch->teardown_pending = 0; - - /* allocate memory for TX CPPI channel on a 4 byte boundry */ - txch->tx_complete = kzalloc(txch->service_max * sizeof(u32), - GFP_KERNEL); - if (NULL == txch->tx_complete) { - dev_err(emac_dev, "DaVinci EMAC: Tx service mem alloc failed"); - kfree(txch); - return -ENOMEM; - } - - /* allocate buffer descriptor pool align every BD on four word - * boundry for future requirements */ - bd_size = (sizeof(struct emac_tx_bd) + 0xF) & ~0xF; - txch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; - txch->alloc_size = (((bd_size * txch->num_bd) + 0xF) & ~0xF); - - /* alloc TX BD memory */ - txch->bd_mem = EMAC_TX_BD_MEM(priv); - __memzero((void __force *)txch->bd_mem, txch->alloc_size); - - /* initialize the BD linked list */ - mem = (void __force __iomem *) - (((u32 __force) txch->bd_mem + 0xF) & ~0xF); - txch->bd_pool_head = NULL; - for (cnt = 0; cnt < txch->num_bd; cnt++) { - curr_bd = mem + (cnt * bd_size); - curr_bd->next = txch->bd_pool_head; - txch->bd_pool_head = curr_bd; - } - - /* reset statistics counters */ - txch->out_of_tx_bd = 0; - txch->no_active_pkts = 0; - txch->active_queue_count = 0; - - return 0; -} - -/** - * emac_cleanup_txch: Book-keep function to clean TX channel resources - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to clean up TX channel resources - * - */ -static void emac_cleanup_txch(struct emac_priv *priv, u32 ch) -{ - struct emac_txch *txch = priv->txch[ch]; - - if (txch) { - if (txch->bd_mem) - txch->bd_mem = NULL; - kfree(txch->tx_complete); - kfree(txch); - priv->txch[ch] = NULL; - } -} - -/** - * emac_net_tx_complete: TX packet completion function - * @priv: The DaVinci EMAC private adapter structure - * @net_data_tokens: packet token - skb pointer - * @num_tokens: number of skb's to free - * @ch: TX channel number - * - * Frees the skb once packet is transmitted - * - */ -static int emac_net_tx_complete(struct emac_priv *priv, - void **net_data_tokens, - int num_tokens, u32 ch) -{ - struct net_device *ndev = priv->ndev; - u32 cnt; - - if (unlikely(num_tokens && netif_queue_stopped(ndev))) - netif_start_queue(ndev); - for (cnt = 0; cnt < num_tokens; cnt++) { - struct sk_buff *skb = (struct sk_buff *)net_data_tokens[cnt]; - if (skb == NULL) - continue; - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += skb->len; - dev_kfree_skb_any(skb); - } - return 0; -} - -/** - * emac_txch_teardown: TX channel teardown - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to teardown TX channel - * - */ -static void emac_txch_teardown(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ - struct emac_txch *txch = priv->txch[ch]; - struct emac_tx_bd __iomem *curr_bd; - - while ((emac_read(EMAC_TXCP(ch)) & EMAC_TEARDOWN_VALUE) != - EMAC_TEARDOWN_VALUE) { - /* wait till tx teardown complete */ - cpu_relax(); /* TODO: check if this helps ... */ - --teardown_cnt; - if (0 == teardown_cnt) { - dev_err(emac_dev, "EMAC: TX teardown aborted\n"); - break; - } - } - emac_write(EMAC_TXCP(ch), EMAC_TEARDOWN_VALUE); - - /* process sent packets and return skb's to upper layer */ - if (1 == txch->queue_active) { - curr_bd = txch->active_queue_head; - while (curr_bd != NULL) { - dma_unmap_single(emac_dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_TO_DEVICE); - - emac_net_tx_complete(priv, (void __force *) - &curr_bd->buf_token, 1, ch); - if (curr_bd != txch->active_queue_tail) - curr_bd = curr_bd->next; - else - break; - } - txch->bd_pool_head = txch->active_queue_head; - txch->active_queue_head = - txch->active_queue_tail = NULL; - } -} - -/** - * emac_stop_txch: Stop TX channel operation - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to stop TX channel operation - * - */ -static void emac_stop_txch(struct emac_priv *priv, u32 ch) -{ - struct emac_txch *txch = priv->txch[ch]; - - if (txch) { - txch->teardown_pending = 1; - emac_write(EMAC_TXTEARDOWN, 0); - emac_txch_teardown(priv, ch); - txch->teardown_pending = 0; - emac_write(EMAC_TXINTMASKCLEAR, BIT(ch)); - } -} - -/** - * emac_tx_bdproc: TX buffer descriptor (packet) processing - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number to process buffer descriptors for - * @budget: number of packets allowed to process - * @pending: indication to caller that packets are pending to process - * - * Processes TX buffer descriptors after packets are transmitted - checks - * ownership bit on the TX * descriptor and requeues it to free pool & frees - * the SKB buffer. Only "budget" number of packets are processed and - * indication of pending packets provided to the caller - * - * Returns number of packets processed - */ -static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) -{ - struct device *emac_dev = &priv->ndev->dev; - unsigned long flags; - u32 frame_status; - u32 pkts_processed = 0; - u32 tx_complete_cnt = 0; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch = priv->txch[ch]; - u32 *tx_complete_ptr = txch->tx_complete; - - if (unlikely(1 == txch->teardown_pending)) { - if (netif_msg_tx_err(priv) && net_ratelimit()) { - dev_err(emac_dev, "DaVinci EMAC:emac_tx_bdproc: "\ - "teardown pending\n"); - } - return 0; /* dont handle any pkt completions */ - } - - ++txch->proc_count; - spin_lock_irqsave(&priv->tx_lock, flags); - curr_bd = txch->active_queue_head; - if (NULL == curr_bd) { - emac_write(EMAC_TXCP(ch), - emac_virt_to_phys(txch->last_hw_bdprocessed, priv)); - txch->no_active_pkts++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return 0; - } - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - while ((curr_bd) && - ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && - (pkts_processed < budget)) { - emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd, priv)); - txch->active_queue_head = curr_bd->next; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - if (curr_bd->next) { /* misqueued packet */ - emac_write(EMAC_TXHDP(ch), curr_bd->h_next); - ++txch->mis_queued_packets; - } else { - txch->queue_active = 0; /* end of queue */ - } - } - - dma_unmap_single(emac_dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_TO_DEVICE); - - *tx_complete_ptr = (u32) curr_bd->buf_token; - ++tx_complete_ptr; - ++tx_complete_cnt; - curr_bd->next = txch->bd_pool_head; - txch->bd_pool_head = curr_bd; - --txch->active_queue_count; - pkts_processed++; - txch->last_hw_bdprocessed = curr_bd; - curr_bd = txch->active_queue_head; - if (curr_bd) { - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - } - } /* end of pkt processing loop */ - - emac_net_tx_complete(priv, - (void *)&txch->tx_complete[0], - tx_complete_cnt, ch); - spin_unlock_irqrestore(&priv->tx_lock, flags); - return pkts_processed; -} - -#define EMAC_ERR_TX_OUT_OF_BD -1 - -/** - * emac_send: EMAC Transmit function (internal) - * @priv: The DaVinci EMAC private adapter structure - * @pkt: packet pointer (contains skb ptr) - * @ch: TX channel number - * - * Called by the transmit function to queue the packet in EMAC hardware queue - * - * Returns success(0) or error code (typically out of desc's) - */ -static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch) -{ - unsigned long flags; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch; - struct emac_netbufobj *buf_list; - - txch = priv->txch[ch]; - buf_list = pkt->buf_list; /* get handle to the buffer array */ - - /* check packet size and pad if short */ - if (pkt->pkt_length < EMAC_DEF_MIN_ETHPKTSIZE) { - buf_list->length += (EMAC_DEF_MIN_ETHPKTSIZE - pkt->pkt_length); - pkt->pkt_length = EMAC_DEF_MIN_ETHPKTSIZE; - } - - spin_lock_irqsave(&priv->tx_lock, flags); - curr_bd = txch->bd_pool_head; - if (curr_bd == NULL) { - txch->out_of_tx_bd++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return EMAC_ERR_TX_OUT_OF_BD; - } - - txch->bd_pool_head = curr_bd->next; - curr_bd->buf_token = buf_list->buf_token; - curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buf_list->data_ptr, - buf_list->length, DMA_TO_DEVICE); - curr_bd->off_b_len = buf_list->length; - curr_bd->h_next = 0; - curr_bd->next = NULL; - curr_bd->mode = (EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT | - EMAC_CPPI_EOP_BIT | pkt->pkt_length); - - /* flush the packet from cache if write back cache is present */ - BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - - /* send the packet */ - if (txch->active_queue_head == NULL) { - txch->active_queue_head = curr_bd; - txch->active_queue_tail = curr_bd; - if (1 != txch->queue_active) { - emac_write(EMAC_TXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - txch->queue_active = 1; - } - ++txch->queue_reinit; - } else { - register struct emac_tx_bd __iomem *tail_bd; - register u32 frame_status; - - tail_bd = txch->active_queue_tail; - tail_bd->next = curr_bd; - txch->active_queue_tail = curr_bd; - tail_bd = EMAC_VIRT_NOCACHE(tail_bd); - tail_bd->h_next = (int)emac_virt_to_phys(curr_bd, priv); - frame_status = tail_bd->mode; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - emac_write(EMAC_TXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - frame_status &= ~(EMAC_CPPI_EOQ_BIT); - tail_bd->mode = frame_status; - ++txch->end_of_queue_add; - } - } - txch->active_queue_count++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return 0; -} - /** * emac_dev_xmit: EMAC Transmit function * @skb: SKB pointer @@ -1647,207 +1110,6 @@ static void emac_dev_tx_timeout(struct net_device *ndev) } /** - * emac_net_alloc_rx_buf: Allocate a skb for RX - * @priv: The DaVinci EMAC private adapter structure - * @buf_size: size of SKB data buffer to allocate - * @data_token: data token returned (skb handle for storing in buffer desc) - * @ch: RX channel number - * - * Called during RX channel setup - allocates skb buffer of required size - * and provides the skb handle and allocated buffer data pointer to caller - * - * Returns skb data pointer or 0 on failure to alloc skb - */ -static void *emac_net_alloc_rx_buf(struct emac_priv *priv, int buf_size, - void **data_token, u32 ch) -{ - struct net_device *ndev = priv->ndev; - struct device *emac_dev = &ndev->dev; - struct sk_buff *p_skb; - - p_skb = dev_alloc_skb(buf_size); - if (unlikely(NULL == p_skb)) { - if (netif_msg_rx_err(priv) && net_ratelimit()) - dev_err(emac_dev, "DaVinci EMAC: failed to alloc skb"); - return NULL; - } - - /* set device pointer in skb and reserve space for extra bytes */ - p_skb->dev = ndev; - skb_reserve(p_skb, NET_IP_ALIGN); - *data_token = (void *) p_skb; - return p_skb->data; -} - -/** - * emac_init_rxch: RX channel initialization - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * @param: mac address for RX channel - * - * Called during device init to setup a RX channel (allocate buffers and - * buffer descriptors, create queue and keep ready for reception - * - * Returns success(0) or mem alloc failures error code - */ -static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 cnt, bd_size; - void __iomem *mem; - struct emac_rx_bd __iomem *curr_bd; - struct emac_rxch *rxch = NULL; - - rxch = kzalloc(sizeof(struct emac_rxch), GFP_KERNEL); - if (NULL == rxch) { - dev_err(emac_dev, "DaVinci EMAC: RX Ch mem alloc failed"); - return -ENOMEM; - } - priv->rxch[ch] = rxch; - rxch->buf_size = priv->rx_buf_size; - rxch->service_max = EMAC_DEF_RX_MAX_SERVICE; - rxch->queue_active = 0; - rxch->teardown_pending = 0; - - /* save mac address */ - for (cnt = 0; cnt < 6; cnt++) - rxch->mac_addr[cnt] = param[cnt]; - - /* allocate buffer descriptor pool align every BD on four word - * boundry for future requirements */ - bd_size = (sizeof(struct emac_rx_bd) + 0xF) & ~0xF; - rxch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; - rxch->alloc_size = (((bd_size * rxch->num_bd) + 0xF) & ~0xF); - rxch->bd_mem = EMAC_RX_BD_MEM(priv); - __memzero((void __force *)rxch->bd_mem, rxch->alloc_size); - rxch->pkt_queue.buf_list = &rxch->buf_queue; - - /* allocate RX buffer and initialize the BD linked list */ - mem = (void __force __iomem *) - (((u32 __force) rxch->bd_mem + 0xF) & ~0xF); - rxch->active_queue_head = NULL; - rxch->active_queue_tail = mem; - for (cnt = 0; cnt < rxch->num_bd; cnt++) { - curr_bd = mem + (cnt * bd_size); - /* for future use the last parameter contains the BD ptr */ - curr_bd->data_ptr = emac_net_alloc_rx_buf(priv, - rxch->buf_size, - (void __force **)&curr_bd->buf_token, - EMAC_DEF_RX_CH); - if (curr_bd->data_ptr == NULL) { - dev_err(emac_dev, "DaVinci EMAC: RX buf mem alloc " \ - "failed for ch %d\n", ch); - kfree(rxch); - return -ENOMEM; - } - - /* populate the hardware descriptor */ - curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head, - priv); - curr_bd->buff_ptr = dma_map_single(emac_dev, curr_bd->data_ptr, - rxch->buf_size, DMA_FROM_DEVICE); - curr_bd->off_b_len = rxch->buf_size; - curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; - - /* write back to hardware memory */ - BD_CACHE_WRITEBACK_INVALIDATE((u32) curr_bd, - EMAC_BD_LENGTH_FOR_CACHE); - curr_bd->next = rxch->active_queue_head; - rxch->active_queue_head = curr_bd; - } - - /* At this point rxCppi->activeQueueHead points to the first - RX BD ready to be given to RX HDP and rxch->active_queue_tail - points to the last RX BD - */ - return 0; -} - -/** - * emac_rxch_teardown: RX channel teardown - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to teardown RX channel - * - */ -static void emac_rxch_teardown(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ - - while ((emac_read(EMAC_RXCP(ch)) & EMAC_TEARDOWN_VALUE) != - EMAC_TEARDOWN_VALUE) { - /* wait till tx teardown complete */ - cpu_relax(); /* TODO: check if this helps ... */ - --teardown_cnt; - if (0 == teardown_cnt) { - dev_err(emac_dev, "EMAC: RX teardown aborted\n"); - break; - } - } - emac_write(EMAC_RXCP(ch), EMAC_TEARDOWN_VALUE); -} - -/** - * emac_stop_rxch: Stop RX channel operation - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to stop RX channel operation - * - */ -static void emac_stop_rxch(struct emac_priv *priv, u32 ch) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - - if (rxch) { - rxch->teardown_pending = 1; - emac_write(EMAC_RXTEARDOWN, ch); - /* wait for teardown complete */ - emac_rxch_teardown(priv, ch); - rxch->teardown_pending = 0; - emac_write(EMAC_RXINTMASKCLEAR, BIT(ch)); - } -} - -/** - * emac_cleanup_rxch: Book-keep function to clean RX channel resources - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to clean up RX channel resources - * - */ -static void emac_cleanup_rxch(struct emac_priv *priv, u32 ch) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - struct emac_rx_bd __iomem *curr_bd; - - if (rxch) { - /* free the receive buffers previously allocated */ - curr_bd = rxch->active_queue_head; - while (curr_bd) { - if (curr_bd->buf_token) { - dma_unmap_single(&priv->ndev->dev, - curr_bd->buff_ptr, - curr_bd->off_b_len - & EMAC_RX_BD_BUF_SIZE, - DMA_FROM_DEVICE); - - dev_kfree_skb_any((struct sk_buff *)\ - curr_bd->buf_token); - } - curr_bd = curr_bd->next; - } - if (rxch->bd_mem) - rxch->bd_mem = NULL; - kfree(rxch); - priv->rxch[ch] = NULL; - } -} - -/** * emac_set_type0addr: Set EMAC Type0 mac address * @priv: The DaVinci EMAC private adapter structure * @ch: RX channel number @@ -1987,194 +1249,6 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) } /** - * emac_addbd_to_rx_queue: Recycle RX buffer descriptor - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number to process buffer descriptors for - * @curr_bd: current buffer descriptor - * @buffer: buffer pointer for descriptor - * @buf_token: buffer token (stores skb information) - * - * Prepares the recycled buffer descriptor and addes it to hardware - * receive queue - if queue empty this descriptor becomes the head - * else addes the descriptor to end of queue - * - */ -static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch, - struct emac_rx_bd __iomem *curr_bd, - char *buffer, void *buf_token) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - - /* populate the hardware descriptor */ - curr_bd->h_next = 0; - curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buffer, - rxch->buf_size, DMA_FROM_DEVICE); - curr_bd->off_b_len = rxch->buf_size; - curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; - curr_bd->next = NULL; - curr_bd->data_ptr = buffer; - curr_bd->buf_token = buf_token; - - /* write back */ - BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - if (rxch->active_queue_head == NULL) { - rxch->active_queue_head = curr_bd; - rxch->active_queue_tail = curr_bd; - if (0 != rxch->queue_active) { - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(rxch->active_queue_head, priv)); - rxch->queue_active = 1; - } - } else { - struct emac_rx_bd __iomem *tail_bd; - u32 frame_status; - - tail_bd = rxch->active_queue_tail; - rxch->active_queue_tail = curr_bd; - tail_bd->next = curr_bd; - tail_bd = EMAC_VIRT_NOCACHE(tail_bd); - tail_bd->h_next = emac_virt_to_phys(curr_bd, priv); - frame_status = tail_bd->mode; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - frame_status &= ~(EMAC_CPPI_EOQ_BIT); - tail_bd->mode = frame_status; - ++rxch->end_of_queue_add; - } - } - ++rxch->recycled_bd; -} - -/** - * emac_net_rx_cb: Prepares packet and sends to upper layer - * @priv: The DaVinci EMAC private adapter structure - * @net_pkt_list: Network packet list (received packets) - * - * Invalidates packet buffer memory and sends the received packet to upper - * layer - * - * Returns success or appropriate error code (none as of now) - */ -static int emac_net_rx_cb(struct emac_priv *priv, - struct emac_netpktobj *net_pkt_list) -{ - struct net_device *ndev = priv->ndev; - struct sk_buff *p_skb = net_pkt_list->pkt_token; - /* set length of packet */ - skb_put(p_skb, net_pkt_list->pkt_length); - p_skb->protocol = eth_type_trans(p_skb, priv->ndev); - netif_receive_skb(p_skb); - ndev->stats.rx_bytes += net_pkt_list->pkt_length; - ndev->stats.rx_packets++; - return 0; -} - -/** - * emac_rx_bdproc: RX buffer descriptor (packet) processing - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number to process buffer descriptors for - * @budget: number of packets allowed to process - * @pending: indication to caller that packets are pending to process - * - * Processes RX buffer descriptors - checks ownership bit on the RX buffer - * descriptor, sends the receive packet to upper layer, allocates a new SKB - * and recycles the buffer descriptor (requeues it in hardware RX queue). - * Only "budget" number of packets are processed and indication of pending - * packets provided to the caller. - * - * Returns number of packets processed (and indication of pending packets) - */ -static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) -{ - unsigned long flags; - u32 frame_status; - u32 pkts_processed = 0; - char *new_buffer; - struct emac_rx_bd __iomem *curr_bd; - struct emac_rx_bd __iomem *last_bd; - struct emac_netpktobj *curr_pkt, pkt_obj; - struct emac_netbufobj buf_obj; - struct emac_netbufobj *rx_buf_obj; - void *new_buf_token; - struct emac_rxch *rxch = priv->rxch[ch]; - - if (unlikely(1 == rxch->teardown_pending)) - return 0; - ++rxch->proc_count; - spin_lock_irqsave(&priv->rx_lock, flags); - pkt_obj.buf_list = &buf_obj; - curr_pkt = &pkt_obj; - curr_bd = rxch->active_queue_head; - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - - while ((curr_bd) && - ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && - (pkts_processed < budget)) { - - new_buffer = emac_net_alloc_rx_buf(priv, rxch->buf_size, - &new_buf_token, EMAC_DEF_RX_CH); - if (unlikely(NULL == new_buffer)) { - ++rxch->out_of_rx_buffers; - goto end_emac_rx_bdproc; - } - - /* populate received packet data structure */ - rx_buf_obj = &curr_pkt->buf_list[0]; - rx_buf_obj->data_ptr = (char *)curr_bd->data_ptr; - rx_buf_obj->length = curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE; - rx_buf_obj->buf_token = curr_bd->buf_token; - - dma_unmap_single(&priv->ndev->dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_FROM_DEVICE); - - curr_pkt->pkt_token = curr_pkt->buf_list->buf_token; - curr_pkt->num_bufs = 1; - curr_pkt->pkt_length = - (frame_status & EMAC_RX_BD_PKT_LENGTH_MASK); - emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd, priv)); - ++rxch->processed_bd; - last_bd = curr_bd; - curr_bd = last_bd->next; - rxch->active_queue_head = curr_bd; - - /* check if end of RX queue ? */ - if (frame_status & EMAC_CPPI_EOQ_BIT) { - if (curr_bd) { - ++rxch->mis_queued_packets; - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - } else { - ++rxch->end_of_queue; - rxch->queue_active = 0; - } - } - - /* recycle BD */ - emac_addbd_to_rx_queue(priv, ch, last_bd, new_buffer, - new_buf_token); - - /* return the packet to the user - BD ptr passed in - * last parameter for potential *future* use */ - spin_unlock_irqrestore(&priv->rx_lock, flags); - emac_net_rx_cb(priv, curr_pkt); - spin_lock_irqsave(&priv->rx_lock, flags); - curr_bd = rxch->active_queue_head; - if (curr_bd) { - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - } - ++pkts_processed; - } - -end_emac_rx_bdproc: - spin_unlock_irqrestore(&priv->rx_lock, flags); - return pkts_processed; -} - -/** * emac_hw_enable: Enable EMAC hardware for packet transmission/reception * @priv: The DaVinci EMAC private adapter structure * @@ -2700,8 +1774,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->ndev = ndev; priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG); - spin_lock_init(&priv->tx_lock); - spin_lock_init(&priv->rx_lock); spin_lock_init(&priv->lock); pdata = pdev->dev.platform_data; @@ -2749,8 +1821,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) ndev->base_addr = (unsigned long)priv->remap_addr; priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset; - priv->ctrl_ram_size = pdata->ctrl_ram_size; - priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset; hw_ram_addr = pdata->hw_ram_addr; if (!hw_ram_addr) -- 1.7.0.4 From cyril at ti.com Tue Sep 7 15:25:40 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 7 Sep 2010 16:25:40 -0400 Subject: [PATCH v3 08/10] net: davinci_emac: separate out cpdma code In-Reply-To: <1283891142-15522-1-git-send-email-cyril@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> Message-ID: <1283891142-15522-9-git-send-email-cyril@ti.com> In addition to being embedded into the EMAC controller, the CPDMA hardware block is used in TI's CPSW switch controller. Fortunately, the programming interface to this hardware block remains pretty nicely consistent across these devices. This patch adds a new CPDMA services layer, which can then be reused across EMAC and CPSW drivers. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller --- drivers/net/Kconfig | 10 + drivers/net/Makefile | 1 + drivers/net/davinci_cpdma.c | 837 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/davinci_cpdma.h | 105 ++++++ 4 files changed, 953 insertions(+), 0 deletions(-) create mode 100644 drivers/net/davinci_cpdma.c create mode 100644 drivers/net/davinci_cpdma.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 911e7f1..775fd87 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -952,6 +952,7 @@ config TI_DAVINCI_EMAC tristate "TI DaVinci EMAC Support" depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) select TI_DAVINCI_MDIO + select TI_DAVINCI_CPDMA select PHYLIB help This driver supports TI's DaVinci Ethernet . @@ -969,6 +970,15 @@ config TI_DAVINCI_MDIO To compile this driver as a module, choose M here: the module will be called davinci_mdio. This is recommended. +config TI_DAVINCI_CPDMA + tristate "TI DaVinci CPDMA Support" + depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + help + This driver supports TI's DaVinci CPDMA dma engine. + + To compile this driver as a module, choose M here: the module + will be called davinci_cpdma. This is recommended. + config DM9000 tristate "DM9000 support" depends on ARM || BLACKFIN || MIPS diff --git a/drivers/net/Makefile b/drivers/net/Makefile index d38a7ab..65da885 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_PHYLIB) += phy/ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o +obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_E1000E) += e1000e/ diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c new file mode 100644 index 0000000..ab7ecd7 --- /dev/null +++ b/drivers/net/davinci_cpdma.c @@ -0,0 +1,837 @@ +/* + * Texas Instruments CPDMA Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "davinci_cpdma.h" + +/* DMA Registers */ +#define CPDMA_TXIDVER 0x00 +#define CPDMA_TXCONTROL 0x04 +#define CPDMA_TXTEARDOWN 0x08 +#define CPDMA_RXIDVER 0x10 +#define CPDMA_RXCONTROL 0x14 +#define CPDMA_SOFTRESET 0x1c +#define CPDMA_RXTEARDOWN 0x18 +#define CPDMA_TXINTSTATRAW 0x80 +#define CPDMA_TXINTSTATMASKED 0x84 +#define CPDMA_TXINTMASKSET 0x88 +#define CPDMA_TXINTMASKCLEAR 0x8c +#define CPDMA_MACINVECTOR 0x90 +#define CPDMA_MACEOIVECTOR 0x94 +#define CPDMA_RXINTSTATRAW 0xa0 +#define CPDMA_RXINTSTATMASKED 0xa4 +#define CPDMA_RXINTMASKSET 0xa8 +#define CPDMA_RXINTMASKCLEAR 0xac +#define CPDMA_DMAINTSTATRAW 0xb0 +#define CPDMA_DMAINTSTATMASKED 0xb4 +#define CPDMA_DMAINTMASKSET 0xb8 +#define CPDMA_DMAINTMASKCLEAR 0xbc +#define CPDMA_DMAINT_HOSTERR BIT(1) + +/* the following exist only if has_ext_regs is set */ +#define CPDMA_DMACONTROL 0x20 +#define CPDMA_DMASTATUS 0x24 +#define CPDMA_RXBUFFOFS 0x28 +#define CPDMA_EM_CONTROL 0x2c + +/* Descriptor mode bits */ +#define CPDMA_DESC_SOP BIT(31) +#define CPDMA_DESC_EOP BIT(30) +#define CPDMA_DESC_OWNER BIT(29) +#define CPDMA_DESC_EOQ BIT(28) +#define CPDMA_DESC_TD_COMPLETE BIT(27) +#define CPDMA_DESC_PASS_CRC BIT(26) + +#define CPDMA_TEARDOWN_VALUE 0xfffffffc + +struct cpdma_desc { + /* hardware fields */ + u32 hw_next; + u32 hw_buffer; + u32 hw_len; + u32 hw_mode; + /* software fields */ + void *sw_token; + u32 sw_buffer; + u32 sw_len; +}; + +struct cpdma_desc_pool { + u32 phys; + void __iomem *iomap; /* ioremap map */ + void *cpumap; /* dma_alloc map */ + int desc_size, mem_size; + int num_desc, used_desc; + unsigned long *bitmap; + struct device *dev; + spinlock_t lock; +}; + +enum cpdma_state { + CPDMA_STATE_IDLE, + CPDMA_STATE_ACTIVE, + CPDMA_STATE_TEARDOWN, +}; + +struct cpdma_ctlr { + enum cpdma_state state; + struct cpdma_params params; + struct device *dev; + struct cpdma_desc_pool *pool; + spinlock_t lock; + struct cpdma_chan *channels[2 * CPDMA_MAX_CHANNELS]; +}; + +struct cpdma_chan { + enum cpdma_state state; + struct cpdma_ctlr *ctlr; + int chan_num; + spinlock_t lock; + struct cpdma_desc __iomem *head, *tail; + int count; + void __iomem *hdp, *cp, *rxfree; + u32 mask; + cpdma_handler_fn handler; + enum dma_data_direction dir; + struct cpdma_chan_stats stats; + /* offsets into dmaregs */ + int int_set, int_clear, td; +}; + +/* The following make access to common cpdma_ctlr params more readable */ +#define dmaregs params.dmaregs +#define num_chan params.num_chan + +/* various accessors */ +#define dma_reg_read(ctlr, ofs) __raw_readl((ctlr)->dmaregs + (ofs)) +#define chan_read(chan, fld) __raw_readl((chan)->fld) +#define desc_read(desc, fld) __raw_readl(&(desc)->fld) +#define dma_reg_write(ctlr, ofs, v) __raw_writel(v, (ctlr)->dmaregs + (ofs)) +#define chan_write(chan, fld, v) __raw_writel(v, (chan)->fld) +#define desc_write(desc, fld, v) __raw_writel((u32)(v), &(desc)->fld) + +/* + * Utility constructs for a cpdma descriptor pool. Some devices (e.g. davinci + * emac) have dedicated on-chip memory for these descriptors. Some other + * devices (e.g. cpsw switches) use plain old memory. Descriptor pools + * abstract out these details + */ +static struct cpdma_desc_pool * +cpdma_desc_pool_create(struct device *dev, u32 phys, int size, int align) +{ + int bitmap_size; + struct cpdma_desc_pool *pool; + + pool = kzalloc(sizeof(*pool), GFP_KERNEL); + if (!pool) + return NULL; + + spin_lock_init(&pool->lock); + + pool->dev = dev; + pool->mem_size = size; + pool->desc_size = ALIGN(sizeof(struct cpdma_desc), align); + pool->num_desc = size / pool->desc_size; + + bitmap_size = (pool->num_desc / BITS_PER_LONG) * sizeof(long); + pool->bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!pool->bitmap) + goto fail; + + if (phys) { + pool->phys = phys; + pool->iomap = ioremap(phys, size); + } else { + pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys, + GFP_KERNEL); + pool->iomap = (void __force __iomem *)pool->cpumap; + } + + if (pool->iomap) + return pool; + +fail: + kfree(pool->bitmap); + kfree(pool); + return NULL; +} + +static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool) +{ + unsigned long flags; + + if (!pool) + return; + + spin_lock_irqsave(&pool->lock, flags); + WARN_ON(pool->used_desc); + kfree(pool->bitmap); + if (pool->cpumap) { + dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap, + pool->phys); + } else { + iounmap(pool->iomap); + } + spin_unlock_irqrestore(&pool->lock, flags); + kfree(pool); +} + +static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool, + struct cpdma_desc __iomem *desc) +{ + if (!desc) + return 0; + return pool->phys + (__force dma_addr_t)desc - + (__force dma_addr_t)pool->iomap; +} + +static inline struct cpdma_desc __iomem * +desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma) +{ + return dma ? pool->iomap + dma - pool->phys : NULL; +} + +static struct cpdma_desc __iomem * +cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc) +{ + unsigned long flags; + int index; + struct cpdma_desc __iomem *desc = NULL; + + spin_lock_irqsave(&pool->lock, flags); + + index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0, + num_desc, 0); + if (index < pool->num_desc) { + bitmap_set(pool->bitmap, index, num_desc); + desc = pool->iomap + pool->desc_size * index; + pool->used_desc++; + } + + spin_unlock_irqrestore(&pool->lock, flags); + return desc; +} + +static void cpdma_desc_free(struct cpdma_desc_pool *pool, + struct cpdma_desc __iomem *desc, int num_desc) +{ + unsigned long flags, index; + + index = ((unsigned long)desc - (unsigned long)pool->iomap) / + pool->desc_size; + spin_lock_irqsave(&pool->lock, flags); + bitmap_clear(pool->bitmap, index, num_desc); + pool->used_desc--; + spin_unlock_irqrestore(&pool->lock, flags); +} + +struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params) +{ + struct cpdma_ctlr *ctlr; + + ctlr = kzalloc(sizeof(*ctlr), GFP_KERNEL); + if (!ctlr) + return NULL; + + ctlr->state = CPDMA_STATE_IDLE; + ctlr->params = *params; + ctlr->dev = params->dev; + spin_lock_init(&ctlr->lock); + + ctlr->pool = cpdma_desc_pool_create(ctlr->dev, + ctlr->params.desc_mem_phys, + ctlr->params.desc_mem_size, + ctlr->params.desc_align); + if (!ctlr->pool) { + kfree(ctlr); + return NULL; + } + + if (WARN_ON(ctlr->num_chan > CPDMA_MAX_CHANNELS)) + ctlr->num_chan = CPDMA_MAX_CHANNELS; + return ctlr; +} + +int cpdma_ctlr_start(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_IDLE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EBUSY; + } + + if (ctlr->params.has_soft_reset) { + unsigned long timeout = jiffies + HZ/10; + + dma_reg_write(ctlr, CPDMA_SOFTRESET, 1); + while (time_before(jiffies, timeout)) { + if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0) + break; + } + WARN_ON(!time_before(jiffies, timeout)); + } + + for (i = 0; i < ctlr->num_chan; i++) { + __raw_writel(0, ctlr->params.txhdp + 4 * i); + __raw_writel(0, ctlr->params.rxhdp + 4 * i); + __raw_writel(0, ctlr->params.txcp + 4 * i); + __raw_writel(0, ctlr->params.rxcp + 4 * i); + } + + dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); + dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); + + dma_reg_write(ctlr, CPDMA_TXCONTROL, 1); + dma_reg_write(ctlr, CPDMA_RXCONTROL, 1); + + ctlr->state = CPDMA_STATE_ACTIVE; + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_start(ctlr->channels[i]); + } + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EINVAL; + } + + ctlr->state = CPDMA_STATE_TEARDOWN; + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_stop(ctlr->channels[i]); + } + + dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); + dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); + + dma_reg_write(ctlr, CPDMA_TXCONTROL, 0); + dma_reg_write(ctlr, CPDMA_RXCONTROL, 0); + + ctlr->state = CPDMA_STATE_IDLE; + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int ret = 0, i; + + if (!ctlr) + return -EINVAL; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_IDLE) + cpdma_ctlr_stop(ctlr); + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_destroy(ctlr->channels[i]); + } + + cpdma_desc_pool_destroy(ctlr->pool); + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(ctlr); + return ret; +} + +int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable) +{ + unsigned long flags; + int i, reg; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EINVAL; + } + + reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR; + dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR); + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_int_ctrl(ctlr->channels[i], enable); + } + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr) +{ + dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0); +} + +struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, + cpdma_handler_fn handler) +{ + struct cpdma_chan *chan; + int ret, offset = (chan_num % CPDMA_MAX_CHANNELS) * 4; + unsigned long flags; + + if (__chan_linear(chan_num) >= ctlr->num_chan) + return NULL; + + ret = -ENOMEM; + chan = kzalloc(sizeof(*chan), GFP_KERNEL); + if (!chan) + goto err_chan_alloc; + + spin_lock_irqsave(&ctlr->lock, flags); + ret = -EBUSY; + if (ctlr->channels[chan_num]) + goto err_chan_busy; + + chan->ctlr = ctlr; + chan->state = CPDMA_STATE_IDLE; + chan->chan_num = chan_num; + chan->handler = handler; + + if (is_rx_chan(chan)) { + chan->hdp = ctlr->params.rxhdp + offset; + chan->cp = ctlr->params.rxcp + offset; + chan->rxfree = ctlr->params.rxfree + offset; + chan->int_set = CPDMA_RXINTMASKSET; + chan->int_clear = CPDMA_RXINTMASKCLEAR; + chan->td = CPDMA_RXTEARDOWN; + chan->dir = DMA_FROM_DEVICE; + } else { + chan->hdp = ctlr->params.txhdp + offset; + chan->cp = ctlr->params.txcp + offset; + chan->int_set = CPDMA_TXINTMASKSET; + chan->int_clear = CPDMA_TXINTMASKCLEAR; + chan->td = CPDMA_TXTEARDOWN; + chan->dir = DMA_TO_DEVICE; + } + chan->mask = BIT(chan_linear(chan)); + + spin_lock_init(&chan->lock); + + ctlr->channels[chan_num] = chan; + spin_unlock_irqrestore(&ctlr->lock, flags); + return chan; + +err_chan_busy: + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(chan); +err_chan_alloc: + return ERR_PTR(ret); +} + +int cpdma_chan_destroy(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + unsigned long flags; + + if (!chan) + return -EINVAL; + + spin_lock_irqsave(&ctlr->lock, flags); + if (chan->state != CPDMA_STATE_IDLE) + cpdma_chan_stop(chan); + ctlr->channels[chan->chan_num] = NULL; + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(chan); + return 0; +} + +int cpdma_chan_get_stats(struct cpdma_chan *chan, + struct cpdma_chan_stats *stats) +{ + unsigned long flags; + if (!chan) + return -EINVAL; + spin_lock_irqsave(&chan->lock, flags); + memcpy(stats, &chan->stats, sizeof(*stats)); + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +static void __cpdma_chan_submit(struct cpdma_chan *chan, + struct cpdma_desc __iomem *desc) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *prev = chan->tail; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t desc_dma; + + desc_dma = desc_phys(pool, desc); + + /* simple case - idle channel */ + if (!chan->head) { + chan->stats.head_enqueue++; + chan->head = desc; + chan->tail = desc; + if (chan->state == CPDMA_STATE_ACTIVE) + chan_write(chan, hdp, desc_dma); + return; + } + + /* first chain the descriptor at the tail of the list */ + desc_write(prev, hw_next, desc_dma); + chan->tail = desc; + chan->stats.tail_enqueue++; + + /* next check if EOQ has been triggered already */ + if (desc_read(prev, hw_mode) & CPDMA_DESC_EOQ && + chan->state == CPDMA_STATE_ACTIVE) { + chan_write(chan, hdp, desc_dma); + chan->stats.misqueued++; + } +} + +int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, + int len, gfp_t gfp_mask) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *desc; + dma_addr_t buffer; + unsigned long flags; + u32 mode; + int ret = 0; + + spin_lock_irqsave(&chan->lock, flags); + + if (chan->state == CPDMA_STATE_TEARDOWN) { + ret = -EINVAL; + goto unlock_ret; + } + + desc = cpdma_desc_alloc(ctlr->pool, 1); + if (!desc) { + chan->stats.desc_alloc_fail++; + ret = -ENOMEM; + goto unlock_ret; + } + + if (len < ctlr->params.min_packet_size) { + len = ctlr->params.min_packet_size; + chan->stats.runt_transmit_buff++; + } + + buffer = dma_map_single(ctlr->dev, data, len, chan->dir); + mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP; + + desc_write(desc, hw_next, 0); + desc_write(desc, hw_buffer, buffer); + desc_write(desc, hw_len, len); + desc_write(desc, hw_mode, mode | len); + desc_write(desc, sw_token, token); + desc_write(desc, sw_buffer, buffer); + desc_write(desc, sw_len, len); + + __cpdma_chan_submit(chan, desc); + + if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree) + chan_write(chan, rxfree, 1); + + chan->count++; + +unlock_ret: + spin_unlock_irqrestore(&chan->lock, flags); + return ret; +} + +static void __cpdma_chan_free(struct cpdma_chan *chan, + struct cpdma_desc __iomem *desc, + int outlen, int status) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t buff_dma; + int origlen; + void *token; + + token = (void *)desc_read(desc, sw_token); + buff_dma = desc_read(desc, sw_buffer); + origlen = desc_read(desc, sw_len); + + dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir); + cpdma_desc_free(pool, desc, 1); + (*chan->handler)(token, outlen, status); +} + +static int __cpdma_chan_process(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *desc; + int status, outlen; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t desc_dma; + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + + desc = chan->head; + if (!desc) { + chan->stats.empty_dequeue++; + status = -ENOENT; + goto unlock_ret; + } + desc_dma = desc_phys(pool, desc); + + status = __raw_readl(&desc->hw_mode); + outlen = status & 0x7ff; + if (status & CPDMA_DESC_OWNER) { + chan->stats.busy_dequeue++; + status = -EBUSY; + goto unlock_ret; + } + status = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE); + + chan->head = desc_from_phys(pool, desc_read(desc, hw_next)); + chan_write(chan, cp, desc_dma); + chan->count--; + chan->stats.good_dequeue++; + + spin_unlock_irqrestore(&chan->lock, flags); + + __cpdma_chan_free(chan, desc, outlen, status); + return status; + +unlock_ret: + spin_unlock_irqrestore(&chan->lock, flags); + return status; +} + +int cpdma_chan_process(struct cpdma_chan *chan, int quota) +{ + int used = 0, ret = 0; + + if (chan->state != CPDMA_STATE_ACTIVE) + return -EINVAL; + + while (used < quota) { + ret = __cpdma_chan_process(chan); + if (ret < 0) + break; + used++; + } + return used; +} + +int cpdma_chan_start(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_IDLE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EBUSY; + } + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + dma_reg_write(ctlr, chan->int_set, chan->mask); + chan->state = CPDMA_STATE_ACTIVE; + if (chan->head) { + chan_write(chan, hdp, desc_phys(pool, chan->head)); + if (chan->rxfree) + chan_write(chan, rxfree, chan->count); + } + + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +int cpdma_chan_stop(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + unsigned long flags; + int ret; + unsigned long timeout; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + + chan->state = CPDMA_STATE_TEARDOWN; + dma_reg_write(ctlr, chan->int_clear, chan->mask); + + /* trigger teardown */ + dma_reg_write(ctlr, chan->td, chan->chan_num); + + /* wait for teardown complete */ + timeout = jiffies + HZ/10; /* 100 msec */ + while (time_before(jiffies, timeout)) { + u32 cp = chan_read(chan, cp); + if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE) + break; + cpu_relax(); + } + WARN_ON(!time_before(jiffies, timeout)); + chan_write(chan, cp, CPDMA_TEARDOWN_VALUE); + + /* handle completed packets */ + do { + ret = __cpdma_chan_process(chan); + if (ret < 0) + break; + } while ((ret & CPDMA_DESC_TD_COMPLETE) == 0); + + /* remaining packets haven't been tx/rx'ed, clean them up */ + while (chan->head) { + struct cpdma_desc __iomem *desc = chan->head; + dma_addr_t next_dma; + + next_dma = desc_read(desc, hw_next); + chan->head = desc_from_phys(pool, next_dma); + chan->stats.teardown_dequeue++; + + /* issue callback without locks held */ + spin_unlock_irqrestore(&chan->lock, flags); + __cpdma_chan_free(chan, desc, 0, -ENOSYS); + spin_lock_irqsave(&chan->lock, flags); + } + + chan->state = CPDMA_STATE_IDLE; + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable) +{ + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + + dma_reg_write(chan->ctlr, enable ? chan->int_set : chan->int_clear, + chan->mask); + spin_unlock_irqrestore(&chan->lock, flags); + + return 0; +} + +struct cpdma_control_info { + u32 reg; + u32 shift, mask; + int access; +#define ACCESS_RO BIT(0) +#define ACCESS_WO BIT(1) +#define ACCESS_RW (ACCESS_RO | ACCESS_WO) +}; + +struct cpdma_control_info controls[] = { + [CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO}, + [CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL, 4, 1, ACCESS_RW}, + [CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL, 2, 1, ACCESS_RW}, + [CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL, 1, 1, ACCESS_RW}, + [CPDMA_TX_PRIO_FIXED] = {CPDMA_DMACONTROL, 0, 1, ACCESS_RW}, + [CPDMA_STAT_IDLE] = {CPDMA_DMASTATUS, 31, 1, ACCESS_RO}, + [CPDMA_STAT_TX_ERR_CODE] = {CPDMA_DMASTATUS, 20, 0xf, ACCESS_RW}, + [CPDMA_STAT_TX_ERR_CHAN] = {CPDMA_DMASTATUS, 16, 0x7, ACCESS_RW}, + [CPDMA_STAT_RX_ERR_CODE] = {CPDMA_DMASTATUS, 12, 0xf, ACCESS_RW}, + [CPDMA_STAT_RX_ERR_CHAN] = {CPDMA_DMASTATUS, 8, 0x7, ACCESS_RW}, + [CPDMA_RX_BUFFER_OFFSET] = {CPDMA_RXBUFFOFS, 0, 0xffff, ACCESS_RW}, +}; + +int cpdma_control_get(struct cpdma_ctlr *ctlr, int control) +{ + unsigned long flags; + struct cpdma_control_info *info = &controls[control]; + int ret; + + spin_lock_irqsave(&ctlr->lock, flags); + + ret = -ENOTSUPP; + if (!ctlr->params.has_ext_regs) + goto unlock_ret; + + ret = -EINVAL; + if (ctlr->state != CPDMA_STATE_ACTIVE) + goto unlock_ret; + + ret = -ENOENT; + if (control < 0 || control >= ARRAY_SIZE(controls)) + goto unlock_ret; + + ret = -EPERM; + if ((info->access & ACCESS_RO) != ACCESS_RO) + goto unlock_ret; + + ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask; + +unlock_ret: + spin_unlock_irqrestore(&ctlr->lock, flags); + return ret; +} + +int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value) +{ + unsigned long flags; + struct cpdma_control_info *info = &controls[control]; + int ret; + u32 val; + + spin_lock_irqsave(&ctlr->lock, flags); + + ret = -ENOTSUPP; + if (!ctlr->params.has_ext_regs) + goto unlock_ret; + + ret = -EINVAL; + if (ctlr->state != CPDMA_STATE_ACTIVE) + goto unlock_ret; + + ret = -ENOENT; + if (control < 0 || control >= ARRAY_SIZE(controls)) + goto unlock_ret; + + ret = -EPERM; + if ((info->access & ACCESS_WO) != ACCESS_WO) + goto unlock_ret; + + val = dma_reg_read(ctlr, info->reg); + val &= ~(info->mask << info->shift); + val |= (value & info->mask) << info->shift; + dma_reg_write(ctlr, info->reg, val); + ret = 0; + +unlock_ret: + spin_unlock_irqrestore(&ctlr->lock, flags); + return ret; +} diff --git a/drivers/net/davinci_cpdma.h b/drivers/net/davinci_cpdma.h new file mode 100644 index 0000000..d50ee35 --- /dev/null +++ b/drivers/net/davinci_cpdma.h @@ -0,0 +1,105 @@ +/* + * Texas Instruments CPDMA Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __DAVINCI_CPDMA_H__ +#define __DAVINCI_CPDMA_H__ + +#define CPDMA_MAX_CHANNELS BITS_PER_LONG + +#define tx_chan_num(chan) (chan) +#define rx_chan_num(chan) ((chan) + CPDMA_MAX_CHANNELS) +#define is_rx_chan(chan) ((chan)->chan_num >= CPDMA_MAX_CHANNELS) +#define is_tx_chan(chan) (!is_rx_chan(chan)) +#define __chan_linear(chan_num) ((chan_num) & (CPDMA_MAX_CHANNELS - 1)) +#define chan_linear(chan) __chan_linear((chan)->chan_num) + +struct cpdma_params { + struct device *dev; + void __iomem *dmaregs; + void __iomem *txhdp, *rxhdp, *txcp, *rxcp; + void __iomem *rxthresh, *rxfree; + int num_chan; + bool has_soft_reset; + int min_packet_size; + u32 desc_mem_phys; + int desc_mem_size; + int desc_align; + + /* + * Some instances of embedded cpdma controllers have extra control and + * status registers. The following flag enables access to these + * "extended" registers. + */ + bool has_ext_regs; +}; + +struct cpdma_chan_stats { + u32 head_enqueue; + u32 tail_enqueue; + u32 pad_enqueue; + u32 misqueued; + u32 desc_alloc_fail; + u32 pad_alloc_fail; + u32 runt_receive_buff; + u32 runt_transmit_buff; + u32 empty_dequeue; + u32 busy_dequeue; + u32 good_dequeue; + u32 teardown_dequeue; +}; + +struct cpdma_ctlr; +struct cpdma_chan; + +typedef void (*cpdma_handler_fn)(void *token, int len, int status); + +struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params); +int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_start(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr); + +struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, + cpdma_handler_fn handler); +int cpdma_chan_destroy(struct cpdma_chan *chan); +int cpdma_chan_start(struct cpdma_chan *chan); +int cpdma_chan_stop(struct cpdma_chan *chan); + +int cpdma_chan_get_stats(struct cpdma_chan *chan, + struct cpdma_chan_stats *stats); +int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, + int len, gfp_t gfp_mask); +int cpdma_chan_process(struct cpdma_chan *chan, int quota); + +int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable); +void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr); +int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable); + +enum cpdma_control { + CPDMA_CMD_IDLE, /* write-only */ + CPDMA_COPY_ERROR_FRAMES, /* read-write */ + CPDMA_RX_OFF_LEN_UPDATE, /* read-write */ + CPDMA_RX_OWNERSHIP_FLIP, /* read-write */ + CPDMA_TX_PRIO_FIXED, /* read-write */ + CPDMA_STAT_IDLE, /* read-only */ + CPDMA_STAT_TX_ERR_CHAN, /* read-only */ + CPDMA_STAT_TX_ERR_CODE, /* read-only */ + CPDMA_STAT_RX_ERR_CHAN, /* read-only */ + CPDMA_STAT_RX_ERR_CODE, /* read-only */ + CPDMA_RX_BUFFER_OFFSET, /* read-write */ +}; + +int cpdma_control_get(struct cpdma_ctlr *ctlr, int control); +int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value); + +#endif -- 1.7.0.4 From cyril at ti.com Tue Sep 7 15:25:41 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 7 Sep 2010 16:25:41 -0400 Subject: [PATCH v3 09/10] net: davinci_emac: switch to new cpdma layer In-Reply-To: <1283891142-15522-1-git-send-email-cyril@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> Message-ID: <1283891142-15522-10-git-send-email-cyril@ti.com> This patch hooks up the emac driver with the newly separated cpdma driver. Key differences introduced here: - The old buffer list scheme is no longer required - The original code maintained mac address per rx channel, even if only one rx channel was being used. With this change, mac address is maintained device wide. If support for multiple rx channels is added in future, this will need to be reworked a bit. - The new CPDMA code handles short packets better than before. The earlier code was adjusting the length up, without ensuring that the tail end of the padding was cleared - a possible security issue. This has been fixed to use skb_padto(). Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller --- drivers/net/davinci_emac.c | 232 ++++++++++++++++++++++++++++---------------- 1 files changed, 147 insertions(+), 85 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 036681a..4147d32 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -63,6 +63,8 @@ #include #include +#include "davinci_cpdma.h" + static int debug_level; module_param(debug_level, int, 0); MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)"); @@ -113,6 +115,7 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_FRAME_SIZE (1500 + 14 + 4 + 4) #define EMAC_DEF_TX_CH (0) /* Default 0th channel */ #define EMAC_DEF_RX_CH (0) /* Default 0th channel */ +#define EMAC_DEF_RX_NUM_DESC (128) #define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */ #define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */ #define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */ @@ -460,6 +463,9 @@ struct emac_priv { u32 hw_ram_addr; struct emac_txch *txch[EMAC_DEF_MAX_TX_CH]; struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH]; + struct cpdma_ctlr *dma; + struct cpdma_chan *txchan; + struct cpdma_chan *rxchan; u32 link; /* 1=link on, 0=link off */ u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */ u32 duplex; /* Link duplex: 0=Half, 1=Full */ @@ -1151,6 +1157,57 @@ static irqreturn_t emac_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static struct sk_buff *emac_rx_alloc(struct emac_priv *priv) +{ + struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size); + if (WARN_ON(!skb)) + return NULL; + skb->dev = priv->ndev; + skb_reserve(skb, NET_IP_ALIGN); + return skb; +} + +static void emac_rx_handler(void *token, int len, int status) +{ + struct sk_buff *skb = token; + struct net_device *ndev = skb->dev; + struct emac_priv *priv = netdev_priv(ndev); + int ret; + + if (status < 0) { + /* error */ + goto recycle; + } + + skb_put(skb, len); + skb->protocol = eth_type_trans(skb, ndev); + netif_receive_skb(skb); + ndev->stats.rx_bytes += len; + ndev->stats.rx_packets++; + + /* alloc a new packet for receive */ + skb = emac_rx_alloc(priv); + +recycle: + if (skb) { + ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, + skb_tailroom(skb), GFP_KERNEL); + WARN_ON(ret < 0); + } +} + +static void emac_tx_handler(void *token, int len, int status) +{ + struct sk_buff *skb = token; + struct net_device *ndev = skb->dev; + + if (unlikely(netif_queue_stopped(ndev))) + netif_start_queue(ndev); + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += len; + dev_kfree_skb_any(skb); +} + /** EMAC on-chip buffer descriptor memory * * WARNING: Please note that the on chip memory is used for both TX and RX @@ -1532,42 +1589,36 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) { struct device *emac_dev = &ndev->dev; int ret_code; - struct emac_netbufobj tx_buf; /* buffer obj-only single frame support */ - struct emac_netpktobj tx_packet; /* packet object */ struct emac_priv *priv = netdev_priv(ndev); /* If no link, return */ if (unlikely(!priv->link)) { if (netif_msg_tx_err(priv) && net_ratelimit()) dev_err(emac_dev, "DaVinci EMAC: No link to transmit"); - return NETDEV_TX_BUSY; + goto fail_tx; } - /* Build the buffer and packet objects - Since only single fragment is - * supported, need not set length and token in both packet & object. - * Doing so for completeness sake & to show that this needs to be done - * in multifragment case - */ - tx_packet.buf_list = &tx_buf; - tx_packet.num_bufs = 1; /* only single fragment supported */ - tx_packet.pkt_length = skb->len; - tx_packet.pkt_token = (void *)skb; - tx_buf.length = skb->len; - tx_buf.buf_token = (void *)skb; - tx_buf.data_ptr = skb->data; - ret_code = emac_send(priv, &tx_packet, EMAC_DEF_TX_CH); + ret_code = skb_padto(skb, EMAC_DEF_MIN_ETHPKTSIZE); + if (unlikely(ret_code < 0)) { + if (netif_msg_tx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "DaVinci EMAC: packet pad failed"); + goto fail_tx; + } + + ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len, + GFP_KERNEL); if (unlikely(ret_code != 0)) { - if (ret_code == EMAC_ERR_TX_OUT_OF_BD) { - if (netif_msg_tx_err(priv) && net_ratelimit()) - dev_err(emac_dev, "DaVinci EMAC: xmit() fatal"\ - " err. Out of TX BD's"); - netif_stop_queue(priv->ndev); - } - ndev->stats.tx_dropped++; - return NETDEV_TX_BUSY; + if (netif_msg_tx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "DaVinci EMAC: desc submit failed"); + goto fail_tx; } return NETDEV_TX_OK; + +fail_tx: + ndev->stats.tx_dropped++; + netif_stop_queue(ndev); + return NETDEV_TX_BUSY; } /** @@ -1590,11 +1641,8 @@ static void emac_dev_tx_timeout(struct net_device *ndev) ndev->stats.tx_errors++; emac_int_disable(priv); - emac_stop_txch(priv, EMAC_DEF_TX_CH); - emac_cleanup_txch(priv, EMAC_DEF_TX_CH); - emac_init_txch(priv, EMAC_DEF_TX_CH); - emac_write(EMAC_TXHDP(0), 0); - emac_write(EMAC_TXINTMASKSET, BIT(EMAC_DEF_TX_CH)); + cpdma_chan_stop(priv->txchan); + cpdma_chan_start(priv->txchan); emac_int_enable(priv); } @@ -1915,7 +1963,6 @@ static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr) static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) { struct emac_priv *priv = netdev_priv(ndev); - struct emac_rxch *rxch = priv->rxch[EMAC_DEF_RX_CH]; struct device *emac_dev = &priv->ndev->dev; struct sockaddr *sa = addr; @@ -1926,11 +1973,10 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); - /* If the interface is down - rxch is NULL. */ /* MAC address is configured only after the interface is enabled. */ if (netif_running(ndev)) { - memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); - emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); + memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); + emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); } if (netif_msg_drv(priv)) @@ -2139,7 +2185,7 @@ end_emac_rx_bdproc: */ static int emac_hw_enable(struct emac_priv *priv) { - u32 ch, val, mbp_enable, mac_control; + u32 val, mbp_enable, mac_control; /* Soft reset */ emac_write(EMAC_SOFTRESET, 1); @@ -2182,26 +2228,9 @@ static int emac_hw_enable(struct emac_priv *priv) emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL); priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF; - val = emac_read(EMAC_TXCONTROL); - val |= EMAC_TX_CONTROL_TX_ENABLE_VAL; - emac_write(EMAC_TXCONTROL, val); - val = emac_read(EMAC_RXCONTROL); - val |= EMAC_RX_CONTROL_RX_ENABLE_VAL; - emac_write(EMAC_RXCONTROL, val); emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL); - for (ch = 0; ch < EMAC_DEF_MAX_TX_CH; ch++) { - emac_write(EMAC_TXHDP(ch), 0); - emac_write(EMAC_TXINTMASKSET, BIT(ch)); - } - for (ch = 0; ch < EMAC_DEF_MAX_RX_CH; ch++) { - struct emac_rxch *rxch = priv->rxch[ch]; - emac_setmac(priv, ch, rxch->mac_addr); - emac_write(EMAC_RXINTMASKSET, BIT(ch)); - rxch->queue_active = 1; - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(rxch->active_queue_head, priv)); - } + emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); /* Enable MII */ val = emac_read(EMAC_MACCONTROL); @@ -2246,8 +2275,8 @@ static int emac_poll(struct napi_struct *napi, int budget) mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC; if (status & mask) { - num_tx_pkts = emac_tx_bdproc(priv, EMAC_DEF_TX_CH, - EMAC_DEF_TX_MAX_SERVICE); + num_tx_pkts = cpdma_chan_process(priv->txchan, + EMAC_DEF_TX_MAX_SERVICE); } /* TX processing */ mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC; @@ -2256,7 +2285,7 @@ static int emac_poll(struct napi_struct *napi, int budget) mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC; if (status & mask) { - num_rx_pkts = emac_rx_bdproc(priv, EMAC_DEF_RX_CH, budget); + num_rx_pkts = cpdma_chan_process(priv->rxchan, budget); } /* RX processing */ mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT; @@ -2397,9 +2426,9 @@ static int match_first_device(struct device *dev, void *data) static int emac_dev_open(struct net_device *ndev) { struct device *emac_dev = &ndev->dev; - u32 rc, cnt, ch; + u32 cnt; struct resource *res; - int q, m; + int q, m, ret; int i = 0; int k = 0; struct emac_priv *priv = netdev_priv(ndev); @@ -2411,29 +2440,21 @@ static int emac_dev_open(struct net_device *ndev) /* Configuration items */ priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN; - /* Clear basic hardware */ - for (ch = 0; ch < EMAC_MAX_TXRX_CHANNELS; ch++) { - emac_write(EMAC_TXHDP(ch), 0); - emac_write(EMAC_RXHDP(ch), 0); - emac_write(EMAC_RXHDP(ch), 0); - emac_write(EMAC_RXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); - emac_write(EMAC_TXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); - } priv->mac_hash1 = 0; priv->mac_hash2 = 0; emac_write(EMAC_MACHASH1, 0); emac_write(EMAC_MACHASH2, 0); - /* multi ch not supported - open 1 TX, 1RX ch by default */ - rc = emac_init_txch(priv, EMAC_DEF_TX_CH); - if (0 != rc) { - dev_err(emac_dev, "DaVinci EMAC: emac_init_txch() failed"); - return rc; - } - rc = emac_init_rxch(priv, EMAC_DEF_RX_CH, priv->mac_addr); - if (0 != rc) { - dev_err(emac_dev, "DaVinci EMAC: emac_init_rxch() failed"); - return rc; + for (i = 0; i < EMAC_DEF_RX_NUM_DESC; i++) { + struct sk_buff *skb = emac_rx_alloc(priv); + + if (!skb) + break; + + ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, + skb_tailroom(skb), GFP_KERNEL); + if (WARN_ON(ret < 0)) + break; } /* Request IRQ */ @@ -2458,6 +2479,8 @@ static int emac_dev_open(struct net_device *ndev) emac_set_coalesce(ndev, &coal); } + cpdma_ctlr_start(priv->dma); + priv->phydev = NULL; /* use the first phy on the bus if pdata did not give us a phy id */ if (!priv->phy_id) { @@ -2545,10 +2568,7 @@ static int emac_dev_stop(struct net_device *ndev) netif_carrier_off(ndev); emac_int_disable(priv); - emac_stop_txch(priv, EMAC_DEF_TX_CH); - emac_stop_rxch(priv, EMAC_DEF_RX_CH); - emac_cleanup_txch(priv, EMAC_DEF_TX_CH); - emac_cleanup_rxch(priv, EMAC_DEF_RX_CH); + cpdma_ctlr_stop(priv->dma); emac_write(EMAC_SOFTRESET, 1); if (priv->phydev) @@ -2653,9 +2673,10 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) struct resource *res; struct net_device *ndev; struct emac_priv *priv; - unsigned long size; + unsigned long size, hw_ram_addr; struct emac_platform_data *pdata; struct device *emac_dev; + struct cpdma_params dma_params; /* obtain emac clock from kernel */ emac_clk = clk_get(&pdev->dev, NULL); @@ -2731,11 +2752,40 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->ctrl_ram_size = pdata->ctrl_ram_size; priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset; - if (pdata->hw_ram_addr) - priv->hw_ram_addr = pdata->hw_ram_addr; - else - priv->hw_ram_addr = (u32 __force)res->start + - pdata->ctrl_ram_offset; + hw_ram_addr = pdata->hw_ram_addr; + if (!hw_ram_addr) + hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset; + + memset(&dma_params, 0, sizeof(dma_params)); + dma_params.dev = emac_dev; + dma_params.dmaregs = priv->emac_base; + dma_params.rxthresh = priv->emac_base + 0x120; + dma_params.rxfree = priv->emac_base + 0x140; + dma_params.txhdp = priv->emac_base + 0x600; + dma_params.rxhdp = priv->emac_base + 0x620; + dma_params.txcp = priv->emac_base + 0x640; + dma_params.rxcp = priv->emac_base + 0x660; + dma_params.num_chan = EMAC_MAX_TXRX_CHANNELS; + dma_params.min_packet_size = EMAC_DEF_MIN_ETHPKTSIZE; + dma_params.desc_mem_phys = hw_ram_addr; + dma_params.desc_mem_size = pdata->ctrl_ram_size; + dma_params.desc_align = 16; + + priv->dma = cpdma_ctlr_create(&dma_params); + if (!priv->dma) { + dev_err(emac_dev, "DaVinci EMAC: Error initializing DMA\n"); + rc = -ENOMEM; + goto no_dma; + } + + priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH), + emac_tx_handler); + priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH), + emac_rx_handler); + if (WARN_ON(!priv->txchan || !priv->rxchan)) { + rc = -ENOMEM; + goto no_irq_res; + } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { @@ -2778,6 +2828,12 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) netdev_reg_err: clk_disable(emac_clk); no_irq_res: + if (priv->txchan) + cpdma_chan_destroy(priv->txchan); + if (priv->rxchan) + cpdma_chan_destroy(priv->rxchan); + cpdma_ctlr_destroy(priv->dma); +no_dma: res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, res->end - res->start + 1); iounmap(priv->remap_addr); @@ -2806,6 +2862,12 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (priv->txchan) + cpdma_chan_destroy(priv->txchan); + if (priv->rxchan) + cpdma_chan_destroy(priv->rxchan); + cpdma_ctlr_destroy(priv->dma); + release_mem_region(res->start, res->end - res->start + 1); unregister_netdev(ndev); -- 1.7.0.4 From tony at atomide.com Tue Sep 7 20:00:31 2010 From: tony at atomide.com (Tony Lindgren) Date: Tue, 7 Sep 2010 18:00:31 -0700 Subject: [PATCH v3 03/10] omap: add mdio platform devices In-Reply-To: <1283891142-15522-4-git-send-email-cyril@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <1283891142-15522-4-git-send-email-cyril@ti.com> Message-ID: <20100908010031.GF22507@atomide.com> * Cyril Chemparathy [100907 13:17]: > This patch adds mdio platform devices on SoCs that have the necessary > hardware. Clock lookup entries (aliases) have also been added, so that the > MDIO and EMAC drivers can independently enable/disable a shared underlying > clock. Further, the EMAC MMR region has been split down into separate MDIO > and EMAC regions. > > Signed-off-by: Cyril Chemparathy > Acked-by: David S. Miller Looks good to me from omap point of view: Acked-by: Tony Lindgren From tony at atomide.com Tue Sep 7 20:00:56 2010 From: tony at atomide.com (Tony Lindgren) Date: Tue, 7 Sep 2010 18:00:56 -0700 Subject: [PATCH v3 06/10] omap: cleanup unused davinci mdio arch code In-Reply-To: <1283891142-15522-7-git-send-email-cyril@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <1283891142-15522-7-git-send-email-cyril@ti.com> Message-ID: <20100908010055.GG22507@atomide.com> * Cyril Chemparathy [100907 13:17]: > This patch removes davinci architecture code that has now been rendered > useless by the previous patches in the MDIO separation series. > > Signed-off-by: Cyril Chemparathy > Acked-by: David S. Miller This one too: Acked-by: Tony Lindgren From khilman at deeprootsystems.com Tue Sep 7 20:18:20 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Tue, 07 Sep 2010 18:18:20 -0700 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <1283891142-15522-1-git-send-email-cyril@ti.com> (Cyril Chemparathy's message of "Tue, 7 Sep 2010 16:25:32 -0400") References: <1283891142-15522-1-git-send-email-cyril@ti.com> Message-ID: <871v95f2xv.fsf@deeprootsystems.com> Cyril Chemparathy writes: > Davinci's EMAC device has an in-built MDIO controller and a CPDMA engine. > These hardware modules are not restricted to EMAC device alone. For example, > CPSW3G (3-port gigabit ethernet switch) hardware uses these very same modules > internally. This patch series separates out EMAC's MDIO and CPDMA > functionality, allowing these individual pieces to be reused across TI > hardware. OK, queuing this series for 2.6.37 in davinci-next. Kevin > This patch series has been broadly organized as follows: > > MDIO: > - Add new functionality > netdev: separate out davinci mdio controller code > - Hookup new functionality > davinci: add mdio platform devices > omap: add mdio platform devices > netdev: switch davinci emac to new mdio driver > - Cleanup left over cruft > davinci: cleanup unused davinci mdio arch code > omap: cleanup unused davinci mdio arch code > netdev: cleanup unused davinci mdio emac code > > CPDMA: > - Add new functionality > netdev: separate out davinci cpdma controller code > - Hookup new functionality > netdev: switch davinci emac to new cpdma layer > - Cleanup left over cruft > netdev: cleanup unused davinci emac cpdma code > > This series has been tested on dm365 and tnetv107x (with additional cpsw > patches) hardware. Although am3517 (omap) board support code has been updated > as needed, emac does not work on this platform. > > Changes from v1: > 1. Fixed memory leak in cpdma_chan_create() failure case > 2. Included new omap patches for am3517, avoids build breakage > > Changes from v2: > 1. Updated series to include mityomapl138 board > 2. Minor white-space fixes > > Cyril Chemparathy (10): > net: davinci_emac: separate out davinci mdio > davinci: add mdio platform devices > omap: add mdio platform devices > net: davinci_emac: switch to new mdio > davinci: cleanup unused davinci mdio arch code > omap: cleanup unused davinci mdio arch code > net: davinci_emac: cleanup unused mdio emac code > net: davinci_emac: separate out cpdma code > net: davinci_emac: switch to new cpdma layer > net: davinci_emac: cleanup unused cpdma code > > arch/arm/mach-davinci/board-da830-evm.c | 5 - > arch/arm/mach-davinci/board-da850-evm.c | 6 - > arch/arm/mach-davinci/board-dm365-evm.c | 7 - > arch/arm/mach-davinci/board-dm644x-evm.c | 7 - > arch/arm/mach-davinci/board-dm646x-evm.c | 8 - > arch/arm/mach-davinci/board-mityomapl138.c | 7 - > arch/arm/mach-davinci/board-neuros-osd2.c | 7 - > arch/arm/mach-davinci/board-sffsdr.c | 7 - > arch/arm/mach-davinci/devices-da8xx.c | 31 +- > arch/arm/mach-davinci/dm365.c | 23 +- > arch/arm/mach-davinci/dm644x.c | 23 +- > arch/arm/mach-davinci/dm646x.c | 22 +- > arch/arm/mach-davinci/include/mach/dm365.h | 2 +- > arch/arm/mach-davinci/include/mach/dm644x.h | 2 +- > arch/arm/mach-davinci/include/mach/dm646x.h | 2 +- > arch/arm/mach-omap2/board-am3517evm.c | 31 +- > drivers/net/Kconfig | 21 + > drivers/net/Makefile | 2 + > drivers/net/davinci_cpdma.c | 837 +++++++++++++++++ > drivers/net/davinci_cpdma.h | 105 +++ > drivers/net/davinci_emac.c | 1325 ++++----------------------- > drivers/net/davinci_mdio.c | 386 ++++++++ > include/linux/davinci_emac.h | 8 +- > 23 files changed, 1635 insertions(+), 1239 deletions(-) > create mode 100644 drivers/net/davinci_cpdma.c > create mode 100644 drivers/net/davinci_cpdma.h > create mode 100644 drivers/net/davinci_mdio.c From michael.williamson at criticallink.com Tue Sep 7 21:22:33 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Tue, 07 Sep 2010 22:22:33 -0400 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <871v95f2xv.fsf@deeprootsystems.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <871v95f2xv.fsf@deeprootsystems.com> Message-ID: <4C86F369.6040906@criticallink.com> On 09/07/2010 09:18 PM, Kevin Hilman wrote: > Cyril Chemparathy writes: > >> Davinci's EMAC device has an in-built MDIO controller and a CPDMA engine. >> These hardware modules are not restricted to EMAC device alone. For example, >> CPSW3G (3-port gigabit ethernet switch) hardware uses these very same modules >> internally. This patch series separates out EMAC's MDIO and CPDMA >> functionality, allowing these individual pieces to be reused across TI >> hardware. > > OK, queuing this series for 2.6.37 in davinci-next. > So I just pulled this to test it out on a da850 based board (mitydspl138), and I'm having some problems. I'm hoping it's just operator error. I have a TI TLK100PHP PHY at address 0x3. The boot log shows: [snip] davinci_mdio davinci_mdio.0: davinci mdio revision 1.5 davinci_mdio davinci_mdio.0: detected phy mask fffffff7 davinci_mdio.0: probed davinci_mdio davinci_mdio.0: phy[3]: device 0:03, driver unknown [snip] and then in the init scripts, following udev population I get a "Configuring network interfaces... " and the boot process just hangs. I went back and did a menuconfig, I didn't see an option for TI PHY support, but shouldn't there be a "generic" PHY driver that defaults if one isn't matched? I do have TI DaVinci EMAC/MDIO/CPDMA support enabled under the Ethernet (10 or 100 Mbit). Anyway, I've only looked at this for about 15 minutes, and I was hoping anyone might point out something obvious. If there are hints anyone might have for debugging, I'd appreciate them as well. Or, if anyone has tested this with a da850 evm, that would point me to a problem in the board file. Thanks for any insight. -Mike From sugumar at ti.com Wed Sep 8 00:55:59 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Wed, 8 Sep 2010 11:25:59 +0530 Subject: [PATCH 1/2] davinci: Add generic PWM support for the PWM control In-Reply-To: <87iq2himaa.fsf@deeprootsystems.com> References: <1283841390-27071-1-git-send-email-sugumar@ti.com> <87iq2himaa.fsf@deeprootsystems.com> Message-ID: <00ae01cb4f1a$8c4dbd00$a4e93700$@com> On Tue, Sep 07, 2010 at 21:22:13, Kevin Hilman wrote: > Sugumar Natarajan writes: > > > This patch adds generic PWM support where it maintains the > > list of PWM control devices that can be added or removed. > > > > The interface provides a list of functions that can be accessed > > by the PWM control driver module and the generic PWM driver. > > > > The PWM control driver module such as eCAP uses the interface to > > register and add itself to the list as a PWM control device. > > The generic PWM driver uses the interface to search for a PWM control > > device and if present, uses the device for PWM control. > > > > Signed-off-by: Sugumar Natarajan > > Looks OK, but I have a minor nit below... > > [...] > > > + > > +void add_pwm(struct pwm_device *pwm) > > +{ > > + mutex_lock(&pwm_lock); > > + list_add_tail(&pwm->node, &pwm_list); > > + mutex_unlock(&pwm_lock); > > +} > > +EXPORT_SYMBOL(add_pwm); > > + > > +void remove_pwm(struct pwm_device *pwm) > > +{ > > + mutex_lock(&pwm_lock); > > + list_del(&pwm->node); > > + mutex_unlock(&pwm_lock); > > +} > > +EXPORT_SYMBOL(remove_pwm); > > These new functions should follow the naming convention of the rest of > the API. Namely, pwm_add(), pwm_remove() > Ok. I agree with your comment. I will incorporate them and resubmit an updated version. Regards, N.sugumar From lindenq at gmail.com Wed Sep 8 04:17:37 2010 From: lindenq at gmail.com (=?GB2312?B?wdbWx9PC?=) Date: Wed, 8 Sep 2010 17:17:37 +0800 Subject: Some questions about USB mass storage support Message-ID: Hello,the cpu of my EVM is davinci DM6446,I update u-boot from 1.2 to 2009.11-rc2 , after updating u-boot,the EVM support 'usb start' under u-boot.But after running kernel and running file system (I update the kernel from 2.6.10 to 2.6.32),when I insert the USB Mass storage device, the system could not identify the USB device. What's more ,Should I modify the file system myself. -------------- next part -------------- An HTML attachment was scrubbed... URL: From sugumar at ti.com Wed Sep 8 05:16:28 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Wed, 8 Sep 2010 15:46:28 +0530 Subject: [PATCH v2 1/2] davinci: Add generic PWM support for PWM control Message-ID: <1283940988-22125-1-git-send-email-sugumar@ti.com> This patch adds generic PWM support where it maintains the list of PWM control devices that can be added or removed. The interface provides a list of functions that can be accessed by the PWM control driver module and the generic PWM driver. The PWM control driver module such as eCAP uses the interface to register and add itself to the list as a PWM control device. The generic PWM driver uses the interface to search for a PWM control device and if present, uses the device for PWM control. Signed-off-by: Sugumar Natarajan --- Since v1, following changes have been made: 1.add_pwm and remove_pwm functions have been renamed to pwm_add and pwm_remove respectively. arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/davinci_pwm.c | 116 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 32 ++++++ 3 files changed, 151 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/davinci_pwm.c create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index a7a70d1..90ca821 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_SUSPEND) += pm.o sleep.o + +# Generic PWM control support +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o diff --git a/arch/arm/mach-davinci/davinci_pwm.c b/arch/arm/mach-davinci/davinci_pwm.c new file mode 100644 index 0000000..aa21b7a --- /dev/null +++ b/arch/arm/mach-davinci/davinci_pwm.c @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + unsigned int clock_freq; + unsigned int period_cycles; + unsigned int duty_cycle; + + if (!pwm || !pwm->pwm_config_device || !period_ns || + duty_ns > period_ns) + return -EINVAL; + + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; + pwm->pwm_config_device(pwm, period_cycles, duty_cycle); + + return 0; +} +EXPORT_SYMBOL(pwm_config); + +int pwm_enable(struct pwm_device *pwm) +{ + return clk_enable(pwm->clk); +} +EXPORT_SYMBOL(pwm_enable); + +void pwm_disable(struct pwm_device *pwm) +{ + clk_disable(pwm->clk); +} +EXPORT_SYMBOL(pwm_disable); + +static DEFINE_MUTEX(pwm_lock); +static LIST_HEAD(pwm_list); + +struct pwm_device *pwm_request(int pwm_id, const char *label) +{ + struct pwm_device *pwm; + int found = 0; + + mutex_lock(&pwm_lock); + + list_for_each_entry(pwm, &pwm_list, node) { + if (pwm->pwm_id == pwm_id) { + found = 1; + break; + } + } + + if (found) { + if (pwm->use_count == 0) { + pwm->use_count++; + pwm->label = label; + } else { + pwm = ERR_PTR(-EBUSY); + } + } else { + pwm = ERR_PTR(-ENOENT); + } + + mutex_unlock(&pwm_lock); + return pwm; +} +EXPORT_SYMBOL(pwm_request); + +void pwm_free(struct pwm_device *pwm) +{ + mutex_lock(&pwm_lock); + + if (pwm->use_count) { + pwm->use_count--; + pwm->label = NULL; + } else { + dev_warn(&pwm->pdev->dev, "PWM device already freed\n"); + } + + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_free); + +void pwm_add(struct pwm_device *pwm) +{ + mutex_lock(&pwm_lock); + list_add_tail(&pwm->node, &pwm_list); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_add); + +void pwm_remove(struct pwm_device *pwm) +{ + mutex_lock(&pwm_lock); + list_del(&pwm->node); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_remove); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h new file mode 100644 index 0000000..ba2720b --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __DAVINCI_PWM_H +#define __DAVINCI_PWM_H + +struct pwm_device { + struct list_head node; + struct platform_device *pdev; + void (*pwm_config_device)(struct pwm_device *pwm, + unsigned int period, unsigned int dutycycle); + const char *label; + struct clk *clk; + unsigned int use_count; + unsigned int pwm_id; +}; + +void pwm_add(struct pwm_device *pwm); +void pwm_remove(struct pwm_device *pwm); + +#endif -- 1.5.6 From sugumar at ti.com Wed Sep 8 05:16:55 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Wed, 8 Sep 2010 15:46:55 +0530 Subject: [PATCH v2 2/2] davinci: da850: eCAP driver for PWM signal generation Message-ID: <1283941015-22153-1-git-send-email-sugumar@ti.com> OMAPL138/DA850 contains three instances of eCAP module. Each eCAP module has one dedicated pin that can be used either in capture mode(input) or in PWM mode. For more information on eCAP module operation, please refer to the following url. http://focus.ti.com/lit/ug/sprufl2a/sprufl2a.pdf This patch adds eCAP driver support for PWM signal generation. Signed-off-by: Sugumar Natarajan --- Since v1, following changes have been made: 1. request_mem_region is called before ioremap (ecap.c) 2. release_mem_region is done during pwm removal (ecap.c) 3. prompt string and help text are included in Kconfig arch/arm/mach-davinci/Kconfig | 9 ++ arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/ecap.c | 155 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 1 + 4 files changed, 168 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/ecap.c diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 9aca60c..8192866 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -40,6 +40,7 @@ config ARCH_DAVINCI_DA850 select CP_INTC select ARCH_DAVINCI_DA8XX select ARCH_HAS_CPUFREQ + select HAVE_PWM config ARCH_DAVINCI_DA8XX select CPU_ARM926T @@ -230,6 +231,14 @@ config DAVINCI_RESET_CLOCKS probably do not want this option enabled until your device drivers work properly. +config DAVINCI_ECAP_PWM + bool "eCAP driver support for PWM control" + depends on ARCH_DAVINCI_DA8XX + depends on HAVE_PWM + default n + help + Say Y to select the eCAP module for PWM control. + endmenu endif diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 90ca821..90bd88e 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -42,3 +42,6 @@ obj-$(CONFIG_SUSPEND) += pm.o sleep.o # Generic PWM control support obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o + +# eCAP driver support for PWM +obj-$(CONFIG_DAVINCI_ECAP_PWM) += ecap.o diff --git a/arch/arm/mach-davinci/ecap.c b/arch/arm/mach-davinci/ecap.c new file mode 100644 index 0000000..5127174 --- /dev/null +++ b/arch/arm/mach-davinci/ecap.c @@ -0,0 +1,155 @@ +/* + * DA850/OMAP-L138 eCAP driver for PWM output generation + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CAPTURE_3_REG 0x10 +#define CAPTURE_4_REG 0x14 +#define CAPTURE_CTRL2_REG 0x2A + +#define ECAP_CTRL2_APWMPOLL BIT(10) +#define ECAP_CTRL2_MODESL BIT(9) +#define ECAP_CTRL2_SWSYNC BIT(8) +#define ECAP_CTRL2_SYNCO_SEL (BIT(7) | BIT(6)) +#define ECAP_CTRL2_SYNCI_EN BIT(5) +#define ECAP_CTRL2_TSCTRSTOP BIT(4) + +/* + * ecap_config_pwm - configures the eCAP Module for the PWM output with given + * period and duty cycle. + */ + +static void ecap_config_pwm(struct pwm_device *pwm, unsigned int period_cycles, + unsigned int duty_cycle) +{ + __raw_writew(ECAP_CTRL2_MODESL | ECAP_CTRL2_SYNCO_SEL | + ECAP_CTRL2_TSCTRSTOP, pwm->mmio_base + CAPTURE_CTRL2_REG); + __raw_writel(period_cycles, pwm->mmio_base + CAPTURE_3_REG); + + /* 100% duty cycle is obtained when the duty cycle value is one + * greater than period ie duty cycle = period + 1 + */ + if (duty_cycle == period_cycles) + duty_cycle = duty_cycle + 1; + + __raw_writel(duty_cycle, pwm->mmio_base + CAPTURE_4_REG); +} + +static int __devinit ecap_probe(struct platform_device *pdev) +{ + struct pwm_device *pwm = NULL; + struct resource *r; + int ret = 0; + + pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); + if (!pwm) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + pwm->clk = clk_get(&pdev->dev, "ecap"); + if (IS_ERR(pwm->clk)) { + ret = PTR_ERR(pwm->clk); + goto err_free; + } + + pwm->pwm_id = pdev->id; + pwm->pdev = pdev; + pwm->pwm_config_device = ecap_config_pwm; + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "no memory resource defined\n"); + ret = -ENODEV; + goto err_free_clk; + } + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) { + dev_err(&pdev->dev, "failed to request memory resource\n"); + ret = -EBUSY; + goto err_free_clk; + } + + pwm->mmio_base = ioremap(r->start, resource_size(r)); + if (!pwm->mmio_base) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + ret = -ENODEV; + goto err_free_mem; + } + + clk_enable(pwm->clk); + pwm_add(pwm); + platform_set_drvdata(pdev, pwm); + return 0; + +err_free_mem: + release_mem_region(r->start, resource_size(r)); +err_free_clk: + clk_put(pwm->clk); +err_free: + kfree(pwm); + return ret; +} + +static int __devexit ecap_remove(struct platform_device *pdev) +{ + struct pwm_device *pwm; + struct resource *r; + + pwm = platform_get_drvdata(pdev); + if (!pwm) + return -ENODEV; + + pwm_remove(pwm); + iounmap(pwm->mmio_base); + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(r->start, resource_size(r)); + clk_put(pwm->clk); + kfree(pwm); + + return 0; +} + +static struct platform_driver ecap_driver = { + .driver = { + .name = "ecap", + .owner = THIS_MODULE, + }, + .probe = ecap_probe, + .remove = __devexit_p(ecap_remove), +}; + +static int __init ecap_init(void) +{ + return platform_driver_register(&ecap_driver); +} + +static void __exit ecap_exit(void) +{ + platform_driver_unregister(&ecap_driver); +} + +module_init(ecap_init); +module_exit(ecap_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h index ba2720b..9778a15 100644 --- a/arch/arm/mach-davinci/include/mach/davinci_pwm.h +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -22,6 +22,7 @@ struct pwm_device { unsigned int period, unsigned int dutycycle); const char *label; struct clk *clk; + void __iomem *mmio_base; unsigned int use_count; unsigned int pwm_id; }; -- 1.5.6 From nsekhar at ti.com Wed Sep 8 07:17:57 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Wed, 8 Sep 2010 17:47:57 +0530 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> References: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> Message-ID: Hi Victor, On Wed, Sep 08, 2010 at 01:32:04, Victor Rodriguez wrote: > This patch adds initial support for the Hawkboard-L138 system > It is under the machine name "omapl138_hawkboard". > This system is based on the da850 davinci CPU architecture. > Information on these system may be found at http://www.hawkboard.org. > Basic support for the UART console is included in this patch. > Depends on Michael Williamson patches: > http://alturl.com/hha7u and http://alturl.com/qy4cr Patch dependencies should be noted below the --- > > Signed-off-by: Victor Rodriguez > --- > Changes since v4: > 1) Registering UART 0 and UART 2, UART 1 is not available on hardware > 2) Add Watch dog timer function > > Notes: > > This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 > from Kernel development tree for TI DaVinci family of processors. > This patch works with da8xx_omapl_defconfig plus this patch. > Depens on patches http://alturl.com/hha7u and http://alturl.com/qy4cr > > arch/arm/configs/da8xx_omapl_defconfig | 1 + > arch/arm/mach-davinci/Kconfig | 8 +++ > arch/arm/mach-davinci/Makefile | 1 + > arch/arm/mach-davinci/board-da850-hawk.c | 66 +++++++++++++++++++++++ > arch/arm/mach-davinci/include/mach/uncompress.h | 1 + > 5 files changed, 77 insertions(+), 0 deletions(-) > create mode 100644 arch/arm/mach-davinci/board-da850-hawk.c > > diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig > index 3952a4e..d7cb4b8 100644 > --- a/arch/arm/configs/da8xx_omapl_defconfig > +++ b/arch/arm/configs/da8xx_omapl_defconfig > @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y > CONFIG_ARCH_DAVINCI=y > CONFIG_ARCH_DAVINCI_DA830=y > CONFIG_ARCH_DAVINCI_DA850=y > +CONFIG_MACH_OMAPL138_HAWKBOARD=y > CONFIG_DAVINCI_RESET_CLOCKS=y > CONFIG_NO_HZ=y > CONFIG_HIGH_RES_TIMERS=y > diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig > index 2bf03e9..985c261 100644 > --- a/arch/arm/mach-davinci/Kconfig > +++ b/arch/arm/mach-davinci/Kconfig > @@ -185,6 +185,14 @@ config MACH_TNETV107X > help > Say Y here to select the TI TNETV107X Evaluation Module. > > +config MACH_OMAPL138_HAWKBOARD > + bool "TI AM1808 / OMAPL138 Hawkboard platform" s/OMAPL138/OMAP-L138 > + depends on ARCH_DAVINCI_DA850 > + help > + Say Y here to select the TI AM1808 / OMAPL138 Hawkboard platform . s/OMAPL138/OMAP-L138 > + Information of this board may be found at > + http://www.hawkboard.org/ > + > config DAVINCI_MUX > bool "DAVINCI multiplexing support" > depends on ARCH_DAVINCI > diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile > index 77a0f71..484071d 100644 > --- a/arch/arm/mach-davinci/Makefile > +++ b/arch/arm/mach-davinci/Makefile > @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o > obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o > obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o > obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o > +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-da850-hawk.o > > # Power Management > obj-$(CONFIG_CPU_FREQ) += cpufreq.o > diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c > new file mode 100644 > index 0000000..b71a6a7 > --- /dev/null > +++ b/arch/arm/mach-davinci/board-da850-hawk.c > @@ -0,0 +1,66 @@ > +/* > + * Hawkboard.org based on TI's OMAP-L138 Platform > + * > + * Initial code: Syed Mohammed Khasim > + * > + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 > +#include > +#include > +#include > + > +#include > +#include > + > +#include > +#include > + > +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { > + .enabled_uarts = 0x7, > +}; > + > +static __init void omapl138_hawk_init(void) > +{ > + int ret; > + > + davinci_serial_init(&omapl138_hawk_uart_config); > + > + /*shut down uart 1; It is not implemented in hardware */ Should be: /* Shut down ... I thought there was going to be a note here as to why we register UART1, but choose to shut it down? > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > + > + ret = da8xx_register_watchdog(); > + if (ret) > + pr_warning("evm_init: watchdog registration failed: %d\n", It is not evm board.. > + ret); > +} > + > +#ifdef CONFIG_SERIAL_8250_CONSOLE > +static int __init omapl138_hawk_console_init(void) > +{ > + if (!machine_is_omapl138_hawkboard()) > + return 0; > + > + return add_preferred_console("ttyS", 2, "115200"); > +} > +console_initcall(omapl138_hawk_console_init); > +#endif > + > +static void __init omapl138_hawk_map_io(void) > +{ > + da850_init(); > +} > + > +MACHINE_START(OMAPL138_HAWKBOARD, "OMAP-L138") OMAP-L138 is just the processor name. What is expected here is the board name. It should be "AM18x/OMAP-L138 Hawkboard" Thanks, Sekhar From nsekhar at ti.com Wed Sep 8 07:32:09 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Wed, 8 Sep 2010 18:02:09 +0530 Subject: [PATCH] hawkboard v_2 In-Reply-To: <8739tlk1mm.fsf@deeprootsystems.com> References: <1283284116-3288-1-git-send-email-vm.rod25@gmail.com> <87y6bk9j2z.fsf@deeprootsystems.com> <0680EC522D0CC943BC586913CF3768C003C2018961@dbde02.ent.ti.com> <8739tlk1mm.fsf@deeprootsystems.com> Message-ID: Hi Kevin, On Tue, Sep 07, 2010 at 21:05:29, Kevin Hilman wrote: > >>> > > + /* > >>> > > + * shut down uart 0 and 1; they are not used on the board and > >>> > > + * accessing them causes endless "too much work in irq53" messages > >>> > > + * with arago fs > >>> > > + */ > >>> > > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > >>> > > + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); > >>> > > >>> > This hack/workaround needs to be removed and/or better described so we > >>> > know *why* such a thing is needed. > >>> > > >>> > Khasim, do you know what the root cause is here? > >>> I will have to look into this, I will get back to you in a day or two. > >>> > >> These lines were directly copied from da850 board file, I am still trying to figure out if this is true for hawk as well. > >> > >> Looks like some thing is not handled properly in driver that is causing this irq 53, we had similar issue in OMAP3 with irq33. > >> > >> I will have to discuss this with Sekhar, he is on vacation this week. Will keep you updated as soon as I get more info into this. > >> > >> For now can we put a big disclaimer on this (TBD) and move forward? - this is just a request. > >> > >> Regards, > >> Khasim > >> > > > > I agree if Kevin is ok I could propose one more version of the patch > > and keep working in the other things to rebase like USB, MMC and so on > > Yes, that's OK. > > I hadn't noticed it came from the da850 EVM board file. What I'd like > is for the da850 EVM board file to be cleaned up with a better > description of the problem as well, but that can be done by TI (Sekhar?) > as a separate patch. Yes, will fix this. Thanks, Sekhar From vm.rod25 at gmail.com Wed Sep 8 09:20:57 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Wed, 8 Sep 2010 09:20:57 -0500 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: References: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> Message-ID: On Wed, Sep 8, 2010 at 7:17 AM, Nori, Sekhar wrote: > Hi Victor, > > On Wed, Sep 08, 2010 at 01:32:04, Victor Rodriguez wrote: >> This patch adds initial support for the Hawkboard-L138 system >> It is under the machine name "omapl138_hawkboard". >> This system is based on the da850 davinci CPU architecture. >> Information on these system may be found at http://www.hawkboard.org. >> Basic support for the UART console is included in this patch. >> Depends on Michael Williamson patches: >> http://alturl.com/hha7u and http://alturl.com/qy4cr > > Patch dependencies should be noted below the --- > >> >> Signed-off-by: Victor Rodriguez >> --- >> Changes since v4: >> 1) Registering UART 0 and UART 2, UART 1 is not available on hardware >> 2) Add Watch dog timer function >> >> Notes: >> >> This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 >> from Kernel development tree for TI DaVinci family of processors. >> This patch works with da8xx_omapl_defconfig plus this patch. >> Depens on patches http://alturl.com/hha7u and http://alturl.com/qy4cr >> >> ?arch/arm/configs/da8xx_omapl_defconfig ? ? ? ? ?| ? ?1 + >> ?arch/arm/mach-davinci/Kconfig ? ? ? ? ? ? ? ? ? | ? ?8 +++ >> ?arch/arm/mach-davinci/Makefile ? ? ? ? ? ? ? ? ?| ? ?1 + >> ?arch/arm/mach-davinci/board-da850-hawk.c ? ? ? ?| ? 66 +++++++++++++++++++++++ >> ?arch/arm/mach-davinci/include/mach/uncompress.h | ? ?1 + >> ?5 files changed, 77 insertions(+), 0 deletions(-) >> ?create mode 100644 arch/arm/mach-davinci/board-da850-hawk.c >> >> diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig >> index 3952a4e..d7cb4b8 100644 >> --- a/arch/arm/configs/da8xx_omapl_defconfig >> +++ b/arch/arm/configs/da8xx_omapl_defconfig >> @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y >> ?CONFIG_ARCH_DAVINCI=y >> ?CONFIG_ARCH_DAVINCI_DA830=y >> ?CONFIG_ARCH_DAVINCI_DA850=y >> +CONFIG_MACH_OMAPL138_HAWKBOARD=y >> ?CONFIG_DAVINCI_RESET_CLOCKS=y >> ?CONFIG_NO_HZ=y >> ?CONFIG_HIGH_RES_TIMERS=y >> diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig >> index 2bf03e9..985c261 100644 >> --- a/arch/arm/mach-davinci/Kconfig >> +++ b/arch/arm/mach-davinci/Kconfig >> @@ -185,6 +185,14 @@ config MACH_TNETV107X >> ? ? ? help >> ? ? ? ? Say Y here to select the TI TNETV107X Evaluation Module. >> >> +config MACH_OMAPL138_HAWKBOARD >> + ? ? bool "TI AM1808 / OMAPL138 Hawkboard platform" Hi thanks for the comments I will fix them, but i do not understand this s/OMAPL138/OMAP-L138 do you suggest that it should be bool "TI AM1808 / OMAPL138 Hawkboard platform/OMAPL138/OMAP-L138 " > >> + ? ? depends on ARCH_DAVINCI_DA850 >> + ? ? help >> + ? ? ? Say Y here to select the TI AM1808 / OMAPL138 Hawkboard platform . same here Waiting for your answer to fix the patch Thanks VIctor Rodriguez > s/OMAPL138/OMAP-L138 > >> + ? ? ? Information of this board may be found at >> + ? ? ? http://www.hawkboard.org/ >> + >> ?config DAVINCI_MUX >> ? ? ? bool "DAVINCI multiplexing support" >> ? ? ? depends on ARCH_DAVINCI >> diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile >> index 77a0f71..484071d 100644 >> --- a/arch/arm/mach-davinci/Makefile >> +++ b/arch/arm/mach-davinci/Makefile >> @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) ? ? ? ?+= board-dm365-evm.o >> ?obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o >> ?obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o >> ?obj-$(CONFIG_MACH_TNETV107X) ? ? ? ? += board-tnetv107x-evm.o >> +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) ? ? ? ?+= board-da850-hawk.o >> >> ?# Power Management >> ?obj-$(CONFIG_CPU_FREQ) ? ? ? ? ? ? ? ? ? ? ? += cpufreq.o >> diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c >> new file mode 100644 >> index 0000000..b71a6a7 >> --- /dev/null >> +++ b/arch/arm/mach-davinci/board-da850-hawk.c >> @@ -0,0 +1,66 @@ >> +/* >> + * Hawkboard.org based on TI's OMAP-L138 Platform >> + * >> + * Initial code: Syed Mohammed Khasim >> + * >> + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 >> +#include >> +#include >> +#include >> + >> +#include >> +#include >> + >> +#include >> +#include >> + >> +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { >> + ? ? .enabled_uarts = 0x7, >> +}; >> + >> +static __init void omapl138_hawk_init(void) >> +{ >> + ? ? int ret; >> + >> + ? ? davinci_serial_init(&omapl138_hawk_uart_config); >> + >> + ? ? /*shut down uart 1; It is not implemented in hardware */ > > Should be: /* Shut down ... > > I thought there was going to be a note here as to > why we register UART1, but choose to shut it down? > >> + ? ? __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >> + >> + ? ? ret = da8xx_register_watchdog(); >> + ? ? if (ret) >> + ? ? ? ? ? ? pr_warning("evm_init: watchdog registration failed: %d\n", > > It is not evm board.. > >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ret); >> +} >> + >> +#ifdef CONFIG_SERIAL_8250_CONSOLE >> +static int __init omapl138_hawk_console_init(void) >> +{ >> + ? ? if (!machine_is_omapl138_hawkboard()) >> + ? ? ? ? ? ? return 0; >> + >> + ? ? return add_preferred_console("ttyS", 2, "115200"); >> +} >> +console_initcall(omapl138_hawk_console_init); >> +#endif >> + >> +static void __init omapl138_hawk_map_io(void) >> +{ >> + ? ? da850_init(); >> +} >> + >> +MACHINE_START(OMAPL138_HAWKBOARD, "OMAP-L138") > > OMAP-L138 is just the processor name. What is expected here is > the board name. It should be "AM18x/OMAP-L138 Hawkboard" > > Thanks, > Sekhar > > From sshtylyov at mvista.com Wed Sep 8 09:28:48 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Wed, 08 Sep 2010 18:28:48 +0400 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: References: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> Message-ID: <4C879DA0.4060007@mvista.com> Hello. Victor Rodriguez wrote: >> On Wed, Sep 08, 2010 at 01:32:04, Victor Rodriguez wrote: >>> This patch adds initial support for the Hawkboard-L138 system >>> It is under the machine name "omapl138_hawkboard". >>> This system is based on the da850 davinci CPU architecture. >>> Information on these system may be found at http://www.hawkboard.org. >>> Basic support for the UART console is included in this patch. >>> Depends on Michael Williamson patches: >>> http://alturl.com/hha7u and http://alturl.com/qy4cr >> Patch dependencies should be noted below the --- >>> Signed-off-by: Victor Rodriguez >>> --- >>> Changes since v4: >>> 1) Registering UART 0 and UART 2, UART 1 is not available on hardware >>> 2) Add Watch dog timer function >>> Notes: >>> This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 >>> from Kernel development tree for TI DaVinci family of processors. >>> This patch works with da8xx_omapl_defconfig plus this patch. >>> Depens on patches http://alturl.com/hha7u and http://alturl.com/qy4cr >>> >>> arch/arm/configs/da8xx_omapl_defconfig | 1 + >>> arch/arm/mach-davinci/Kconfig | 8 +++ >>> arch/arm/mach-davinci/Makefile | 1 + >>> arch/arm/mach-davinci/board-da850-hawk.c | 66 +++++++++++++++++++++++ >>> arch/arm/mach-davinci/include/mach/uncompress.h | 1 + >>> 5 files changed, 77 insertions(+), 0 deletions(-) >>> create mode 100644 arch/arm/mach-davinci/board-da850-hawk.c >>> diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig >>> index 3952a4e..d7cb4b8 100644 >>> --- a/arch/arm/configs/da8xx_omapl_defconfig >>> +++ b/arch/arm/configs/da8xx_omapl_defconfig >>> @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y >>> CONFIG_ARCH_DAVINCI=y >>> CONFIG_ARCH_DAVINCI_DA830=y >>> CONFIG_ARCH_DAVINCI_DA850=y >>> +CONFIG_MACH_OMAPL138_HAWKBOARD=y >>> CONFIG_DAVINCI_RESET_CLOCKS=y >>> CONFIG_NO_HZ=y >>> CONFIG_HIGH_RES_TIMERS=y >>> diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig >>> index 2bf03e9..985c261 100644 >>> --- a/arch/arm/mach-davinci/Kconfig >>> +++ b/arch/arm/mach-davinci/Kconfig >>> @@ -185,6 +185,14 @@ config MACH_TNETV107X >>> help >>> Say Y here to select the TI TNETV107X Evaluation Module. >>> >>> +config MACH_OMAPL138_HAWKBOARD >>> + bool "TI AM1808 / OMAPL138 Hawkboard platform" > Hi thanks for the comments I will fix them, but i do not understand this > s/OMAPL138/OMAP-L138 This ('vi' command for "search and replace") just means that you should replace OMAPL138 with OMAP-L138. WBR, Sergei From vm.rod25 at gmail.com Wed Sep 8 09:31:19 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Wed, 8 Sep 2010 09:31:19 -0500 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <4C879DA0.4060007@mvista.com> References: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> <4C879DA0.4060007@mvista.com> Message-ID: On Wed, Sep 8, 2010 at 9:28 AM, Sergei Shtylyov wrote: > Hello. > > Victor Rodriguez wrote: > >>> On Wed, Sep 08, 2010 at 01:32:04, Victor Rodriguez wrote: >>>> >>>> This patch adds initial support for the Hawkboard-L138 system >>>> It is under the machine name "omapl138_hawkboard". >>>> This system is based on the da850 davinci CPU architecture. >>>> Information on these system may be found at http://www.hawkboard.org. >>>> Basic support for the UART console is included in this patch. >>>> Depends on Michael Williamson patches: >>>> http://alturl.com/hha7u and http://alturl.com/qy4cr > >>> Patch dependencies should be noted below the --- > >>>> Signed-off-by: Victor Rodriguez >>>> --- >>>> Changes since v4: >>>> 1) Registering UART 0 and UART 2, UART 1 is not available on hardware >>>> 2) Add Watch dog timer function > >>>> Notes: > >>>> This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 >>>> from Kernel development tree for TI DaVinci family of processors. >>>> This patch works with da8xx_omapl_defconfig plus this patch. >>>> Depens on patches http://alturl.com/hha7u and http://alturl.com/qy4cr >>>> >>>> ?arch/arm/configs/da8xx_omapl_defconfig ? ? ? ? ?| ? ?1 + >>>> ?arch/arm/mach-davinci/Kconfig ? ? ? ? ? ? ? ? ? | ? ?8 +++ >>>> ?arch/arm/mach-davinci/Makefile ? ? ? ? ? ? ? ? ?| ? ?1 + >>>> ?arch/arm/mach-davinci/board-da850-hawk.c ? ? ? ?| ? 66 >>>> +++++++++++++++++++++++ >>>> ?arch/arm/mach-davinci/include/mach/uncompress.h | ? ?1 + >>>> ?5 files changed, 77 insertions(+), 0 deletions(-) >>>> ?create mode 100644 arch/arm/mach-davinci/board-da850-hawk.c > >>>> diff --git a/arch/arm/configs/da8xx_omapl_defconfig >>>> b/arch/arm/configs/da8xx_omapl_defconfig >>>> index 3952a4e..d7cb4b8 100644 >>>> --- a/arch/arm/configs/da8xx_omapl_defconfig >>>> +++ b/arch/arm/configs/da8xx_omapl_defconfig >>>> @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y >>>> ?CONFIG_ARCH_DAVINCI=y >>>> ?CONFIG_ARCH_DAVINCI_DA830=y >>>> ?CONFIG_ARCH_DAVINCI_DA850=y >>>> +CONFIG_MACH_OMAPL138_HAWKBOARD=y >>>> ?CONFIG_DAVINCI_RESET_CLOCKS=y >>>> ?CONFIG_NO_HZ=y >>>> ?CONFIG_HIGH_RES_TIMERS=y >>>> diff --git a/arch/arm/mach-davinci/Kconfig >>>> b/arch/arm/mach-davinci/Kconfig >>>> index 2bf03e9..985c261 100644 >>>> --- a/arch/arm/mach-davinci/Kconfig >>>> +++ b/arch/arm/mach-davinci/Kconfig >>>> @@ -185,6 +185,14 @@ config MACH_TNETV107X >>>> ? ? ?help >>>> ? ? ? ?Say Y here to select the TI TNETV107X Evaluation Module. >>>> >>>> +config MACH_OMAPL138_HAWKBOARD >>>> + ? ? bool "TI AM1808 / OMAPL138 Hawkboard platform" > >> Hi thanks for the comments I will fix them, but i do not understand this > >> ?s/OMAPL138/OMAP-L138 > > ? This ('vi' command for "search and replace") just means that you should > replace OMAPL138 with OMAP-L138. > > WBR, Sergei > Thanks a lot Victor Rodriguez From vm.rod25 at gmail.com Wed Sep 8 09:35:15 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Wed, 8 Sep 2010 09:35:15 -0500 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: References: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> Message-ID: On Wed, Sep 8, 2010 at 7:17 AM, Nori, Sekhar wrote: > Hi Victor, > > On Wed, Sep 08, 2010 at 01:32:04, Victor Rodriguez wrote: >> This patch adds initial support for the Hawkboard-L138 system >> It is under the machine name "omapl138_hawkboard". >> This system is based on the da850 davinci CPU architecture. >> Information on these system may be found at http://www.hawkboard.org. >> Basic support for the UART console is included in this patch. >> Depends on Michael Williamson patches: >> http://alturl.com/hha7u and http://alturl.com/qy4cr > > Patch dependencies should be noted below the --- > >> >> Signed-off-by: Victor Rodriguez >> --- >> Changes since v4: >> 1) Registering UART 0 and UART 2, UART 1 is not available on hardware >> 2) Add Watch dog timer function >> >> Notes: >> >> This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 >> from Kernel development tree for TI DaVinci family of processors. >> This patch works with da8xx_omapl_defconfig plus this patch. >> Depens on patches http://alturl.com/hha7u and http://alturl.com/qy4cr >> >> ?arch/arm/configs/da8xx_omapl_defconfig ? ? ? ? ?| ? ?1 + >> ?arch/arm/mach-davinci/Kconfig ? ? ? ? ? ? ? ? ? | ? ?8 +++ >> ?arch/arm/mach-davinci/Makefile ? ? ? ? ? ? ? ? ?| ? ?1 + >> ?arch/arm/mach-davinci/board-da850-hawk.c ? ? ? ?| ? 66 +++++++++++++++++++++++ >> ?arch/arm/mach-davinci/include/mach/uncompress.h | ? ?1 + >> ?5 files changed, 77 insertions(+), 0 deletions(-) >> ?create mode 100644 arch/arm/mach-davinci/board-da850-hawk.c >> >> diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig >> index 3952a4e..d7cb4b8 100644 >> --- a/arch/arm/configs/da8xx_omapl_defconfig >> +++ b/arch/arm/configs/da8xx_omapl_defconfig >> @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y >> ?CONFIG_ARCH_DAVINCI=y >> ?CONFIG_ARCH_DAVINCI_DA830=y >> ?CONFIG_ARCH_DAVINCI_DA850=y >> +CONFIG_MACH_OMAPL138_HAWKBOARD=y >> ?CONFIG_DAVINCI_RESET_CLOCKS=y >> ?CONFIG_NO_HZ=y >> ?CONFIG_HIGH_RES_TIMERS=y >> diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig >> index 2bf03e9..985c261 100644 >> --- a/arch/arm/mach-davinci/Kconfig >> +++ b/arch/arm/mach-davinci/Kconfig >> @@ -185,6 +185,14 @@ config MACH_TNETV107X >> ? ? ? help >> ? ? ? ? Say Y here to select the TI TNETV107X Evaluation Module. >> >> +config MACH_OMAPL138_HAWKBOARD >> + ? ? bool "TI AM1808 / OMAPL138 Hawkboard platform" > > s/OMAPL138/OMAP-L138 > >> + ? ? depends on ARCH_DAVINCI_DA850 >> + ? ? help >> + ? ? ? Say Y here to select the TI AM1808 / OMAPL138 Hawkboard platform . > > s/OMAPL138/OMAP-L138 > >> + ? ? ? Information of this board may be found at >> + ? ? ? http://www.hawkboard.org/ >> + >> ?config DAVINCI_MUX >> ? ? ? bool "DAVINCI multiplexing support" >> ? ? ? depends on ARCH_DAVINCI >> diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile >> index 77a0f71..484071d 100644 >> --- a/arch/arm/mach-davinci/Makefile >> +++ b/arch/arm/mach-davinci/Makefile >> @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) ? ? ? ?+= board-dm365-evm.o >> ?obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o >> ?obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o >> ?obj-$(CONFIG_MACH_TNETV107X) ? ? ? ? += board-tnetv107x-evm.o >> +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) ? ? ? ?+= board-da850-hawk.o >> >> ?# Power Management >> ?obj-$(CONFIG_CPU_FREQ) ? ? ? ? ? ? ? ? ? ? ? += cpufreq.o >> diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c >> new file mode 100644 >> index 0000000..b71a6a7 >> --- /dev/null >> +++ b/arch/arm/mach-davinci/board-da850-hawk.c >> @@ -0,0 +1,66 @@ >> +/* >> + * Hawkboard.org based on TI's OMAP-L138 Platform >> + * >> + * Initial code: Syed Mohammed Khasim >> + * >> + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 >> +#include >> +#include >> +#include >> + >> +#include >> +#include >> + >> +#include >> +#include >> + >> +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { >> + ? ? .enabled_uarts = 0x7, >> +}; >> + >> +static __init void omapl138_hawk_init(void) >> +{ >> + ? ? int ret; >> + >> + ? ? davinci_serial_init(&omapl138_hawk_uart_config); >> + >> + ? ? /*shut down uart 1; It is not implemented in hardware */ > > Should be: /* Shut down ... > > I thought there was going to be a note here as to > why we register UART1, but choose to shut it down? The UART1 is not present in the board, we are registering first the UART0,1 and 2 and then just shut down UART1 because it is not present in hardware. But what do you suggest. Thanks VIctor Rodriguez >> + ? ? __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >> + >> + ? ? ret = da8xx_register_watchdog(); >> + ? ? if (ret) >> + ? ? ? ? ? ? pr_warning("evm_init: watchdog registration failed: %d\n", > > It is not evm board.. > >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ret); >> +} >> + >> +#ifdef CONFIG_SERIAL_8250_CONSOLE >> +static int __init omapl138_hawk_console_init(void) >> +{ >> + ? ? if (!machine_is_omapl138_hawkboard()) >> + ? ? ? ? ? ? return 0; >> + >> + ? ? return add_preferred_console("ttyS", 2, "115200"); >> +} >> +console_initcall(omapl138_hawk_console_init); >> +#endif >> + >> +static void __init omapl138_hawk_map_io(void) >> +{ >> + ? ? da850_init(); >> +} >> + >> +MACHINE_START(OMAPL138_HAWKBOARD, "OMAP-L138") > > OMAP-L138 is just the processor name. What is expected here is > the board name. It should be "AM18x/OMAP-L138 Hawkboard" > > Thanks, > Sekhar > > From c.aeschlimann at acn-group.ch Wed Sep 8 10:35:04 2010 From: c.aeschlimann at acn-group.ch (Christophe Aeschlimann) Date: Wed, 08 Sep 2010 17:35:04 +0200 Subject: [PATCH v3] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <4C801DBC.5050105@criticallink.com> References: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> <87fwxs6n6b.fsf@deeprootsystems.com> <4C801DBC.5050105@criticallink.com> Message-ID: <4C87AD28.5040701@acn-group.ch> On 02.09.2010 23:57, Michael Williamson wrote: > On 09/02/2010 02:00 PM, Kevin Hilman wrote: >> Victor Rodriguez writes: >> > [...] >> >> [...] >> >>> +static __init void omapl138_hawk_init(void) >>> +{ >>> + >>> + davinci_serial_init(&omapl138_hawk_uart_config); >>> + >>> + /* >>> + * shut down uart 0 and 1; they are not used on the board and >>> + * accessing them causes endless "too much work in irq53" messages >>> + * with arago fs >>> + */ >>> + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >>> + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); >> >> I still dont' want to merge this until this issue is understood and >> described in the changelog (or the code removed.) >> > > Looking at the schametic, neither UART0 or UART1 are ever hooked up, so it seems > like the "enabled_uarts" fields should just be set to 0x4 (UART2) and these lines > that pound the controller removed. > > I'm fairly certain the "too much work in irq53" issue here has to > do with the fact that the pins for the UART0 Rx line and output flow control > line, which share pin-mux duties with the MII data lines, are hooked up > externally to the LAN8710 chip on the hawkboard. > > Turns out, the pin-mux controls don't appear to really disconnect inputs from > devices having input ports that share a pin via the muxing logic (only outputs > are truly "muxed" at the pin level). > > The LAN interface is probably causing serial interrupts based on receive data or > flow control logic firing for UART0, because you're enabling it in the enable_uarts > mask and enumerating the device. > > We actually have seen a similar problem with trying to use UART1 with no HW flow > control and and the McASP. The UART1 CTS/RTS lines pin-mux-share lines with the > McASP AHCLKX and AHCLKR. The minute you try to enable the McASP, the serial driver > gets pounded with flow control interrupts. There's no provision, that I can find > in the kernel anyway, that allows for disabling CTS/RTS interrupts in the > platform definition. (looking at a patch for this...) I'm having the same problem here. (UART1 + McASP sharing the same pins and getting tons of "too much work in irq53") Did you find a workaround ? Thanks ! Best regards, Christophe > > -Mike > > -- Christophe Aeschlimann Embedded Software Engineer Advanced Communications Networks S.A. Rue du Puits-Godet 8a 2000 Neuch?tel, Switzerland T?l. +41 32 724 74 31 c.aeschlimann at acn-group.ch From khilman at deeprootsystems.com Wed Sep 8 10:52:55 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Wed, 08 Sep 2010 08:52:55 -0700 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: (Victor Rodriguez's message of "Wed, 8 Sep 2010 09:35:15 -0500") References: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> Message-ID: <871v949qqw.fsf@deeprootsystems.com> Victor Rodriguez writes: >>> +static __init void omapl138_hawk_init(void) >>> +{ >>> + ? ? int ret; >>> + >>> + ? ? davinci_serial_init(&omapl138_hawk_uart_config); >>> + >>> + ? ? /*shut down uart 1; It is not implemented in hardware */ >> >> Should be: /* Shut down ... >> >> I thought there was going to be a note here as to >> why we register UART1, but choose to shut it down? > > The UART1 is not present in the board, we are registering first the > UART0,1 and 2 and then just shut down UART1 because it is not present > in hardware. But what do you suggest. "not implemented in hardware" is not a good enough description, nor is it actually true. IIUC, the issue is that the *pins* used for UART1 are hooked up to other peripherals on the board. IOW, UART1 is not *connected* on the board, and due to pin mux conflicts, enabling UART1 will lead to spurious interrupts. A summary of this problem is what needs to accompany the line that shuts down UART1. Victor, I know you inherited this problem from the EVM board file, but it needs to be fixed in both places. Maybe you and Sekhar can come up with the right wording for the EVM file, and you can propose a patch for each board file. Thanks, Kevin From khilman at deeprootsystems.com Wed Sep 8 11:07:55 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Wed, 08 Sep 2010 09:07:55 -0700 Subject: [PATCH v2 1/2] davinci: Add generic PWM support for PWM control In-Reply-To: <1283940988-22125-1-git-send-email-sugumar@ti.com> (Sugumar Natarajan's message of "Wed, 8 Sep 2010 15:46:28 +0530") References: <1283940988-22125-1-git-send-email-sugumar@ti.com> Message-ID: <87r5h46wx0.fsf@deeprootsystems.com> Sugumar Natarajan writes: > This patch adds generic PWM support where it maintains the > list of PWM control devices that can be added or removed. > > The interface provides a list of functions that can be accessed > by the PWM control driver module and the generic PWM driver. > > The PWM control driver module such as eCAP uses the interface to > register and add itself to the list as a PWM control device. > The generic PWM driver uses the interface to search for a PWM control > device and if present, uses the device for PWM control. > > Signed-off-by: Sugumar Natarajan Some more comments below... > --- > Since v1, following changes have been made: > 1.add_pwm and remove_pwm functions have been renamed to pwm_add > and pwm_remove respectively. > > arch/arm/mach-davinci/Makefile | 3 + > arch/arm/mach-davinci/davinci_pwm.c | 116 ++++++++++++++++++++++ > arch/arm/mach-davinci/include/mach/davinci_pwm.h | 32 ++++++ > 3 files changed, 151 insertions(+), 0 deletions(-) > create mode 100644 arch/arm/mach-davinci/davinci_pwm.c > create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h > > diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile > index a7a70d1..90ca821 100644 > --- a/arch/arm/mach-davinci/Makefile > +++ b/arch/arm/mach-davinci/Makefile > @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o > obj-$(CONFIG_CPU_FREQ) += cpufreq.o > obj-$(CONFIG_CPU_IDLE) += cpuidle.o > obj-$(CONFIG_SUSPEND) += pm.o sleep.o > + > +# Generic PWM control support > +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o > diff --git a/arch/arm/mach-davinci/davinci_pwm.c b/arch/arm/mach-davinci/davinci_pwm.c > new file mode 100644 > index 0000000..aa21b7a > --- /dev/null > +++ b/arch/arm/mach-davinci/davinci_pwm.c > @@ -0,0 +1,116 @@ > +/* > + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed .as is. WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) > +{ > + unsigned int clock_freq; > + unsigned int period_cycles; > + unsigned int duty_cycle; > + > + if (!pwm || !pwm->pwm_config_device || !period_ns || > + duty_ns > period_ns) > + return -EINVAL; Is it required to have a pwm_config_device callback? To be more flexible, it might be better... > + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; > + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; > + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; ... to add 'if (pwm->pwm_config_device)' here > + pwm->pwm_config_device(pwm, period_cycles, duty_cycle); > + > + return 0; > +} > +EXPORT_SYMBOL(pwm_config); > + > +int pwm_enable(struct pwm_device *pwm) > +{ if (WARN_ON(!pwm)) return -EINVAL; For a little more safety, all of these functions should sanity-check/warn if a NULL pwm pointer is passed in. > + return clk_enable(pwm->clk); > +} > +EXPORT_SYMBOL(pwm_enable); > + > +void pwm_disable(struct pwm_device *pwm) > +{ > + clk_disable(pwm->clk); > +} > +EXPORT_SYMBOL(pwm_disable); > + > +static DEFINE_MUTEX(pwm_lock); > +static LIST_HEAD(pwm_list); > + > +struct pwm_device *pwm_request(int pwm_id, const char *label) > +{ > + struct pwm_device *pwm; > + int found = 0; A relatively minor issue, but I'm not crazy about the 'found' flag. Here's a proposal for a slightly cleaner, and more compact way to handle this: struct pwm_device *tmp_pwm, *pwm = ERR_PTR(-ENOENT); > + mutex_lock(&pwm_lock); > + > + list_for_each_entry(pwm, &pwm_list, node) { Here, iterate using 'tmp_pwm' > + if (pwm->pwm_id == pwm_id) { > + found = 1; and instead of 'found = 1', do 'pwm = tmp_pwm'; > + break; > + } > + } > + > + if (found) { this can be 'if (pwm) {' > + if (pwm->use_count == 0) { > + pwm->use_count++; > + pwm->label = label; > + } else { > + pwm = ERR_PTR(-EBUSY); > + } > + } else { > + pwm = ERR_PTR(-ENOENT); > + } and this else clause can be dropped > + mutex_unlock(&pwm_lock); > + return pwm; > +} > +EXPORT_SYMBOL(pwm_request); [...] Kevin From vm.rod25 at gmail.com Wed Sep 8 12:36:01 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Wed, 8 Sep 2010 12:36:01 -0500 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <871v949qqw.fsf@deeprootsystems.com> References: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> <871v949qqw.fsf@deeprootsystems.com> Message-ID: On Wed, Sep 8, 2010 at 10:52 AM, Kevin Hilman wrote: > Victor Rodriguez writes: > >>>> +static __init void omapl138_hawk_init(void) >>>> +{ >>>> + ? ? int ret; >>>> + >>>> + ? ? davinci_serial_init(&omapl138_hawk_uart_config); >>>> + >>>> + ? ? /*shut down uart 1; It is not implemented in hardware */ >>> >>> Should be: /* Shut down ... >>> >>> I thought there was going to be a note here as to >>> why we register UART1, but choose to shut it down? >> >> The UART1 is not present in the board, we are registering first the >> UART0,1 and 2 and then just shut down UART1 because it is not present >> in hardware. But what do you suggest. > > "not implemented in hardware" is not a good enough description, nor is > it actually true. > > IIUC, the issue is that the *pins* used for UART1 are hooked up to other > peripherals on the board. ?IOW, UART1 is not *connected* on the board, > and due to pin mux conflicts, enabling UART1 will lead to spurious > interrupts. > > A summary of this problem is what needs to accompany the line that shuts > down UART1. > > Victor, I know you inherited this problem from the EVM board file, but > it needs to be fixed in both places. ?Maybe you and Sekhar can come up > with the right wording for the EVM file, and you can propose a patch for > each board file. > > Thanks, > > Kevin > HI Is this paragraph better ? /* Shut down UART 1; It shares pins with McASP0 transmit/receive master clock. Enable it will produce fake interrupts */ __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); I will keep in touch with Sekhar to fix this problem. but is there any thing else to modify to the hawk board patch? Thanks VIctor Rodriguez From sshtylyov at mvista.com Wed Sep 8 12:41:32 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Wed, 08 Sep 2010 21:41:32 +0400 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: References: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> <871v949qqw.fsf@deeprootsystems.com> Message-ID: <4C87CACC.6030905@mvista.com> Hello. Victor Rodriguez wrote: >>>>> +static __init void omapl138_hawk_init(void) >>>>> +{ >>>>> + int ret; >>>>> + >>>>> + davinci_serial_init(&omapl138_hawk_uart_config); >>>>> + >>>>> + /*shut down uart 1; It is not implemented in hardware */ >>>> Should be: /* Shut down ... >>>> I thought there was going to be a note here as to >>>> why we register UART1, but choose to shut it down? >>> The UART1 is not present in the board, we are registering first the >>> UART0,1 and 2 and then just shut down UART1 because it is not present >>> in hardware. But what do you suggest. >> "not implemented in hardware" is not a good enough description, nor is >> it actually true. >> IIUC, the issue is that the *pins* used for UART1 are hooked up to other >> peripherals on the board. IOW, UART1 is not *connected* on the board, >> and due to pin mux conflicts, enabling UART1 will lead to spurious >> interrupts. >> A summary of this problem is what needs to accompany the line that shuts >> down UART1. >> Victor, I know you inherited this problem from the EVM board file, but >> it needs to be fixed in both places. Maybe you and Sekhar can come up >> with the right wording for the EVM file, and you can propose a patch for >> each board file. >> Thanks, >> Kevin > HI > Is this paragraph better ? > /* > Shut down UART 1; It shares pins with > McASP0 transmit/receive master clock. > Enable it will produce fake interrupts Enabling. > */ The preferred style for the multi-line comments is this (according to CodingStyle): /* * bla * bla */ WBR, Sergei From khilman at deeprootsystems.com Wed Sep 8 12:45:55 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Wed, 08 Sep 2010 10:45:55 -0700 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: (Victor Rodriguez's message of "Wed, 8 Sep 2010 12:36:01 -0500") References: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> <871v949qqw.fsf@deeprootsystems.com> Message-ID: <87iq2g3z8s.fsf@deeprootsystems.com> Victor Rodriguez writes: > On Wed, Sep 8, 2010 at 10:52 AM, Kevin Hilman > wrote: >> Victor Rodriguez writes: >> >>>>> +static __init void omapl138_hawk_init(void) >>>>> +{ >>>>> + ? ? int ret; >>>>> + >>>>> + ? ? davinci_serial_init(&omapl138_hawk_uart_config); >>>>> + >>>>> + ? ? /*shut down uart 1; It is not implemented in hardware */ >>>> >>>> Should be: /* Shut down ... >>>> >>>> I thought there was going to be a note here as to >>>> why we register UART1, but choose to shut it down? >>> >>> The UART1 is not present in the board, we are registering first the >>> UART0,1 and 2 and then just shut down UART1 because it is not present >>> in hardware. But what do you suggest. >> >> "not implemented in hardware" is not a good enough description, nor is >> it actually true. >> >> IIUC, the issue is that the *pins* used for UART1 are hooked up to other >> peripherals on the board. ?IOW, UART1 is not *connected* on the board, >> and due to pin mux conflicts, enabling UART1 will lead to spurious >> interrupts. >> >> A summary of this problem is what needs to accompany the line that shuts >> down UART1. >> >> Victor, I know you inherited this problem from the EVM board file, but >> it needs to be fixed in both places. ?Maybe you and Sekhar can come up >> with the right wording for the EVM file, and you can propose a patch for >> each board file. >> >> Thanks, >> >> Kevin >> > > HI > > Is this paragraph better ? It's better except for it doesn't follow the multi-line comment style. :) (search for 'muti-line' in Documentation/CodingStyle for details) > /* > Shut down UART 1; It shares pins with > McASP0 transmit/receive master clock. > Enable it will produce fake interrupts > */ s/fake/spurious/. Also, I would like to see this described in terms of how the board is wired. IOW, reading this comment, you might assume you could use UART1 if you're not using McASP0. However, IIUC, you cannot because the board has been wired such that UART1 is not not connected at all. > __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > > I will keep in touch with Sekhar to fix this problem. but is there any > thing else to modify to the hawk board patch? Nothing else that I saw, but Sekhar had several comments that need to be addressed. Thanks, Kevin From vm.rod25 at gmail.com Wed Sep 8 14:16:19 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Wed, 8 Sep 2010 14:16:19 -0500 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard Message-ID: <1283973379-5179-1-git-send-email-vm.rod25@gmail.com> This patch adds initial support for the Hawkboard-L138 system It is under the machine name "omapl138_hawkboard". This system is based on the da850 davinci CPU architecture. Information on these system may be found at http://www.hawkboard.org. Basic support for the UART console is included in this patch. Signed-off-by: Victor Rodriguez --- Changes since v4: 1) Registering UART 0 and UART 2, UART 1 is not available on hardware 2) Add Watch dog timer function Notes: This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 from Kernel development tree for TI DaVinci family of processors. This patch works with da8xx_omapl_defconfig plus this patch. Depends on Michael Williamson patches: http://alturl.com/hha7u and http://alturl.com/qy4cr arch/arm/configs/da8xx_omapl_defconfig | 1 + arch/arm/mach-davinci/Kconfig | 8 +++ arch/arm/mach-davinci/Makefile | 1 + arch/arm/mach-davinci/board-da850-hawk.c | 72 +++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/uncompress.h | 1 + 5 files changed, 83 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/board-da850-hawk.c diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig index 3952a4e..d7cb4b8 100644 --- a/arch/arm/configs/da8xx_omapl_defconfig +++ b/arch/arm/configs/da8xx_omapl_defconfig @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y CONFIG_ARCH_DAVINCI=y CONFIG_ARCH_DAVINCI_DA830=y CONFIG_ARCH_DAVINCI_DA850=y +CONFIG_MACH_OMAPL138_HAWKBOARD=y CONFIG_DAVINCI_RESET_CLOCKS=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 2bf03e9..5e5d8a3 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -185,6 +185,14 @@ config MACH_TNETV107X help Say Y here to select the TI TNETV107X Evaluation Module. +config MACH_OMAPL138_HAWKBOARD + bool "TI AM1808 / OMAPL-138 Hawkboard platform" + depends on ARCH_DAVINCI_DA850 + help + Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard platform . + Information of this board may be found at + http://www.hawkboard.org/ + config DAVINCI_MUX bool "DAVINCI multiplexing support" depends on ARCH_DAVINCI diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 77a0f71..484071d 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-da850-hawk.o # Power Management obj-$(CONFIG_CPU_FREQ) += cpufreq.o diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c new file mode 100644 index 0000000..3d5625d --- /dev/null +++ b/arch/arm/mach-davinci/board-da850-hawk.c @@ -0,0 +1,72 @@ +/* + * Hawkboard.org based on TI's OMAP-L138 Platform + * + * Initial code: Syed Mohammed Khasim + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 +#include +#include +#include + +#include +#include + +#include +#include + +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { + .enabled_uarts = 0x7, +}; + +static __init void omapl138_hawk_init(void) +{ + int ret; + + davinci_serial_init(&omapl138_hawk_uart_config); + + /* + * Shut down UART 1; It shares pins with + * McASP0 transmit/receive master clock, + * and it's imposible to access by expancion conector + * Enable it will produce fake interrupts + */ + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); + + ret = da8xx_register_watchdog(); + if (ret) + pr_warning("omapl138_hawk_init:\ + watchdog registration failed: %d\n", + ret); +} + +#ifdef CONFIG_SERIAL_8250_CONSOLE +static int __init omapl138_hawk_console_init(void) +{ + if (!machine_is_omapl138_hawkboard()) + return 0; + + return add_preferred_console("ttyS", 2, "115200"); +} +console_initcall(omapl138_hawk_console_init); +#endif + +static void __init omapl138_hawk_map_io(void) +{ + da850_init(); +} + +MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") + .phys_io = IO_PHYS, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, + .boot_params = (DA8XX_DDR_BASE + 0x100), + .map_io = omapl138_hawk_map_io, + .init_irq = cp_intc_init, + .timer = &davinci_timer, + .init_machine = omapl138_hawk_init, +MACHINE_END diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h index 15a6192..640f834 100644 --- a/arch/arm/mach-davinci/include/mach/uncompress.h +++ b/arch/arm/mach-davinci/include/mach/uncompress.h @@ -88,6 +88,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) /* DA8xx boards */ DEBUG_LL_DA8XX(davinci_da830_evm, 2); DEBUG_LL_DA8XX(davinci_da850_evm, 2); + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); /* TNETV107x boards */ DEBUG_LL_TNETV107X(tnetv107x, 1); -- 1.6.0.5 From vm.rod25 at gmail.com Wed Sep 8 14:20:06 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Wed, 8 Sep 2010 14:20:06 -0500 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard Message-ID: <1283973606-5269-1-git-send-email-vm.rod25@gmail.com> This patch adds initial support for the Hawkboard-L138 system It is under the machine name "omapl138_hawkboard". This system is based on the da850 davinci CPU architecture. Information on these system may be found at http://www.hawkboard.org. Basic support for the UART console is included in this patch. Signed-off-by: Victor Rodriguez --- Changes since v4: 1) Registering UART 0 and UART 2, UART 1 is not available on hardware 2) Add Watch dog timer function Notes: This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 from Kernel development tree for TI DaVinci family of processors. This patch works with da8xx_omapl_defconfig plus this patch. Depends on Michael Williamson patches: http://alturl.com/hha7u and http://alturl.com/qy4cr arch/arm/configs/da8xx_omapl_defconfig | 1 + arch/arm/mach-davinci/Kconfig | 8 +++ arch/arm/mach-davinci/Makefile | 1 + arch/arm/mach-davinci/board-da850-hawk.c | 72 +++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/uncompress.h | 1 + 5 files changed, 83 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/board-da850-hawk.c diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig index 3952a4e..d7cb4b8 100644 --- a/arch/arm/configs/da8xx_omapl_defconfig +++ b/arch/arm/configs/da8xx_omapl_defconfig @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y CONFIG_ARCH_DAVINCI=y CONFIG_ARCH_DAVINCI_DA830=y CONFIG_ARCH_DAVINCI_DA850=y +CONFIG_MACH_OMAPL138_HAWKBOARD=y CONFIG_DAVINCI_RESET_CLOCKS=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 2bf03e9..5e5d8a3 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -185,6 +185,14 @@ config MACH_TNETV107X help Say Y here to select the TI TNETV107X Evaluation Module. +config MACH_OMAPL138_HAWKBOARD + bool "TI AM1808 / OMAPL-138 Hawkboard platform" + depends on ARCH_DAVINCI_DA850 + help + Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard platform . + Information of this board may be found at + http://www.hawkboard.org/ + config DAVINCI_MUX bool "DAVINCI multiplexing support" depends on ARCH_DAVINCI diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 77a0f71..484071d 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-da850-hawk.o # Power Management obj-$(CONFIG_CPU_FREQ) += cpufreq.o diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c new file mode 100644 index 0000000..100d3b6 --- /dev/null +++ b/arch/arm/mach-davinci/board-da850-hawk.c @@ -0,0 +1,72 @@ +/* + * Hawkboard.org based on TI's OMAP-L138 Platform + * + * Initial code: Syed Mohammed Khasim + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 +#include +#include +#include + +#include +#include + +#include +#include + +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { + .enabled_uarts = 0x7, +}; + +static __init void omapl138_hawk_init(void) +{ + int ret; + + davinci_serial_init(&omapl138_hawk_uart_config); + + /* + * Shut down UART 1; It shares pins with + * McASP0 transmit/receive master clock, + * and it's imposible to access by expancion conector + * Enable it will produce spurious interrupts + */ + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); + + ret = da8xx_register_watchdog(); + if (ret) + pr_warning("omapl138_hawk_init:\ + watchdog registration failed: %d\n", + ret); +} + +#ifdef CONFIG_SERIAL_8250_CONSOLE +static int __init omapl138_hawk_console_init(void) +{ + if (!machine_is_omapl138_hawkboard()) + return 0; + + return add_preferred_console("ttyS", 2, "115200"); +} +console_initcall(omapl138_hawk_console_init); +#endif + +static void __init omapl138_hawk_map_io(void) +{ + da850_init(); +} + +MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") + .phys_io = IO_PHYS, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, + .boot_params = (DA8XX_DDR_BASE + 0x100), + .map_io = omapl138_hawk_map_io, + .init_irq = cp_intc_init, + .timer = &davinci_timer, + .init_machine = omapl138_hawk_init, +MACHINE_END diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h index 15a6192..640f834 100644 --- a/arch/arm/mach-davinci/include/mach/uncompress.h +++ b/arch/arm/mach-davinci/include/mach/uncompress.h @@ -88,6 +88,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) /* DA8xx boards */ DEBUG_LL_DA8XX(davinci_da830_evm, 2); DEBUG_LL_DA8XX(davinci_da850_evm, 2); + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); /* TNETV107x boards */ DEBUG_LL_TNETV107X(tnetv107x, 1); -- 1.6.0.5 From sshtylyov at mvista.com Wed Sep 8 14:24:13 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Wed, 08 Sep 2010 23:24:13 +0400 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <1283973379-5179-1-git-send-email-vm.rod25@gmail.com> References: <1283973379-5179-1-git-send-email-vm.rod25@gmail.com> Message-ID: <4C87E2DD.5030009@mvista.com> Hello. Victor Rodriguez wrote: > This patch adds initial support for the Hawkboard-L138 system > It is under the machine name "omapl138_hawkboard". > This system is based on the da850 davinci CPU architecture. > Information on these system may be found at http://www.hawkboard.org. > Basic support for the UART console is included in this patch. > Signed-off-by: Victor Rodriguez > --- > Changes since v4: > 1) Registering UART 0 and UART 2, UART 1 is not available on hardware You are still registering all 3 but then disable UART1. > 2) Add Watch dog timer function [...] > diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c > new file mode 100644 > index 0000000..3d5625d > --- /dev/null > +++ b/arch/arm/mach-davinci/board-da850-hawk.c > @@ -0,0 +1,72 @@ > +/* > + * Hawkboard.org based on TI's OMAP-L138 Platform > + * > + * Initial code: Syed Mohammed Khasim > + * > + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 > +#include > +#include > +#include > + > +#include > +#include > + > +#include > +#include > + > +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { > + .enabled_uarts = 0x7, > +}; > + > +static __init void omapl138_hawk_init(void) > +{ > + int ret; > + > + davinci_serial_init(&omapl138_hawk_uart_config); > + > + /* > + * Shut down UART 1; It shares pins with > + * McASP0 transmit/receive master clock, > + * and it's imposible to access by expancion conector > + * Enable it will produce fake interrupts > + */ > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > + > + ret = da8xx_register_watchdog(); > + if (ret) > + pr_warning("omapl138_hawk_init:\ > + watchdog registration failed: %d\n", Don't do this! Your message will get extra spaces in it. Instead do: pr_warning("omapl138_hawk_init: " "watchdog registration failed: %d\n", > + ret); > +} > + WBR, Sergei From vm.rod25 at gmail.com Wed Sep 8 14:51:31 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Wed, 8 Sep 2010 14:51:31 -0500 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard Message-ID: <1283975491-5984-1-git-send-email-vm.rod25@gmail.com> This patch adds initial support for the Hawkboard-L138 system It is under the machine name "omapl138_hawkboard". This system is based on the da850 davinci CPU architecture. Information on these system may be found at http://www.hawkboard.org. Basic support for the UART console is included in this patch. Signed-off-by: Victor Rodriguez --- Changes since v4: 1) Disable UART1 because it produces spurious interrupts 2) Add Watch dog timer function Notes: This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 from Kernel development tree for TI DaVinci family of processors. This patch works with da8xx_omapl_defconfig plus this patch. Depends on Michael Williamson patches: http://alturl.com/hha7u and http://alturl.com/qy4cr arch/arm/configs/da8xx_omapl_defconfig | 1 + arch/arm/mach-davinci/Kconfig | 8 +++ arch/arm/mach-davinci/Makefile | 1 + arch/arm/mach-davinci/board-da850-hawk.c | 72 +++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/uncompress.h | 1 + 5 files changed, 83 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/board-da850-hawk.c diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig index 3952a4e..d7cb4b8 100644 --- a/arch/arm/configs/da8xx_omapl_defconfig +++ b/arch/arm/configs/da8xx_omapl_defconfig @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y CONFIG_ARCH_DAVINCI=y CONFIG_ARCH_DAVINCI_DA830=y CONFIG_ARCH_DAVINCI_DA850=y +CONFIG_MACH_OMAPL138_HAWKBOARD=y CONFIG_DAVINCI_RESET_CLOCKS=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 2bf03e9..5e5d8a3 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -185,6 +185,14 @@ config MACH_TNETV107X help Say Y here to select the TI TNETV107X Evaluation Module. +config MACH_OMAPL138_HAWKBOARD + bool "TI AM1808 / OMAPL-138 Hawkboard platform" + depends on ARCH_DAVINCI_DA850 + help + Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard platform . + Information of this board may be found at + http://www.hawkboard.org/ + config DAVINCI_MUX bool "DAVINCI multiplexing support" depends on ARCH_DAVINCI diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 77a0f71..484071d 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-da850-hawk.o # Power Management obj-$(CONFIG_CPU_FREQ) += cpufreq.o diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c new file mode 100644 index 0000000..c4596b1 --- /dev/null +++ b/arch/arm/mach-davinci/board-da850-hawk.c @@ -0,0 +1,72 @@ +/* + * Hawkboard.org based on TI's OMAP-L138 Platform + * + * Initial code: Syed Mohammed Khasim + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 +#include +#include +#include + +#include +#include + +#include +#include + +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { + .enabled_uarts = 0x7, +}; + +static __init void omapl138_hawk_init(void) +{ + int ret; + + davinci_serial_init(&omapl138_hawk_uart_config); + + /* + * Shut down UART 1; It shares pins with + * McASP0 transmit/receive master clock, + * and it's imposible to access by expancion conector + * Enable it will produce spurious interrupts + */ + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); + + ret = da8xx_register_watchdog(); + if (ret) + pr_warning("omapl138_hawk_init: " + "watchdog registration failed: %d\n", + ret); +} + +#ifdef CONFIG_SERIAL_8250_CONSOLE +static int __init omapl138_hawk_console_init(void) +{ + if (!machine_is_omapl138_hawkboard()) + return 0; + + return add_preferred_console("ttyS", 2, "115200"); +} +console_initcall(omapl138_hawk_console_init); +#endif + +static void __init omapl138_hawk_map_io(void) +{ + da850_init(); +} + +MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") + .phys_io = IO_PHYS, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, + .boot_params = (DA8XX_DDR_BASE + 0x100), + .map_io = omapl138_hawk_map_io, + .init_irq = cp_intc_init, + .timer = &davinci_timer, + .init_machine = omapl138_hawk_init, +MACHINE_END diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h index 15a6192..640f834 100644 --- a/arch/arm/mach-davinci/include/mach/uncompress.h +++ b/arch/arm/mach-davinci/include/mach/uncompress.h @@ -88,6 +88,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) /* DA8xx boards */ DEBUG_LL_DA8XX(davinci_da830_evm, 2); DEBUG_LL_DA8XX(davinci_da850_evm, 2); + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); /* TNETV107x boards */ DEBUG_LL_TNETV107X(tnetv107x, 1); -- 1.6.0.5 From cyril at ti.com Wed Sep 8 16:59:15 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Wed, 08 Sep 2010 17:59:15 -0400 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C86F369.6040906@criticallink.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <871v95f2xv.fsf@deeprootsystems.com> <4C86F369.6040906@criticallink.com> Message-ID: <4C880733.5010909@ti.com> Hi Mike, [...] > So I just pulled this to test it out on a da850 based board > (mitydspl138), and I'm having some problems. I'm hoping it's just > operator error. Probably not, considering that this series had not been tested on da8xx platforms. Thanks for jumping in! > I have a TI TLK100PHP PHY at address 0x3. The boot log shows: > > [snip] > davinci_mdio davinci_mdio.0: davinci mdio revision 1.5 > davinci_mdio davinci_mdio.0: detected phy mask fffffff7 > davinci_mdio.0: probed > davinci_mdio davinci_mdio.0: phy[3]: device 0:03, driver unknown > [snip] So far so good. The MDIO code seems to have done its part and latched on to the correct phy. To answer your question from below, the "driver unknown" implies that the generic phy driver has been attached to the detected phy. > and then in the init scripts, following udev population I get a > "Configuring network interfaces... " > > and the boot process just hangs. Not a peep from emac? Strange. > I went back and did a menuconfig, I didn't see an option for TI PHY support, but > shouldn't there be a "generic" PHY driver that defaults if one isn't matched? I > do have TI DaVinci EMAC/MDIO/CPDMA support enabled under the Ethernet (10 or 100 Mbit). > > Anyway, I've only looked at this for about 15 minutes, and I was hoping anyone might > point out something obvious. If there are hints anyone might have for debugging, I'd > appreciate them as well. Or, if anyone has tested this with a da850 evm, that would > point me to a problem in the board file. I spent some time today on testing this series on a da830 evm board (sorry, couldn't manage to scrounge up a da850 platform). In the process, I have had to put in some fixes, particularly for the phy-association piece. You can preview these commits on my repo's gitweb [1]. Cheers Cyril. 1. http://arago-project.org/git/people/?p=cyril/linux-tnetv107x.git;a=log;h=emac-cpdma-mdio-fixes From michael.williamson at criticallink.com Wed Sep 8 19:47:38 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Wed, 08 Sep 2010 20:47:38 -0400 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C880733.5010909@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <871v95f2xv.fsf@deeprootsystems.com> <4C86F369.6040906@criticallink.com> <4C880733.5010909@ti.com> Message-ID: <4C882EAA.9030903@criticallink.com> Hi Cyril, On 09/08/2010 05:59 PM, Cyril Chemparathy wrote: > Hi Mike, > > [...] >> So I just pulled this to test it out on a da850 based board >> (mitydspl138), and I'm having some problems. I'm hoping it's just >> operator error. > > Probably not, considering that this series had not been tested on da8xx > platforms. Thanks for jumping in! > Jumped, pushed, you say tomato, ... ;^) >> I have a TI TLK100PHP PHY at address 0x3. The boot log shows: >> >> [snip] >> davinci_mdio davinci_mdio.0: davinci mdio revision 1.5 >> davinci_mdio davinci_mdio.0: detected phy mask fffffff7 >> davinci_mdio.0: probed >> davinci_mdio davinci_mdio.0: phy[3]: device 0:03, driver unknown >> [snip] > > So far so good. The MDIO code seems to have done its part and latched > on to the correct phy. To answer your question from below, the "driver > unknown" implies that the generic phy driver has been attached to the > detected phy. > >> and then in the init scripts, following udev population I get a >> "Configuring network interfaces... " >> >> and the boot process just hangs. > > Not a peep from emac? Strange. > So I went in and set the debug_level to netif_msg_init() to -1 in the davinci_emac driver. The only thing I get during the boot process is: net eth0: DaVinci EMAC Probe found device (regs: 01e23000, irq: 33) which is good (I also added some debug to make sure probe actually completes), but I don't see *anything* else. I guess I would have expected to see something out of the emac_dev_open. So I added some more debug in there, it's hanging in the phy_connect() call. The phy_id it came up with was correct "0:03". [snip] > > I spent some time today on testing this series on a da830 evm board > (sorry, couldn't manage to scrounge up a da850 platform). In the > process, I have had to put in some fixes, particularly for the > phy-association piece. You can preview these commits on my repo's > gitweb [1]. > I did apply the requeue on early end-of-queue patch. No difference, which is not surprising as it's dying in the phy_connect. I don't think I need the others, as the correct phy_id is being located by the MDIO probe headed into the phy_connect call (pointer is valid, string is OK, etc.). If I have time I can continue to poke around, but I'm really not up on this chunk of code... -Mike From lindenq at gmail.com Wed Sep 8 20:49:59 2010 From: lindenq at gmail.com (=?GB2312?B?wdbWx9PC?=) Date: Thu, 9 Sep 2010 09:49:59 +0800 Subject: USB support Message-ID: ## Booting kernel from Legacy Image at 02080000 ... Image Name: Linux-2.6.32-rc2-davinci1 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1949388 Bytes = 1.9 MB Load Address: 80008000 Entry Point: 80008000 Verifying Checksum ... OK Loading Kernel Image ... OK OK Starting kernel ... Uncompressing Linux............................................................. ................................................................. done, booting the kernel. Linux version 2.6.32-rc2-davinci1 (lzy at lzy-desktop) (gcc version 4.3.3 (Sourcery G++ Lite 2009q1-203) ) #6 PREEMPT Thu Sep 9 09:03:40 CST 2010 CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177 CPU: VIVT data cache, VIVT instruction cache Machine: DaVinci DM644x EVM Memory policy: ECC disabled, Data cache writeback DaVinci dm6446a variant 0x1 Built 1 zonelists in Zone order, mobility grouping on. Total pages: 30480 Kernel command line: mem=120M console=ttyS0,115200n8 root=/dev/ram0 initrd=0x838 00000,0xc70000 ip=192.168.0.128:192.168.0.6:192.168.0.1:255.255.255.0:::eth0:off PID hash table entries: 512 (order: -1, 2048 bytes) Dentry cache hash table entries: 16384 (order: 4, 65536 bytes) Inode-cache hash table entries: 8192 (order: 3, 32768 bytes) Memory: 120MB = 120MB total Memory: 104716KB available (3616K code, 356K data, 132K init, 0K highmem) SLUB: Genslabs=11, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 Hierarchical RCU implementation. NR_IRQS:245 Console: colour dummy device 80x30 Calibrating delay loop... 147.86 BogoMIPS (lpj=739328) Mount-cache hash table entries: 512 CPU: Testing write buffer coherency: ok DaVinci: 71 gpio irqs NET: Registered protocol family 16 bio: create slab at 0 SCSI subsystem initialized usbcore: registered new interface driver usbfs usbcore: registered new interface driver hub usbcore: registered new device driver usb pcf857x: probe of 1-0038 failed with error -121 pcf857x: probe of 1-0039 failed with error -121 pcf857x: probe of 1-003a failed with error -121 vpss vpss: dm644x_vpss vpss probed vpss vpss: dm644x_vpss vpss probe success ch0 default output "COMPOSITE", mode "NTSC" VPBE Encoder Initialized LogicPD encoder initialized Switching to clocksource timer0_1 musb_hdrc: version 6.0, pio, host, debug=0 NET: Registered protocol family 2 IP route cache hash table entries: 1024 (order: 0, 4096 bytes) TCP established hash table entries: 4096 (order: 3, 32768 bytes) TCP bind hash table entries: 4096 (order: 2, 16384 bytes) TCP: Hash tables configured (established 4096 bind 4096) TCP reno registered NET: Registered protocol family 1 RPC: Registered udp transport module. RPC: Registered tcp transport module. RPC: Registered tcp NFSv4.1 backchannel transport module. Trying to unpack rootfs image as initramfs... rootfs image is not initramfs (no cpio magic); looks like an initrd Freeing initrd memory: 12736K msgmni has been set to 229 alg: No test for stdrng (krng) io scheduler noop registered io scheduler anticipatory registered (default) Console: switching to colour frame buffer device 90x30 davincifb davincifb: dm_osd0_fb: 720x480x16 at 0,0 with framebuffer size 675KB davincifb davincifb: dm_vid0_fb: 0x0x16 at 0,0 with framebuffer size 1020KB davincifb davincifb: dm_osd1_fb: 720x480x4 at 0,0 with framebuffer size 675KB davincifb davincifb: dm_vid1_fb: 0x0x16 at 0,0 with framebuffer size 1020KB davincifb davincifb.0: dm_osd0_fb: Failed to obtain ownership of OSD window. Serial: 8250/16550 driver, 3 ports, IRQ sharing disabled serial8250.0: ttyS0 at MMIO 0x1c20000 (irq = 40) is a 16550A console [ttyS0] enabled serial8250 serial8250.0: unable to register port at index 1 (IO0 MEM1c20400 IRQ4 1): -22 serial8250 serial8250.0: unable to register port at index 2 (IO0 MEM1c20800 IRQ4 2): -22 brd: module loaded at24 1-0050: 32768 byte 24c256 EEPROM (writable) Read MAC addr from EEPROM: ff:ff:ff:ff:ff:ff Uniform Multi-Platform E-IDE driver ide-gd driver 1.18 ide0: MMIO-DMA ide0: no devices on the port ide0 at 0xfec661f0-0xfec661f7,0xfec663f6 on irq 22 console [netcon0] enabled netconsole: network logging started usbcore: registered new interface driver hwa-rc Initializing USB Mass Storage driver... usbcore: registered new interface driver usb-storage USB Mass Storage support registered. usbcore: registered new interface driver libusual usbcore: registered new interface driver ums-alauda usbcore: registered new interface driver ums-cypress usbcore: registered new interface driver ums-datafab usbcore: registered new interface driver ums-freecom usbcore: registered new interface driver ums-isd200 usbcore: registered new interface driver ums-jumpshot usbcore: registered new interface driver ums-karma usbcore: registered new interface driver ums-onetouch usbcore: registered new interface driver ums-sddr09 usbcore: registered new interface driver ums-sddr55 usbcore: registered new interface driver ums-usbat usbcore: registered new interface driver usbtest i2c /dev entries driver Linux video capture interface: v2.00 vpfe_init vpfe-capture: vpss clock vpss_master enabled vpfe-capture: vpss clock vpss_slave enabled vpfe-capture vpfe-capture: v4l2 device registered vpfe-capture vpfe-capture: video device registered tvp514x 1-005d: tvp514x 1-005d decoder driver registered !! vpfe-capture vpfe-capture: v4l2 sub device tvp514x registered vpfe_register_ccdc_device: DM6446 CCDC DM6446 CCDC is registered with vpfe. Trying to register davinci display video device. layer=c6d3b000,layer->video_dev=c6d3b170 Trying to register davinci display video device. layer=c6d3b800,layer->video_dev=c6d3b970 davinci_init:DaVinci V4L2 Display Driver V1.0 loaded davinci_mmc davinci_mmc.0: Using DMA, 4-bit mode TCP cubic registered NET: Registered protocol family 17 Clocks: disable unused emac Clocks: disable unused usb Clocks: disable unused timer1 davinci_emac_probe: using random MAC addr: 52:a9:7b:9f:b9:84 emac-mii: probed mmc0: host does not support reading read-only switch. assuming write-enable. mmc0: new SDHC card at address d0d2 mmcblk0: mmc0:d0d2 SD32G 29.7 GiB mmcblk0: eth0: attached PHY driver [Generic PHY] (mii_bus:phy_addr=1:01, id=221619) IP-Config: Complete: device=eth0, addr=192.168.0.128, mask=255.255.255.0, gw=192.168.0.1, host=192.168.0.128, domain=, nis-domain=(none), bootserver=192.168.0.6, rootserver=192.168.0.6, rootpath= RAMDISK: gzip image found at block 0 PHY: 1:01 - Link is Up - 100/Full VFS: Mounted root (ext2 filesystem) on device 1:0. Freeing init memory: 132K INIT: version 2.86 booting Please wait: booting... Starting udev Error: Driver 'palm_bk3710' is already registered, aborting... watchdog watchdog: heartbeat 60 sec tvp514x: module is already loaded snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_put_enum_double snd_soc_tlv320aic3x: Unknown symbol snd_soc_register_codec snd_soc_tlv320aic3x: Unknown symbol snd_soc_new_pcms snd_soc_tlv320aic3x: Unknown symbol snd_soc_add_controls snd_soc_tlv320aic3x: Unknown symbol snd_soc_register_dai snd_soc_tlv320aic3x: Unknown symbol dapm_reg_event snd_soc_tlv320aic3x: Unknown symbol snd_soc_put_enum_double snd_soc_tlv320aic3x: Unknown symbol snd_soc_free_pcms snd_soc_tlv320aic3x: Unknown symbol snd_soc_unregister_codec snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_sync snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_new_widgets snd_soc_tlv320aic3x: Unknown symbol snd_soc_info_volsw_2r snd_soc_tlv320aic3x: Unknown symbol snd_soc_get_enum_double snd_soc_tlv320aic3x: Unknown symbol snd_soc_info_volsw snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_put_volsw snd_soc_tlv320aic3x: Unknown symbol snd_soc_update_bits snd_soc_tlv320aic3x: Unknown symbol snd_soc_unregister_dai snd_soc_tlv320aic3x: Unknown symbol snd_soc_init_card snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_add_routes snd_soc_tlv320aic3x: Unknown symbol snd_soc_info_enum_double snd_soc_tlv320aic3x: Unknown symbol snd_soc_get_volsw snd_soc_tlv320aic3x: Unknown symbol snd_soc_put_volsw snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_new_controls snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_free snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_get_volsw snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_get_enum_double snd_soc_tlv320aic3x: Unknown symbol snd_soc_get_volsw_2r snd_soc_tlv320aic3x: Unknown symbol snd_soc_put_volsw_2r snd_soc_tlv320aic3x: Unknown symbol snd_soc_test_bits snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_put_enum_double snd_soc_tlv320aic3x: Unknown symbol snd_soc_register_codec snd_soc_tlv320aic3x: Unknown symbol snd_soc_new_pcms snd_soc_tlv320aic3x: Unknown symbol snd_soc_add_controls snd_soc_tlv320aic3x: Unknown symbol snd_soc_register_dai snd_soc_tlv320aic3x: Unknown symbol dapm_reg_event snd_soc_tlv320aic3x: Unknown symbol snd_soc_put_enum_double snd_soc_tlv320aic3x: Unknown symbol snd_soc_free_pcms snd_soc_tlv320aic3x: Unknown symbol snd_soc_unregister_codec snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_sync snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_new_widgets snd_soc_tlv320aic3x: Unknown symbol snd_soc_info_volsw_2r snd_soc_tlv320aic3x: Unknown symbol snd_soc_get_enum_double snd_soc_tlv320aic3x: Unknown symbol snd_soc_info_volsw snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_put_volsw snd_soc_tlv320aic3x: Unknown symbol snd_soc_update_bits snd_soc_tlv320aic3x: Unknown symbol snd_soc_unregister_dai snd_soc_tlv320aic3x: Unknown symbol snd_soc_init_card snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_add_routes snd_soc_tlv320aic3x: Unknown symbol snd_soc_info_enum_double snd_soc_tlv320aic3x: Unknown symbol snd_soc_get_volsw snd_soc_tlv320aic3x: Unknown symbol snd_soc_put_volsw snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_new_controls snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_free snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_get_volsw snd_soc_tlv320aic3x: Unknown symbol snd_soc_dapm_get_enum_double snd_soc_tlv320aic3x: Unknown symbol snd_soc_get_volsw_2r snd_soc_tlv320aic3x: Unknown symbol snd_soc_put_volsw_2r snd_soc_tlv320aic3x: Unknown symbol snd_soc_test_bits Populating dev cachetar: short write Remounting root file system... root: mount: mounting rootfs on / failed: No such file or directory ALSA: Restoring mixer settings... /usr/sbin/alsactl: load_state:1608: No soundcards found... Setting up IP spoofing protection: rp_filter. Configuring network interfaces... done. Mon Jun 21 16:35:00 UTC 2010 Configuring update-modules cat: write error: No space left on device update-modules: No such file or directory INIT: Entering runlevel: 5 Starting telnet daemon. Starting syslogd/klogd: done Starting thttpdNET: Registered protocol family 10 . _____ _____ _ _ | _ |___ ___ ___ ___ | _ |___ ___ |_|___ ___| |_ | | _| .'| . | . | | __| _| . | | | -_| _| _| |__|__|_| |__,|_ |___| |__| |_| |___|_| |___|___|_| |___| |___| Arago Project http://arago-project.org dm6446-evm ttyS0 Arago 2009.11 dm6446-evm ttyS0 -------------- next part -------------- An HTML attachment was scrubbed... URL: From sugumar at ti.com Thu Sep 9 00:53:52 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Thu, 9 Sep 2010 11:23:52 +0530 Subject: [PATCH v2 1/2] davinci: Add generic PWM support for PWM control In-Reply-To: <87r5h46wx0.fsf@deeprootsystems.com> References: <1283940988-22125-1-git-send-email-sugumar@ti.com> <87r5h46wx0.fsf@deeprootsystems.com> Message-ID: <00ce01cb4fe3$6ad29ff0$4077dfd0$@com> On Wed, Sep 08, 2010 at 21:37:55, Kevin Hilman wrote: > Sugumar Natarajan writes: > > > This patch adds generic PWM support where it maintains the > > list of PWM control devices that can be added or removed. > > > > The interface provides a list of functions that can be accessed > > by the PWM control driver module and the generic PWM driver. > > > > The PWM control driver module such as eCAP uses the interface to > > register and add itself to the list as a PWM control device. > > The generic PWM driver uses the interface to search for a PWM control > > device and if present, uses the device for PWM control. > > > > Signed-off-by: Sugumar Natarajan > > Some more comments below... > > > --- > > Since v1, following changes have been made: > > 1.add_pwm and remove_pwm functions have been renamed to pwm_add > > and pwm_remove respectively. > > > > arch/arm/mach-davinci/Makefile | 3 + > > arch/arm/mach-davinci/davinci_pwm.c | 116 ++++++++++++++++++++++ > > arch/arm/mach-davinci/include/mach/davinci_pwm.h | 32 ++++++ > > 3 files changed, 151 insertions(+), 0 deletions(-) > > create mode 100644 arch/arm/mach-davinci/davinci_pwm.c > > create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h > > > > diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile > > index a7a70d1..90ca821 100644 > > --- a/arch/arm/mach-davinci/Makefile > > +++ b/arch/arm/mach-davinci/Makefile > > @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o > > obj-$(CONFIG_CPU_FREQ) += cpufreq.o > > obj-$(CONFIG_CPU_IDLE) += cpuidle.o > > obj-$(CONFIG_SUSPEND) += pm.o sleep.o > > + > > +# Generic PWM control support > > +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o > > diff --git a/arch/arm/mach-davinci/davinci_pwm.c b/arch/arm/mach-davinci/davinci_pwm.c > > new file mode 100644 > > index 0000000..aa21b7a > > --- /dev/null > > +++ b/arch/arm/mach-davinci/davinci_pwm.c > > @@ -0,0 +1,116 @@ > > +/* > > + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ > > + * > > + * This program is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU General Public License as > > + * published by the Free Software Foundation version 2. > > + * > > + * This program is distributed .as is. WITHOUT ANY WARRANTY of any > > + * kind, whether express or implied; without even the implied warranty > > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) > > +{ > > + unsigned int clock_freq; > > + unsigned int period_cycles; > > + unsigned int duty_cycle; > > + > > + if (!pwm || !pwm->pwm_config_device || !period_ns || > > + duty_ns > period_ns) > > + return -EINVAL; > > Is it required to have a pwm_config_device callback? To be more > flexible, it might be better... > > > + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; > > + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; > > + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; > > ... to add 'if (pwm->pwm_config_device)' here > > > + pwm->pwm_config_device(pwm, period_cycles, duty_cycle); > > + > > + return 0; > > +} > > +EXPORT_SYMBOL(pwm_config); > > + > > +int pwm_enable(struct pwm_device *pwm) > > +{ > if (WARN_ON(!pwm)) > return -EINVAL; > > For a little more safety, all of these functions should > sanity-check/warn if a NULL pwm pointer is passed in. > > > + return clk_enable(pwm->clk); > > +} > > +EXPORT_SYMBOL(pwm_enable); > > + > > +void pwm_disable(struct pwm_device *pwm) > > +{ > > + clk_disable(pwm->clk); > > +} > > +EXPORT_SYMBOL(pwm_disable); > > + > > +static DEFINE_MUTEX(pwm_lock); > > +static LIST_HEAD(pwm_list); > > + > > +struct pwm_device *pwm_request(int pwm_id, const char *label) > > +{ > > + struct pwm_device *pwm; > > + int found = 0; > > A relatively minor issue, but I'm not crazy about the 'found' flag. > Here's a proposal for a slightly cleaner, and more compact way to handle > this: > > struct pwm_device *tmp_pwm, *pwm = ERR_PTR(-ENOENT); > > > + mutex_lock(&pwm_lock); > > + > > + list_for_each_entry(pwm, &pwm_list, node) { > > Here, iterate using 'tmp_pwm' > > > + if (pwm->pwm_id == pwm_id) { > > + found = 1; > > and instead of 'found = 1', do 'pwm = tmp_pwm'; > > > + break; > > + } > > + } > > + > > + if (found) { > > this can be 'if (pwm) {' > > > + if (pwm->use_count == 0) { > > + pwm->use_count++; > > + pwm->label = label; > > + } else { > > + pwm = ERR_PTR(-EBUSY); > > + } > > + } else { > > + pwm = ERR_PTR(-ENOENT); > > + } > > and this else clause can be dropped > > > + mutex_unlock(&pwm_lock); > > + return pwm; > > +} > > +EXPORT_SYMBOL(pwm_request); > > [...] > Kevin, I received your comments . I will modify and incorporate the changes in the next version. Regards, N.sugumar From arttak1586 at gmail.com Thu Sep 9 01:05:22 2010 From: arttak1586 at gmail.com (Arturo CV) Date: Thu, 9 Sep 2010 15:05:22 +0900 Subject: Adding a library (libusb) to the toolchain for cross-compilation - Working with DM6446 Message-ID: Hi all, My name is Arturo Corrales and I've been working with the DM6446 for signal processing, in which I use an USB device to gather the audio information that I need to work with, and so transfer all the information via USB communication to the Davinci DM6446. So far the USB device that I used for the information gathering works really well with the host PC, so I started adapting the USB driver so it can work in the Davinci DM6446 enviroment, and while doing this I found a problem while I tried to cross-compile an application that is needed to download the firmware to the USB Device. When I tried to do the cross-compilation of the application (C source code) it gives me this error: *arm-linux-gnueabi-gcc -pipe -g fx2_programmer.c -lusb -o fx2_programmer fx2_programmer.c:4:17: error: usb.h: No such file or directory fx2_programmer.c: In function ?dump_busses?: fx2_programmer.c:34: error: ?usb_busses? undeclared (first use in this function) fx2_programmer.c:34: error: (Each undeclared identifier is reported only once fx2_programmer.c:34: error: for each function it appears in.) fx2_programmer.c:37: error: dereferencing pointer to incomplete type fx2_programmer.c:40: error: dereferencing pointer to incomplete type fx2_programmer.c:40: error: dereferencing pointer to incomplete type fx2_programmer.c:40: error: dereferencing pointer to incomplete type fx2_programmer.c:40: error: dereferencing pointer to incomplete type fx2_programmer.c:41: error: dereferencing pointer to incomplete type fx2_programmer.c:41: error: dereferencing pointer to incomplete type fx2_programmer.c:43: error: dereferencing pointer to incomplete type fx2_programmer.c:45: error: dereferencing pointer to incomplete type fx2_programmer.c: In function ?find_device?: fx2_programmer.c:54: error: ?usb_busses? undeclared (first use in this function) fx2_programmer.c:56: error: dereferencing pointer to incomplete type fx2_programmer.c:57: error: dereferencing pointer to incomplete type fx2_programmer.c:58: error: dereferencing pointer to incomplete type fx2_programmer.c:62: error: dereferencing pointer to incomplete type fx2_programmer.c:63: error: dereferencing pointer to incomplete type fx2_programmer.c:65: error: dereferencing pointer to incomplete type fx2_programmer.c: At top level: fx2_programmer.c:71: error: expected ?=?, ?,?, ?;?, ?asm? or ?__attribute__? before ?*? token fx2_programmer.c: In function ?dump_ram?: fx2_programmer.c:83: error: ?current_handle? undeclared (first use in this function) fx2_programmer.c: In function ?dump_bulkdata?: fx2_programmer.c:108: error: ?current_handle? undeclared (first use in this function) fx2_programmer.c: In function ?bench_bulk?: fx2_programmer.c:143: error: ?current_handle? undeclared (first use in this function) fx2_programmer.c: In function ?upload_ram?: fx2_programmer.c:177: error: ?current_handle? undeclared (first use in this function) fx2_programmer.c: In function ?main?: fx2_programmer.c:299: error: dereferencing pointer to incomplete type fx2_programmer.c:299: error: dereferencing pointer to incomplete type fx2_programmer.c:300: error: ?current_handle? undeclared (first use in this function) make: *** [fx2_programmer] Error 1* Looking around to find a solution of why it didn't cross-compile properly I found that the application uses the library "libusb", and this one is no part of the Toolchain of the cross-compiler, so I was wondering if someone can tell me *How can I add this library into the toolchain so the cross-compiler can find the headers that are missing?* In case that adding the library into the Toolchain is not the solution, then maybe someone can tell me how to accomplish to cross-compile the application so I can run it from the Davinci DM6446 enviroment. Thanks a lot for your answers and time, Arturo Corrales V. KIST - Robotics System Division CJS Team -------------- next part -------------- An HTML attachment was scrubbed... URL: From arttak1586 at gmail.com Thu Sep 9 01:05:22 2010 From: arttak1586 at gmail.com (Arturo CV) Date: Thu, 9 Sep 2010 15:05:22 +0900 Subject: Adding a library (libusb) to the toolchain for cross-compilation - Working with DM6446 Message-ID: Hi all, My name is Arturo Corrales and I've been working with the DM6446 for signal processing, in which I use an USB device to gather the audio information that I need to work with, and so transfer all the information via USB communication to the Davinci DM6446. So far the USB device that I used for the information gathering works really well with the host PC, so I started adapting the USB driver so it can work in the Davinci DM6446 enviroment, and while doing this I found a problem while I tried to cross-compile an application that is needed to download the firmware to the USB Device. When I tried to do the cross-compilation of the application (C source code) it gives me this error: *arm-linux-gnueabi-gcc -pipe -g fx2_programmer.c -lusb -o fx2_programmer fx2_programmer.c:4:17: error: usb.h: No such file or directory fx2_programmer.c: In function ?dump_busses?: fx2_programmer.c:34: error: ?usb_busses? undeclared (first use in this function) fx2_programmer.c:34: error: (Each undeclared identifier is reported only once fx2_programmer.c:34: error: for each function it appears in.) fx2_programmer.c:37: error: dereferencing pointer to incomplete type fx2_programmer.c:40: error: dereferencing pointer to incomplete type fx2_programmer.c:40: error: dereferencing pointer to incomplete type fx2_programmer.c:40: error: dereferencing pointer to incomplete type fx2_programmer.c:40: error: dereferencing pointer to incomplete type fx2_programmer.c:41: error: dereferencing pointer to incomplete type fx2_programmer.c:41: error: dereferencing pointer to incomplete type fx2_programmer.c:43: error: dereferencing pointer to incomplete type fx2_programmer.c:45: error: dereferencing pointer to incomplete type fx2_programmer.c: In function ?find_device?: fx2_programmer.c:54: error: ?usb_busses? undeclared (first use in this function) fx2_programmer.c:56: error: dereferencing pointer to incomplete type fx2_programmer.c:57: error: dereferencing pointer to incomplete type fx2_programmer.c:58: error: dereferencing pointer to incomplete type fx2_programmer.c:62: error: dereferencing pointer to incomplete type fx2_programmer.c:63: error: dereferencing pointer to incomplete type fx2_programmer.c:65: error: dereferencing pointer to incomplete type fx2_programmer.c: At top level: fx2_programmer.c:71: error: expected ?=?, ?,?, ?;?, ?asm? or ?__attribute__? before ?*? token fx2_programmer.c: In function ?dump_ram?: fx2_programmer.c:83: error: ?current_handle? undeclared (first use in this function) fx2_programmer.c: In function ?dump_bulkdata?: fx2_programmer.c:108: error: ?current_handle? undeclared (first use in this function) fx2_programmer.c: In function ?bench_bulk?: fx2_programmer.c:143: error: ?current_handle? undeclared (first use in this function) fx2_programmer.c: In function ?upload_ram?: fx2_programmer.c:177: error: ?current_handle? undeclared (first use in this function) fx2_programmer.c: In function ?main?: fx2_programmer.c:299: error: dereferencing pointer to incomplete type fx2_programmer.c:299: error: dereferencing pointer to incomplete type fx2_programmer.c:300: error: ?current_handle? undeclared (first use in this function) make: *** [fx2_programmer] Error 1* Looking around to find a solution of why it didn't cross-compile properly I found that the application uses the library "libusb", and this one is no part of the Toolchain of the cross-compiler, so I was wondering if someone can tell me *How can I add this library into the toolchain so the cross-compiler can find the headers that are missing?* In case that adding the library into the Toolchain is not the solution, then maybe someone can tell me how to accomplish to cross-compile the application so I can run it from the Davinci DM6446 enviroment. Thanks a lot for your answers and time, Arturo Corrales V. KIST - Robotics System Division CJS Team -------------- next part -------------- An HTML attachment was scrubbed... URL: From lindenq at gmail.com Thu Sep 9 02:37:10 2010 From: lindenq at gmail.com (=?GB2312?B?wdbWx9PC?=) Date: Thu, 9 Sep 2010 15:37:10 +0800 Subject: No subject Message-ID: Hello,the cpu of my EVM is davinci DM6446,I update u-boot from 1.2 to 2009.11-rc2 , after updating u-boot,the EVM support 'usb start' under u-boot.But after running kernel and running file system (I update the kernel from 2.6.10 to 2.6.32),when I insert the USB Mass storage device, the system could not identify the USB device. the USB don't work. -------------- next part -------------- An HTML attachment was scrubbed... URL: From sugumar at ti.com Thu Sep 9 02:59:23 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Thu, 9 Sep 2010 13:29:23 +0530 Subject: [PATCH v3 1/2] davinci: Add generic PWM support for PWM control Message-ID: <1284019163-31399-1-git-send-email-sugumar@ti.com> This patch adds generic PWM support where it maintains the list of PWM control devices that can be added or removed. The interface provides a list of functions that can be accessed by the PWM control driver module and the generic PWM driver. The PWM control driver module such as eCAP uses the interface to register and add itself to the list as a PWM control device. The generic PWM driver uses the interface to search for a PWM control device and if present, uses the device for PWM control. Signed-off-by: Sugumar Natarajan --- Changes since v2: a. pwm_config_device callback is made more flexible b. pwm_request function code has been made more cleaner c. Sanity-check/warn has been included arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/davinci_pwm.c | 130 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 32 ++++++ 3 files changed, 165 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/davinci_pwm.c create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index a7a70d1..90ca821 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_SUSPEND) += pm.o sleep.o + +# Generic PWM control support +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o diff --git a/arch/arm/mach-davinci/davinci_pwm.c b/arch/arm/mach-davinci/davinci_pwm.c new file mode 100644 index 0000000..2962470 --- /dev/null +++ b/arch/arm/mach-davinci/davinci_pwm.c @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + unsigned int clock_freq; + unsigned int period_cycles; + unsigned int duty_cycle; + int ret = 0; + + if (WARN_ON(!pwm)) + return -EINVAL; + + if (pwm->pwm_config_device) { + if (!period_ns || duty_ns > period_ns) + return -EINVAL; + + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; + ret = pwm->pwm_config_device(pwm, period_cycles, duty_cycle); + } + + return ret; +} +EXPORT_SYMBOL(pwm_config); + +int pwm_enable(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return -EINVAL; + + return clk_enable(pwm->clk); +} +EXPORT_SYMBOL(pwm_enable); + +void pwm_disable(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return -EINVAL; + + clk_disable(pwm->clk); +} +EXPORT_SYMBOL(pwm_disable); + +static DEFINE_MUTEX(pwm_lock); +static LIST_HEAD(pwm_list); + +struct pwm_device *pwm_request(int pwm_id, const char *label) +{ + struct pwm_device pwm, *tmp_pwm = ERR_PTR(-ENOENT); + + mutex_lock(&pwm_lock); + + list_for_each_entry(pwm, &pwm_list, node) { + if (pwm->pwm_id == pwm_id) { + if (pwm->use_count == 0) { + pwm->use_count++; + pwm->label = label; + } else { + pwm = ERR_PTR(-EBUSY); + } + tmp_pwm = pwm; + break; + } + } + + mutex_unlock(&pwm_lock); + return tmp_pwm; +} +EXPORT_SYMBOL(pwm_request); + +void pwm_free(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return -EINVAL; + + mutex_lock(&pwm_lock); + + if (pwm->use_count) { + pwm->use_count--; + pwm->label = NULL; + } else { + dev_warn(&pwm->pdev->dev, "PWM device already freed\n"); + } + + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_free); + +void pwm_add(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return -EINVAL; + + mutex_lock(&pwm_lock); + list_add_tail(&pwm->node, &pwm_list); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_add); + +void pwm_remove(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return -EINVAL; + + mutex_lock(&pwm_lock); + list_del(&pwm->node); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_remove); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h new file mode 100644 index 0000000..3b7a3c8 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __DAVINCI_PWM_H +#define __DAVINCI_PWM_H + +struct pwm_device { + struct list_head node; + struct platform_device *pdev; + int (*pwm_config_device)(struct pwm_device *pwm, + unsigned int period, unsigned int dutycycle); + const char *label; + struct clk *clk; + unsigned int use_count; + unsigned int pwm_id; +}; + +void pwm_add(struct pwm_device *pwm); +void pwm_remove(struct pwm_device *pwm); + +#endif -- 1.5.6 From sugumar at ti.com Thu Sep 9 02:59:39 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Thu, 9 Sep 2010 13:29:39 +0530 Subject: [PATCH v3 2/2] davinci: da850: eCAP driver for PWM signal generation Message-ID: <1284019179-31443-1-git-send-email-sugumar@ti.com> OMAPL138/DA850 contains three instances of eCAP module. Each eCAP module has one dedicated pin that can be used either in capture mode(input) or in PWM mode. For more information on eCAP module operation, please refer to the following url. http://focus.ti.com/lit/ug/sprufl2a/sprufl2a.pdf This patch adds eCAP driver support for PWM signal generation. Signed-off-by: Sugumar Natarajan --- arch/arm/mach-davinci/Kconfig | 9 ++ arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/ecap.c | 154 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 1 + 4 files changed, 167 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/ecap.c diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 9aca60c..8192866 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -40,6 +40,7 @@ config ARCH_DAVINCI_DA850 select CP_INTC select ARCH_DAVINCI_DA8XX select ARCH_HAS_CPUFREQ + select HAVE_PWM config ARCH_DAVINCI_DA8XX select CPU_ARM926T @@ -230,6 +231,14 @@ config DAVINCI_RESET_CLOCKS probably do not want this option enabled until your device drivers work properly. +config DAVINCI_ECAP_PWM + bool "eCAP driver support for PWM control" + depends on ARCH_DAVINCI_DA8XX + depends on HAVE_PWM + default n + help + Say Y to select the eCAP module for PWM control. + endmenu endif diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 90ca821..90bd88e 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -42,3 +42,6 @@ obj-$(CONFIG_SUSPEND) += pm.o sleep.o # Generic PWM control support obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o + +# eCAP driver support for PWM +obj-$(CONFIG_DAVINCI_ECAP_PWM) += ecap.o diff --git a/arch/arm/mach-davinci/ecap.c b/arch/arm/mach-davinci/ecap.c new file mode 100644 index 0000000..e89acb2 --- /dev/null +++ b/arch/arm/mach-davinci/ecap.c @@ -0,0 +1,154 @@ +/* + * DA850/OMAP-L138 eCAP driver for PWM output generation + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CAPTURE_3_REG 0x10 +#define CAPTURE_4_REG 0x14 +#define CAPTURE_CTRL2_REG 0x2A + +#define ECAP_CTRL2_MODESL BIT(9) +#define ECAP_CTRL2_SYNCO_SEL_MASK (BIT(7) | BIT(6)) +#define ECAP_CTRL2_SYNCO_SEL_VAL (0x3 << 6) +#define ECAP_CTRL2_TSCTRSTOP BIT(4) + +/* + * ecap_config_pwm - configures the eCAP Module for the PWM output with given + * period and duty cycle. + */ + +static void ecap_config_pwm(struct pwm_device *pwm, unsigned int period_cycles, + unsigned int duty_cycle) +{ + __raw_writew(ECAP_CTRL2_MODESL | ECAP_CTRL2_SYNCO_SEL_VAL | + ECAP_CTRL2_TSCTRSTOP, pwm->mmio_base + CAPTURE_CTRL2_REG); + __raw_writel(period_cycles, pwm->mmio_base + CAPTURE_3_REG); + + /* + * 100% duty cycle is obtained when the duty cycle value is one + * greater than period ie duty cycle = period + 1 + */ + if (duty_cycle == period_cycles) + duty_cycle = duty_cycle + 1; + + __raw_writel(duty_cycle, pwm->mmio_base + CAPTURE_4_REG); +} + +static int __devinit ecap_probe(struct platform_device *pdev) +{ + struct pwm_device *pwm = NULL; + struct resource *r; + int ret = 0; + + pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); + if (!pwm) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + pwm->clk = clk_get(&pdev->dev, "ecap"); + if (IS_ERR(pwm->clk)) { + ret = PTR_ERR(pwm->clk); + goto err_free; + } + + pwm->pwm_id = pdev->id; + pwm->pdev = pdev; + pwm->pwm_config_device = ecap_config_pwm; + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "no memory resource defined\n"); + ret = -ENODEV; + goto err_free_clk; + } + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) { + dev_err(&pdev->dev, "failed to request memory resource\n"); + ret = -EBUSY; + goto err_free_clk; + } + + pwm->mmio_base = ioremap(r->start, resource_size(r)); + if (!pwm->mmio_base) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + ret = -ENODEV; + goto err_free_mem; + } + + clk_enable(pwm->clk); + pwm_add(pwm); + platform_set_drvdata(pdev, pwm); + return 0; + +err_free_mem: + release_mem_region(r->start, resource_size(r)); +err_free_clk: + clk_put(pwm->clk); +err_free: + kfree(pwm); + return ret; +} + +static int __devexit ecap_remove(struct platform_device *pdev) +{ + struct pwm_device *pwm; + struct resource *r; + + pwm = platform_get_drvdata(pdev); + if (!pwm) + return -ENODEV; + + pwm_remove(pwm); + iounmap(pwm->mmio_base); + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(r->start, resource_size(r)); + clk_put(pwm->clk); + kfree(pwm); + + return 0; +} + +static struct platform_driver ecap_driver = { + .driver = { + .name = "ecap", + .owner = THIS_MODULE, + }, + .probe = ecap_probe, + .remove = __devexit_p(ecap_remove), +}; + +static int __init ecap_init(void) +{ + return platform_driver_register(&ecap_driver); +} + +static void __exit ecap_exit(void) +{ + platform_driver_unregister(&ecap_driver); +} + +module_init(ecap_init); +module_exit(ecap_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h index 3b7a3c8..7c64dda 100644 --- a/arch/arm/mach-davinci/include/mach/davinci_pwm.h +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -22,6 +22,7 @@ struct pwm_device { unsigned int period, unsigned int dutycycle); const char *label; struct clk *clk; + void __iomem *mmio_base; unsigned int use_count; unsigned int pwm_id; }; -- 1.5.6 From sugumar at ti.com Thu Sep 9 05:03:19 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Thu, 9 Sep 2010 15:33:19 +0530 Subject: [PATCH v3 1/2] davinci: Add generic PWM support for PWM control In-Reply-To: <1284019163-31399-1-git-send-email-sugumar@ti.com> References: <1284019163-31399-1-git-send-email-sugumar@ti.com> Message-ID: <00ec01cb5006$443ac840$ccb058c0$@com> On Thu, Sep 09, 2010 at 13:29:23, Sugumar Natarajan wrote: > This patch adds generic PWM support where it maintains the list of PWM control devices that can be added or removed. > > The interface provides a list of functions that can be accessed by the PWM control driver module and the generic PWM driver. > > The PWM control driver module such as eCAP uses the interface to register and add itself to the list as a PWM control device. > The generic PWM driver uses the interface to search for a PWM control device and if present, uses the device for PWM control. > > Signed-off-by: Sugumar Natarajan > --- > Changes since v2: > a. pwm_config_device callback is made more flexible b. pwm_request function code has been made more cleaner c. Sanity-check/warn has been included > > arch/arm/mach-davinci/Makefile | 3 + > arch/arm/mach-davinci/davinci_pwm.c | 130 ++++++++++++++++++++++ > arch/arm/mach-davinci/include/mach/davinci_pwm.h | 32 ++++++ > 3 files changed, 165 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/davinci_pwm.c > create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h > > diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index a7a70d1..90ca821 100644 > --- a/arch/arm/mach-davinci/Makefile > +++ b/arch/arm/mach-davinci/Makefile > @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o > obj-$(CONFIG_CPU_FREQ) += cpufreq.o > obj-$(CONFIG_CPU_IDLE) += cpuidle.o > obj-$(CONFIG_SUSPEND) += pm.o sleep.o > + > +# Generic PWM control support > +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o > diff --git a/arch/arm/mach-davinci/davinci_pwm.c b/arch/arm/mach-davinci/davinci_pwm.c > new file mode 100644 > index 0000000..2962470 > --- /dev/null > +++ b/arch/arm/mach-davinci/davinci_pwm.c > @@ -0,0 +1,130 @@ > +/* > + * Copyright (C) 2010 Texas Instruments Incorporated - > +http://www.ti.com/ > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed .as is. WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) { > + unsigned int clock_freq; > + unsigned int period_cycles; > + unsigned int duty_cycle; > + int ret = 0; > + > + if (WARN_ON(!pwm)) > + return -EINVAL; > + > + if (pwm->pwm_config_device) { > + if (!period_ns || duty_ns > period_ns) > + return -EINVAL; > + > + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; > + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; > + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; > + ret = pwm->pwm_config_device(pwm, period_cycles, duty_cycle); > + } > + > + return ret; > +} > +EXPORT_SYMBOL(pwm_config); > + > +int pwm_enable(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return -EINVAL; > + > + return clk_enable(pwm->clk); > +} > +EXPORT_SYMBOL(pwm_enable); > + > +void pwm_disable(struct pwm_device *pwm) { > + if (WARN_ON(!pwm)) > + return -EINVAL; > + > + clk_disable(pwm->clk); > +} > +EXPORT_SYMBOL(pwm_disable); > + > +static DEFINE_MUTEX(pwm_lock); > +static LIST_HEAD(pwm_list); > + > +struct pwm_device *pwm_request(int pwm_id, const char *label) { > + struct pwm_device pwm, *tmp_pwm = ERR_PTR(-ENOENT); > + > + mutex_lock(&pwm_lock); > + > + list_for_each_entry(pwm, &pwm_list, node) { > + if (pwm->pwm_id == pwm_id) { > + if (pwm->use_count == 0) { > + pwm->use_count++; > + pwm->label = label; > + } else { > + pwm = ERR_PTR(-EBUSY); > + } > + tmp_pwm = pwm; > + break; > + } > + } > + > + mutex_unlock(&pwm_lock); > + return tmp_pwm; > +} > +EXPORT_SYMBOL(pwm_request); > + > +void pwm_free(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return -EINVAL; > + > + mutex_lock(&pwm_lock); > + > + if (pwm->use_count) { > + pwm->use_count--; > + pwm->label = NULL; > + } else { > + dev_warn(&pwm->pdev->dev, "PWM device already freed\n"); > + } > + > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(pwm_free); > + > +void pwm_add(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return -EINVAL; > + > + mutex_lock(&pwm_lock); > + list_add_tail(&pwm->node, &pwm_list); > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(pwm_add); > + > +void pwm_remove(struct pwm_device *pwm) { > + if (WARN_ON(!pwm)) > + return -EINVAL; > + > + mutex_lock(&pwm_lock); > + list_del(&pwm->node); > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(pwm_remove); > diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h > new file mode 100644 > index 0000000..3b7a3c8 > --- /dev/null > +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h > @@ -0,0 +1,32 @@ > +/* > + * Copyright (C) 2010 Texas Instruments Incorporated - > +http://www.ti.com/ > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed .as is. WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + */ > + > +#ifndef __DAVINCI_PWM_H > +#define __DAVINCI_PWM_H > + > +struct pwm_device { > + struct list_head node; > + struct platform_device *pdev; > + int (*pwm_config_device)(struct pwm_device *pwm, > + unsigned int period, unsigned int dutycycle); > + const char *label; > + struct clk *clk; > + unsigned int use_count; > + unsigned int pwm_id; > +}; > + > +void pwm_add(struct pwm_device *pwm); > +void pwm_remove(struct pwm_device *pwm); > + > +#endif > Please ignore this Patch. I will send the updated version. Regards, N.Sugumar From c.aeschlimann at acn-group.ch Thu Sep 9 06:00:07 2010 From: c.aeschlimann at acn-group.ch (Christophe Aeschlimann) Date: Thu, 09 Sep 2010 13:00:07 +0200 Subject: [PATCH v3] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <4C87AD28.5040701@acn-group.ch> References: <1283449187-9383-1-git-send-email-vm.rod25@gmail.com> <87fwxs6n6b.fsf@deeprootsystems.com> <4C801DBC.5050105@criticallink.com> <4C87AD28.5040701@acn-group.ch> Message-ID: <4C88BE37.3010601@acn-group.ch> On 08.09.2010 17:35, Christophe Aeschlimann wrote: > On 02.09.2010 23:57, Michael Williamson wrote: >> On 09/02/2010 02:00 PM, Kevin Hilman wrote: >>> Victor Rodriguez writes: >>> >> [...] >>> >>> [...] >>> >>>> +static __init void omapl138_hawk_init(void) >>>> +{ >>>> + >>>> + davinci_serial_init(&omapl138_hawk_uart_config); >>>> + >>>> + /* >>>> + * shut down uart 0 and 1; they are not used on the board and >>>> + * accessing them causes endless "too much work in irq53" messages >>>> + * with arago fs >>>> + */ >>>> + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >>>> + __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); >>> >>> I still dont' want to merge this until this issue is understood and >>> described in the changelog (or the code removed.) >>> >> >> Looking at the schametic, neither UART0 or UART1 are ever hooked up, >> so it seems >> like the "enabled_uarts" fields should just be set to 0x4 (UART2) and >> these lines >> that pound the controller removed. >> >> I'm fairly certain the "too much work in irq53" issue here has to >> do with the fact that the pins for the UART0 Rx line and output flow >> control >> line, which share pin-mux duties with the MII data lines, are hooked up >> externally to the LAN8710 chip on the hawkboard. >> >> Turns out, the pin-mux controls don't appear to really disconnect >> inputs from >> devices having input ports that share a pin via the muxing logic (only >> outputs >> are truly "muxed" at the pin level). >> >> The LAN interface is probably causing serial interrupts based on >> receive data or >> flow control logic firing for UART0, because you're enabling it in the >> enable_uarts >> mask and enumerating the device. >> >> We actually have seen a similar problem with trying to use UART1 with >> no HW flow >> control and and the McASP. The UART1 CTS/RTS lines pin-mux-share lines >> with the >> McASP AHCLKX and AHCLKR. The minute you try to enable the McASP, the >> serial driver >> gets pounded with flow control interrupts. There's no provision, that >> I can find >> in the kernel anyway, that allows for disabling CTS/RTS interrupts in the >> platform definition. (looking at a patch for this...) > > I'm having the same problem here. (UART1 + McASP sharing the same pins > and getting tons of "too much work in irq53") > > Did you find a workaround ? > > Thanks ! > > Best regards, > > Christophe > >> >> -Mike For those who have that problem using UART1 without RTS/CTS and having McASP enabled). A temporary workaround is to comment out in 8250.c the following lines (starting at line 2356): if (!(up->bugs & UART_BUG_NOMSR) && UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; This will disable the Modem Status Interrupt (for all uarts) which is triggered by the RTS/CTS lines being toggled by the McASP Clocks. Best regards, Christophe -- Christophe Aeschlimann Embedded Software Engineer Advanced Communications Networks S.A. Rue du Puits-Godet 8a 2000 Neuch?tel, Switzerland T?l. +41 32 724 74 31 c.aeschlimann at acn-group.ch From sugumar at ti.com Thu Sep 9 05:40:49 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Thu, 9 Sep 2010 16:10:49 +0530 Subject: [PATCH v4 1/2] davinci: Add generic PWM support for PWM control Message-ID: <1284028849-16680-1-git-send-email-sugumar@ti.com> This patch adds generic PWM support where it maintains the list of PWM control devices that can be added or removed. The interface provides a list of functions that can be accessed by the PWM control driver module and the generic PWM driver. The PWM control driver module such as eCAP uses the interface to register and add itself to the list as a PWM control device. The generic PWM driver uses the interface to search for a PWM control device and if present, uses the device for PWM control. Signed-off-by: Sugumar Natarajan --- Changes since v2: a) pwm_config_device callback is made more flexible. b) pwm_request function code has been made more cleaner. c) Sanity-check/warn has been included. arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/davinci_pwm.c | 130 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 32 ++++++ 3 files changed, 165 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/davinci_pwm.c create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index a7a70d1..90ca821 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_SUSPEND) += pm.o sleep.o + +# Generic PWM control support +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o diff --git a/arch/arm/mach-davinci/davinci_pwm.c b/arch/arm/mach-davinci/davinci_pwm.c new file mode 100644 index 0000000..c2b8b9a --- /dev/null +++ b/arch/arm/mach-davinci/davinci_pwm.c @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + unsigned int clock_freq; + unsigned int period_cycles; + unsigned int duty_cycle; + int ret = 0; + + if (WARN_ON(!pwm)) + return -EINVAL; + + if (pwm->pwm_config_device) { + if (!period_ns || duty_ns > period_ns) + return -EINVAL; + + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; + ret = pwm->pwm_config_device(pwm, period_cycles, duty_cycle); + } + + return ret; +} +EXPORT_SYMBOL(pwm_config); + +int pwm_enable(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return -EINVAL; + + return clk_enable(pwm->clk); +} +EXPORT_SYMBOL(pwm_enable); + +void pwm_disable(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + clk_disable(pwm->clk); +} +EXPORT_SYMBOL(pwm_disable); + +static DEFINE_MUTEX(pwm_lock); +static LIST_HEAD(pwm_list); + +struct pwm_device *pwm_request(int pwm_id, const char *label) +{ + struct pwm_device *pwm, *tmp_pwm = ERR_PTR(-ENOENT); + + mutex_lock(&pwm_lock); + + list_for_each_entry(pwm, &pwm_list, node) { + if (pwm->pwm_id == pwm_id) { + if (pwm->use_count == 0) { + pwm->use_count++; + pwm->label = label; + } else { + pwm = ERR_PTR(-EBUSY); + } + tmp_pwm = pwm; + break; + } + } + + mutex_unlock(&pwm_lock); + return tmp_pwm; +} +EXPORT_SYMBOL(pwm_request); + +void pwm_free(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + mutex_lock(&pwm_lock); + + if (pwm->use_count) { + pwm->use_count--; + pwm->label = NULL; + } else { + dev_warn(&pwm->pdev->dev, "PWM device already freed\n"); + } + + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_free); + +void pwm_add(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + mutex_lock(&pwm_lock); + list_add_tail(&pwm->node, &pwm_list); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_add); + +void pwm_remove(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + mutex_lock(&pwm_lock); + list_del(&pwm->node); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_remove); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h new file mode 100644 index 0000000..3b7a3c8 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __DAVINCI_PWM_H +#define __DAVINCI_PWM_H + +struct pwm_device { + struct list_head node; + struct platform_device *pdev; + int (*pwm_config_device)(struct pwm_device *pwm, + unsigned int period, unsigned int dutycycle); + const char *label; + struct clk *clk; + unsigned int use_count; + unsigned int pwm_id; +}; + +void pwm_add(struct pwm_device *pwm); +void pwm_remove(struct pwm_device *pwm); + +#endif -- 1.5.6 From sugumar at ti.com Thu Sep 9 05:42:04 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Thu, 9 Sep 2010 16:12:04 +0530 Subject: [PATCH v4 2/2] davinci: da850: eCAP driver for PWM signal generation Message-ID: <1284028924-16810-1-git-send-email-sugumar@ti.com> OMAPL138/DA850 contains three instances of eCAP module. Each eCAP module has one dedicated pin that can be used either in capture mode(input) or in PWM mode. For more information on eCAP module operation, please refer to the following url. http://focus.ti.com/lit/ug/sprufl2a/sprufl2a.pdf This patch adds eCAP driver support for PWM signal generation. Signed-off-by: Sugumar Natarajan --- arch/arm/mach-davinci/Kconfig | 9 ++ arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/ecap.c | 155 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 1 + 4 files changed, 168 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/ecap.c diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 9aca60c..8192866 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -40,6 +40,7 @@ config ARCH_DAVINCI_DA850 select CP_INTC select ARCH_DAVINCI_DA8XX select ARCH_HAS_CPUFREQ + select HAVE_PWM config ARCH_DAVINCI_DA8XX select CPU_ARM926T @@ -230,6 +231,14 @@ config DAVINCI_RESET_CLOCKS probably do not want this option enabled until your device drivers work properly. +config DAVINCI_ECAP_PWM + bool "eCAP driver support for PWM control" + depends on ARCH_DAVINCI_DA8XX + depends on HAVE_PWM + default n + help + Say Y to select the eCAP module for PWM control. + endmenu endif diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 90ca821..90bd88e 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -42,3 +42,6 @@ obj-$(CONFIG_SUSPEND) += pm.o sleep.o # Generic PWM control support obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o + +# eCAP driver support for PWM +obj-$(CONFIG_DAVINCI_ECAP_PWM) += ecap.o diff --git a/arch/arm/mach-davinci/ecap.c b/arch/arm/mach-davinci/ecap.c new file mode 100644 index 0000000..0247426 --- /dev/null +++ b/arch/arm/mach-davinci/ecap.c @@ -0,0 +1,155 @@ +/* + * DA850/OMAP-L138 eCAP driver for PWM output generation + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CAPTURE_3_REG 0x10 +#define CAPTURE_4_REG 0x14 +#define CAPTURE_CTRL2_REG 0x2A + +#define ECAPCTRL2_MODESL_ECAP BIT(9) +#define ECAPCTRL2_SYNCOSEL_DISABLE (0x3 << 6) +#define ECAPCTRL2_TSCTRSTOP_FREERUN BIT(4) + +/* + * ecap_config_pwm - configures the eCAP Module for the PWM output with given + * period and duty cycle. + */ + +static int ecap_config_pwm(struct pwm_device *pwm, unsigned int period_cycles, + unsigned int duty_cycle) +{ + __raw_writew(ECAPCTRL2_MODESL_ECAP | ECAPCTRL2_SYNCOSEL_DISABLE | + ECAPCTRL2_TSCTRSTOP_FREERUN, pwm->mmio_base + + CAPTURE_CTRL2_REG); + __raw_writel(period_cycles, pwm->mmio_base + CAPTURE_3_REG); + + /* + * 100% duty cycle is obtained when the duty cycle value is one + * greater than period ie duty cycle = period + 1 + */ + if (duty_cycle == period_cycles) + duty_cycle = duty_cycle + 1; + + __raw_writel(duty_cycle, pwm->mmio_base + CAPTURE_4_REG); + return 0; +} + +static int __devinit ecap_probe(struct platform_device *pdev) +{ + struct pwm_device *pwm = NULL; + struct resource *r; + int ret = 0; + + pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); + if (!pwm) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + pwm->clk = clk_get(&pdev->dev, "ecap"); + if (IS_ERR(pwm->clk)) { + ret = PTR_ERR(pwm->clk); + goto err_free; + } + + pwm->pwm_id = pdev->id; + pwm->pdev = pdev; + pwm->pwm_config_device = ecap_config_pwm; + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "no memory resource defined\n"); + ret = -ENODEV; + goto err_free_clk; + } + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) { + dev_err(&pdev->dev, "failed to request memory resource\n"); + ret = -EBUSY; + goto err_free_clk; + } + + pwm->mmio_base = ioremap(r->start, resource_size(r)); + if (!pwm->mmio_base) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + ret = -ENODEV; + goto err_free_mem; + } + + clk_enable(pwm->clk); + pwm_add(pwm); + platform_set_drvdata(pdev, pwm); + return 0; + +err_free_mem: + release_mem_region(r->start, resource_size(r)); +err_free_clk: + clk_put(pwm->clk); +err_free: + kfree(pwm); + return ret; +} + +static int __devexit ecap_remove(struct platform_device *pdev) +{ + struct pwm_device *pwm; + struct resource *r; + + pwm = platform_get_drvdata(pdev); + if (!pwm) + return -ENODEV; + + pwm_remove(pwm); + iounmap(pwm->mmio_base); + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(r->start, resource_size(r)); + clk_put(pwm->clk); + kfree(pwm); + + return 0; +} + +static struct platform_driver ecap_driver = { + .driver = { + .name = "ecap", + .owner = THIS_MODULE, + }, + .probe = ecap_probe, + .remove = __devexit_p(ecap_remove), +}; + +static int __init ecap_init(void) +{ + return platform_driver_register(&ecap_driver); +} + +static void __exit ecap_exit(void) +{ + platform_driver_unregister(&ecap_driver); +} + +module_init(ecap_init); +module_exit(ecap_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h index 3b7a3c8..7c64dda 100644 --- a/arch/arm/mach-davinci/include/mach/davinci_pwm.h +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -22,6 +22,7 @@ struct pwm_device { unsigned int period, unsigned int dutycycle); const char *label; struct clk *clk; + void __iomem *mmio_base; unsigned int use_count; unsigned int pwm_id; }; -- 1.5.6 From sshtylyov at mvista.com Thu Sep 9 09:00:22 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Thu, 09 Sep 2010 18:00:22 +0400 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <1283975491-5984-1-git-send-email-vm.rod25@gmail.com> References: <1283975491-5984-1-git-send-email-vm.rod25@gmail.com> Message-ID: <4C88E876.6020700@mvista.com> Hello. Victor Rodriguez wrote: > This patch adds initial support for the Hawkboard-L138 system > It is under the machine name "omapl138_hawkboard". > This system is based on the da850 davinci CPU architecture. > Information on these system may be found at http://www.hawkboard.org. > Basic support for the UART console is included in this patch. > Signed-off-by: Victor Rodriguez > --- > Changes since v4: > 1) Disable UART1 because it produces spurious interrupts > 2) Add Watch dog timer function You've already had all this in version 4. > diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile > index 77a0f71..484071d 100644 > --- a/arch/arm/mach-davinci/Makefile > +++ b/arch/arm/mach-davinci/Makefile > @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o > obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o > obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o > obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o > +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-da850-hawk.o I'd skip '-da850' from the name, and call the file simply board-hawk.c (or board-omapl138-hawk.c)... > diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach-davinci/board-da850-hawk.c > new file mode 100644 > index 0000000..c4596b1 > --- /dev/null > +++ b/arch/arm/mach-davinci/board-da850-hawk.c > @@ -0,0 +1,72 @@ > +/* > + * Hawkboard.org based on TI's OMAP-L138 Platform > + * > + * Initial code: Syed Mohammed Khasim > + * > + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 > +#include > +#include > +#include > + > +#include > +#include > + > +#include > +#include > + > +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { > + .enabled_uarts = 0x7, > +}; > + > +static __init void omapl138_hawk_init(void) > +{ > + int ret; > + > + davinci_serial_init(&omapl138_hawk_uart_config); > + > + /* > + * Shut down UART 1; It shares pins with > + * McASP0 transmit/receive master clock, > + * and it's imposible Only "impossible". > to access by expancion conector Only "expansion connector". Too may typos to not notice. :-) > + * Enable it will produce spurious interrupts > + */ You forgot to insert the space before '*', it should be: /* * bla * bla */ > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > + > + ret = da8xx_register_watchdog(); > + if (ret) > + pr_warning("omapl138_hawk_init: " > + "watchdog registration failed: %d\n", > + ret); Indent the previous 2 lines some more please. WBR, Sergei From vm.rod25 at gmail.com Thu Sep 9 10:21:15 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Thu, 9 Sep 2010 10:21:15 -0500 Subject: [PATCH v6] davinci: Initial support for Omapl138-Hawkboard Message-ID: <1284045675-4025-1-git-send-email-vm.rod25@gmail.com> This patch adds initial support for the Hawkboard-L138 system It is under the machine name "omapl138_hawkboard". This system is based on the da850 davinci CPU architecture. Information on these system may be found at http://www.hawkboard.org. Basic support for the UART console is included in this patch. Signed-off-by: Victor Rodriguez --- Changes since v5: 1) Change name of board file 2) Typos Notes: This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 from Kernel development tree for TI DaVinci family of processors. This patch works with da8xx_omapl_defconfig plus this patch. Depends on Michael Williamson patches: http://alturl.com/hha7u and http://alturl.com/qy4cr arch/arm/configs/da8xx_omapl_defconfig | 1 + arch/arm/mach-davinci/Kconfig | 8 +++ arch/arm/mach-davinci/Makefile | 1 + arch/arm/mach-davinci/board-omapl138-hawk.c | 72 +++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/uncompress.h | 1 + 5 files changed, 83 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/board-omapl138-hawk.c diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig index 3952a4e..d7cb4b8 100644 --- a/arch/arm/configs/da8xx_omapl_defconfig +++ b/arch/arm/configs/da8xx_omapl_defconfig @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y CONFIG_ARCH_DAVINCI=y CONFIG_ARCH_DAVINCI_DA830=y CONFIG_ARCH_DAVINCI_DA850=y +CONFIG_MACH_OMAPL138_HAWKBOARD=y CONFIG_DAVINCI_RESET_CLOCKS=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 2bf03e9..5e5d8a3 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -185,6 +185,14 @@ config MACH_TNETV107X help Say Y here to select the TI TNETV107X Evaluation Module. +config MACH_OMAPL138_HAWKBOARD + bool "TI AM1808 / OMAPL-138 Hawkboard platform" + depends on ARCH_DAVINCI_DA850 + help + Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard platform . + Information of this board may be found at + http://www.hawkboard.org/ + config DAVINCI_MUX bool "DAVINCI multiplexing support" depends on ARCH_DAVINCI diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 77a0f71..fc123b4 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o # Power Management obj-$(CONFIG_CPU_FREQ) += cpufreq.o diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c new file mode 100644 index 0000000..d1f08aa --- /dev/null +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c @@ -0,0 +1,72 @@ +/* + * Hawkboard.org based on TI's OMAP-L138 Platform + * + * Initial code: Syed Mohammed Khasim + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 +#include +#include +#include + +#include +#include + +#include +#include + +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { + .enabled_uarts = 0x7, +}; + +static __init void omapl138_hawk_init(void) +{ + int ret; + + davinci_serial_init(&omapl138_hawk_uart_config); + + /* + * Shut down UART 1; It shares pins with + * McASP0 transmit/receive master clock, + * and impossible to access by expansion connector + * Enable it will produce spurious interrupts + */ + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); + + ret = da8xx_register_watchdog(); + if (ret) + pr_warning("omapl138_hawk_init: " + "watchdog registration failed: %d\n", + ret); +} + +#ifdef CONFIG_SERIAL_8250_CONSOLE +static int __init omapl138_hawk_console_init(void) +{ + if (!machine_is_omapl138_hawkboard()) + return 0; + + return add_preferred_console("ttyS", 2, "115200"); +} +console_initcall(omapl138_hawk_console_init); +#endif + +static void __init omapl138_hawk_map_io(void) +{ + da850_init(); +} + +MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") + .phys_io = IO_PHYS, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, + .boot_params = (DA8XX_DDR_BASE + 0x100), + .map_io = omapl138_hawk_map_io, + .init_irq = cp_intc_init, + .timer = &davinci_timer, + .init_machine = omapl138_hawk_init, +MACHINE_END diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h index 15a6192..640f834 100644 --- a/arch/arm/mach-davinci/include/mach/uncompress.h +++ b/arch/arm/mach-davinci/include/mach/uncompress.h @@ -88,6 +88,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) /* DA8xx boards */ DEBUG_LL_DA8XX(davinci_da830_evm, 2); DEBUG_LL_DA8XX(davinci_da850_evm, 2); + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); /* TNETV107x boards */ DEBUG_LL_TNETV107X(tnetv107x, 1); -- 1.6.0.5 From michael.williamson at criticallink.com Thu Sep 9 13:43:12 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Thu, 09 Sep 2010 14:43:12 -0400 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C882EAA.9030903@criticallink.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <871v95f2xv.fsf@deeprootsystems.com> <4C86F369.6040906@criticallink.com> <4C880733.5010909@ti.com> <4C882EAA.9030903@criticallink.com> Message-ID: <4C892AC0.80409@criticallink.com> On 9/8/2010 8:47 PM, Michael Williamson wrote: > Hi Cyril, > > On 09/08/2010 05:59 PM, Cyril Chemparathy wrote: >> Hi Mike, >> > > So I went in and set the debug_level to netif_msg_init() to -1 in the davinci_emac > driver. The only thing I get during the boot process is: > > net eth0: DaVinci EMAC Probe found device (regs: 01e23000, irq: 33) > > which is good (I also added some debug to make sure probe actually completes), but > I don't see *anything* else. I guess I would have expected to see something out of > the emac_dev_open. So I added some more debug in there, it's hanging in the > phy_connect() call. The phy_id it came up with was correct "0:03". > > The hang is in wait_for_user_access() in the davinci_mdio_read() call. Looks like the state machine got put back into IDLE somewhere between the MDIO probe and the EMAC probe. Seems like there should be some sort of time-out and error message in the wait_for_user_access() method.... (maybe even a check for IDLE??) If I add a patch to check the state machine for IDLE and then re-enable it in the davinci_mdio_read() call, it is able to press on and come up. I don't see any calls to the davinci_mdio_suspend() call, so I am wondering if the EMAC probe routine, particularly the application of the SOFTRESET, is causing the MDIO to drop back to IDLE / disabled. I can post the patch if you like, but it is a bit of a hack... -Mike From michael.williamson at criticallink.com Thu Sep 9 14:40:57 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Thu, 9 Sep 2010 15:40:57 -0400 Subject: [PATCH] davinci: MityDSP-L138/MityARM-1808 read MAC address from I2C Prom Message-ID: <1284061257-9017-1-git-send-email-michael.williamson@criticallink.com> For the MityDSP-L138/MityARM-1808 SOMS, read the factory assigned MAC address from the onboard I2C EPROM and assign it to the emac device during platform initialization. Signed-off-by: Michael Williamson --- arch/arm/mach-davinci/board-mityomapl138.c | 55 ++++++++++++++++++++++++++++ 1 files changed, 55 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index e872fcc..e1cffb8 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,59 @@ #include #include +#define FACTORY_CONFIG_MAGIC 0x012C0138 +#define FACTORY_CONFIG_VERSION 0x00010001 + +/* Data Held in On-Board I2C device */ +struct factory_config { + uint32_t magic; + uint32_t version; + uint8_t mac[6]; + uint32_t fpga_type; + uint32_t spare; + uint32_t serialnumber; + char partnum[32]; +}; + +static struct factory_config factory_config; + +static void read_factory_config(struct memory_accessor *a, void *context) +{ + int ret; + struct davinci_soc_info *soc_info = &davinci_soc_info; + + ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config)); + if (ret != sizeof(struct factory_config)) { + pr_warning("Read Factory Config Failed: %d\n", ret); + return; + } + + if (factory_config.magic != FACTORY_CONFIG_MAGIC) { + pr_warning("Factory Config Magic Wrong (%X)\n", + factory_config.magic); + return; + } + + if (factory_config.version != FACTORY_CONFIG_VERSION) { + pr_warning("Factory Config Version Wrong (%X)\n", + factory_config.version); + return; + } + + pr_info("Found MAC = %pM\n", factory_config.mac); + pr_info("Part Number = %s\n", factory_config.partnum); + memcpy(&soc_info->emac_pdata->mac_addr[0], + &factory_config.mac[0], 6); +} + +static struct at24_platform_data mityomapl138_fd_chip = { + .byte_len = 256, + .page_size = 8, + .flags = AT24_FLAG_READONLY | AT24_FLAG_IRUGO, + .setup = read_factory_config, + .context = NULL, +}; + static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = { .bus_freq = 100, /* kHz */ .bus_delay = 0, /* usec */ @@ -150,6 +204,7 @@ static struct i2c_board_info __initdata mityomap_tps65023_info[] = { }, { I2C_BOARD_INFO("24c02", 0x50), + .platform_data = &mityomapl138_fd_chip, }, }; -- 1.7.0.4 From cyril at ti.com Thu Sep 9 14:51:58 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 09 Sep 2010 15:51:58 -0400 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C892AC0.80409@criticallink.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <871v95f2xv.fsf@deeprootsystems.com> <4C86F369.6040906@criticallink.com> <4C880733.5010909@ti.com> <4C882EAA.9030903@criticallink.com> <4C892AC0.80409@criticallink.com> Message-ID: <4C893ADE.809@ti.com> Hi Mike, [...] > The hang is in wait_for_user_access() in the davinci_mdio_read() call. Looks like > the state machine got put back into IDLE somewhere between the MDIO probe and the > EMAC probe. Seems like there should be some sort of time-out and error message > in the wait_for_user_access() method.... (maybe even a check for IDLE??) > > If I add a patch to check the state machine for IDLE and then re-enable it in the > davinci_mdio_read() call, it is able to press on and come up. I don't see any calls > to the davinci_mdio_suspend() call, so I am wondering if the EMAC probe routine, > particularly the application of the SOFTRESET, is causing the MDIO to drop back to > IDLE / disabled. > > I can post the patch if you like, but it is a bit of a hack... An EMAC soft-reset clobbering the MDIO controller state is a possibility. I will poll TI designers to see if this could be the case. In any case, a couple of unanswered questions remain: 1. Why don't other davinci devices display similar behavior? 2. If the answer to #1 above is that the timing window is pretty slim (i.e., only if an MDIO read/write is in progress during EMAC soft-reset), why do we hit this situation consistently on mityomap? I have put together a quick patch (tested dm365). See attached. Regards Cyril. -------------- next part -------------- A non-text attachment was scrubbed... Name: mdio-check-idle.patch Type: text/x-patch Size: 7775 bytes Desc: not available URL: From cyril at ti.com Thu Sep 9 16:24:14 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 09 Sep 2010 17:24:14 -0400 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C893ADE.809@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <871v95f2xv.fsf@deeprootsystems.com> <4C86F369.6040906@criticallink.com> <4C880733.5010909@ti.com> <4C882EAA.9030903@criticallink.com> <4C892AC0.80409@criticallink.com> <4C893ADE.809@ti.com> Message-ID: <4C89507E.9040407@ti.com> Hi Mike, [...] > An EMAC soft-reset clobbering the MDIO controller state is a > possibility. I will poll TI designers to see if this could be the case. To test this theory out, I hacked up a crude beat-it-to-death-and-see-if-it-breaks kinda patch (attached). This tests 10000 mdio read cycles while constantly doing an emac soft-reset. I ran this on a dm365 evm, and the test didn't raise a single failed read: > davinci_mdio davinci_mdio.0: davinci mdio revision 1.4 > davinci_mdio davinci_mdio.0: detected phy mask fffffffc > 10000 test loops completed, 10000 reads ok The failure in question seems to be limited to the da8xx family (tested da830 evm), where: > davinci_mdio davinci_mdio.0: davinci mdio revision 1.5 > davinci_mdio davinci_mdio.0: detected phy mask fffffff1 > idle triggered!! The MDIO module upgrade (rev 1.4 -> 1.5) could have something to do with this behavior. Even so, I can't explain why this issue wasn't seen on da8xx prior to this series. The original code should (at least in theory) have sporadically locked up on emac open. Regards Cyril. -------------- next part -------------- A non-text attachment was scrubbed... Name: beat-emac-soft-reset.patch Type: text/x-patch Size: 1935 bytes Desc: not available URL: From michael.williamson at criticallink.com Thu Sep 9 16:25:40 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Thu, 09 Sep 2010 17:25:40 -0400 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C893ADE.809@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <871v95f2xv.fsf@deeprootsystems.com> <4C86F369.6040906@criticallink.com> <4C880733.5010909@ti.com> <4C882EAA.9030903@criticallink.com> <4C892AC0.80409@criticallink.com> <4C893ADE.809@ti.com> Message-ID: <4C8950D4.9060102@criticallink.com> Hi Cyril, On 09/09/2010 03:51 PM, Cyril Chemparathy wrote: > Hi Mike, > > [...] >> The hang is in wait_for_user_access() in the davinci_mdio_read() call. Looks like >> the state machine got put back into IDLE somewhere between the MDIO probe and the >> EMAC probe. Seems like there should be some sort of time-out and error message >> in the wait_for_user_access() method.... (maybe even a check for IDLE??) >> >> If I add a patch to check the state machine for IDLE and then re-enable it in the >> davinci_mdio_read() call, it is able to press on and come up. I don't see any calls >> to the davinci_mdio_suspend() call, so I am wondering if the EMAC probe routine, >> particularly the application of the SOFTRESET, is causing the MDIO to drop back to >> IDLE / disabled. >> >> I can post the patch if you like, but it is a bit of a hack... > > An EMAC soft-reset clobbering the MDIO controller state is a > possibility. I will poll TI designers to see if this could be the case. > > In any case, a couple of unanswered questions remain: > > 1. Why don't other davinci devices display similar behavior? > > 2. If the answer to #1 above is that the timing window is pretty slim > (i.e., only if an MDIO read/write is in progress during EMAC > soft-reset), why do we hit this situation consistently on > mityomap? Has it been confirmed that this only happens on mityomap? Has anyone had success using a da850 evm or other da850 platform? The configuration for the mityomap, wrt to the EMAC/MII/MDIO, is pretty much identical to the da850 evm using the MII interface. The only difference I am aware of is the assigned address to the PHY chip. The reference clocks and rates are identical, AFAIK, to the evm. > > I have put together a quick patch (tested dm365). See attached. Your patch doesn't work with my board. It does attempt to reset the bus on the read call, but following wait_for_user_access() calls are timing out and the _read() and _write() calls punt. I bumped up the MDIO_TIMEOUT to 100 ms, and it works. I'm wondering if the scanning logic has to complete an entire cycle (all 32 phys) before issuing a request, and if it's a lot slower than expected. I also found that the initial scanning logic would not reliably find the PHY until I bumped up the delay time following the reset operation. Sometimes it would, sometimes no. Also, your while(1) loops with the continue conditions on the second wait_for_user_access() in the read and writes might need some consideration, i.e.: while (1) { ret = wait_for_user_access(data); if (ret == -EAGAIN) continue; if (ret < 0) break; __raw_writel(reg, &data->regs->user[0].access); ret = wait_for_user_access(data); if (ret == -EAGAIN) continue; ^^^^^^^^^ <--- this will re-issue the request.... what you want? if (ret < 0) break; reg = __raw_readl(&data->regs->user[0].access); ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO; break; } Also, on the shutdown, I get a major kernel trace. Here is the dump, as much as I could catch of it.... (I need a better terminal program) Deconfiguring network interfaces... ------------[ cut here ]------------ WARNING: at kernel/softirq.c:143 local_bh_enable+0x40/0xb4() Modules linked in: [] (unwind_backtrace+0x0/0xec) from [] (warn_slowpath_common+0x4c/0x64) [] (warn_slowpath_common+0x4c/0x64) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null+0x1c/0x24) from [] (local_bh_enable+0x40/0xb4) [] (local_bh_enable+0x40/0xb4) from [] (__netif_receive_skb+0xf8/0x3d0) [] (__netif_receive_skb+0xf8/0x3d0) from [] (emac_rx_handler+0x40/0xcc) [] (emac_rx_handler+0x40/0xcc) from [] (__cpdma_chan_free+0xac/0xb0) [] (__cpdma_chan_free+0xac/0xb0) from [] (__cpdma_chan_process+0xe4/0x114) [] (__cpdma_chan_process+0xe4/0x114) from [] (cpdma_chan_stop+0xf0/0x1c8) [] (cpdma_chan_stop+0xf0/0x1c8) from [] (cpdma_ctlr_stop+0x80/0xe4) [] (cpdma_ctlr_stop+0x80/0xe4) from [] (emac_dev_stop+0xb0/0x13c) [] (emac_dev_stop+0xb0/0x13c) from [] (__dev_close+0x74/0x98) [] (__dev_close+0x74/0x98) from [] (__dev_change_flags+0xac/0x13c) [] (__dev_change_flags+0xac/0x13c) from [] (dev_change_flags+0x10/0x44) [] (dev_change_flags+0x10/0x44) from [] (devinet_ioctl+0x2dc/0x6f4) [] (devinet_ioctl+0x2dc/0x6f4) from [] (sock_ioctl+0x1fc/0x258) [] (sock_ioctl+0x1fc/0x258) from [] (do_vfs_ioctl+0x550/0x5c0) [] (do_vfs_ioctl+0x550/0x5c0) from [] (sys_ioctl+0x38/0x5c) [] (sys_ioctl+0x38/0x5c) from [] (ret_fast_syscall+0x0/0x2c) ---[ end trace 0e686330480db12e ]--- ------------[ cut here ]------------ WARNING: at drivers/net/davinci_emac.c:1025 __cpdma_chan_free+0xac/0xb0() Modules linked in: [] (unwind_backtrace+0x0/0xec) from [] (warn_slowpath_common+0x4c/0x64) [] (warn_slowpath_common+0x4c/0x64) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null+0x1c/0x24) from [] (__cpdma_chan_free+0xac/0xb0) [] (__cpdma_chan_free+0xac/0xb0) from [] (__cpdma_chan_process+0xe4/0x114) [] (__cpdma_chan_process+0xe4/0x114) from [] (cpdma_chan_stop+0xf0/0x1c8) [] (cpdma_chan_stop+0xf0/0x1c8) from [] (cpdma_ctlr_stop+0x80/0xe4) [] (cpdma_ctlr_stop+0x80/0xe4) from [] (emac_dev_stop+0xb0/0x13c) [] (emac_dev_stop+0xb0/0x13c) from [] (__dev_close+0x74/0x98) [] (__dev_close+0x74/0x98) from [] (__dev_change_flags+0xac/0x13c) [] (__dev_change_flags+0xac/0x13c) from [] (dev_change_flags+0x10/0x44) [] (dev_change_flags+0x10/0x44) from [] (devinet_ioctl+0x2dc/0x6f4) [] (devinet_ioctl+0x2dc/0x6f4) from [] (sock_ioctl+0x1fc/0x258) [] (sock_ioctl+0x1fc/0x258) from [] (do_vfs_ioctl+0x550/0x5c0) [] (do_vfs_ioctl+0x550/0x5c0) from [] (sys_ioctl+0x38/0x5c) [] (sys_ioctl+0x38/0x5c) from [] (ret_fast_syscall+0x0/0x2c) ---[ end trace 0e686330480db12f ]--- Thanks for the help. -Mike From michael.williamson at criticallink.com Thu Sep 9 16:45:44 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Thu, 09 Sep 2010 17:45:44 -0400 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C89507E.9040407@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <871v95f2xv.fsf@deeprootsystems.com> <4C86F369.6040906@criticallink.com> <4C880733.5010909@ti.com> <4C882EAA.9030903@criticallink.com> <4C892AC0.80409@criticallink.com> <4C893ADE.809@ti.com> <4C89507E.9040407@ti.com> Message-ID: <4C895588.3060500@criticallink.com> On 09/09/2010 05:24 PM, Cyril Chemparathy wrote: > Hi Mike, > > [...] >> An EMAC soft-reset clobbering the MDIO controller state is a >> possibility. I will poll TI designers to see if this could be the case. > > To test this theory out, I hacked up a crude > beat-it-to-death-and-see-if-it-breaks kinda patch (attached). This > tests 10000 mdio read cycles while constantly doing an emac soft-reset. > > I ran this on a dm365 evm, and the test didn't raise a single failed read: >> davinci_mdio davinci_mdio.0: davinci mdio revision 1.4 >> davinci_mdio davinci_mdio.0: detected phy mask fffffffc >> 10000 test loops completed, 10000 reads ok > > The failure in question seems to be limited to the da8xx family (tested > da830 evm), where: >> davinci_mdio davinci_mdio.0: davinci mdio revision 1.5 >> davinci_mdio davinci_mdio.0: detected phy mask fffffff1 >> idle triggered!! > > The MDIO module upgrade (rev 1.4 -> 1.5) could have something to do with > this behavior. Even so, I can't explain why this issue wasn't seen on > da8xx prior to this series. The original code should (at least in > theory) have sporadically locked up on emac open. > I think, if I understand it correctly, that in the previous version of this code, the emac was reset *prior* to enabling, scanning, and assigning the associated phy on the MDIO bus. The new implementation sets up and scans the MDIO bus first, then comes back around to the EMAC second... hits a reset, and doesn't re-ENABLE the MDIO. Also, maybe hitting the EMAC reset while the MDIO state machine is up is *bad*, I seem to recall some text in the user's guide about waiting for the state machine to stop before disabling it. I wonder if that also applies to reset? -Mike From hitesh.patel at einfochips.com Fri Sep 10 02:14:44 2010 From: hitesh.patel at einfochips.com (hitesh) Date: Fri, 10 Sep 2010 12:44:44 +0530 Subject: Chroma Conversion from IPIPE_YUV420SP to IPIPE_UYVY Message-ID: <4C89DAE4.9080608@einfochips.com> Hi All, I want to convert my H264 decoder output format YUV420SP to UYVY422 using IPIPE. But I am getting kernel error like *" rsz_validate_out_pix_formatspix format not supported"*. I debug in kernel so I found that kernel not supporting YUV420SP format as input of IPIPE module. Can you please tell what are the setting or procedure required to convert YUV420SP to UYVY422 format? Is there any patch available for above configuration? Thanks Hitesh -------------- next part -------------- An HTML attachment was scrubbed... URL: From arttak1586 at gmail.com Fri Sep 10 02:28:04 2010 From: arttak1586 at gmail.com (Arturo CV) Date: Fri, 10 Sep 2010 16:28:04 +0900 Subject: How to add a library (libusb) to the Toolchain for cross-compilation - DM6446 Message-ID: Hi all, My name is Arturo Corrales and I've been working with the DM6446 for signal processing, in which I use an USB device to gather the audio information that I need to work with, and so transfer all the information via USB communication to the Davinci DM6446. So far the USB device that I used for the information gathering works really well with the host PC, so I started adapting the USB driver so it can work in the Davinci DM6446 enviroment, and while doing this I found a problem while I tried to cross-compile an application that is needed to download the firmware to the USB Device. When I tried to do the cross-compilation of the application (C source code) it gives me this error: arm-linux-gnueabi-gcc -pipe -g fx2_programmer.c -lusb -o fx2_programmer fx2_programmer.c:4:17: error: usb.h: No such file or directory fx2_programmer.c: In function ?dump_busses?: fx2_programmer.c:34: error: ?usb_busses? undeclared (first use in this function) fx2_programmer.c:34: error: (Each undeclared identifier is reported only once fx2_programmer.c:34: error: for each function it appears in.) fx2_programmer.c:37: error: dereferencing pointer to incomplete type fx2_programmer.c:40: error: dereferencing pointer to incomplete type fx2_programmer.c:40: error: dereferencing pointer to incomplete type fx2_programmer.c:40: error: dereferencing pointer to incomplete type fx2_programmer.c:40: error: dereferencing pointer to incomplete type fx2_programmer.c:41: error: dereferencing pointer to incomplete type fx2_programmer.c:41: error: dereferencing pointer to incomplete type fx2_programmer.c:43: error: dereferencing pointer to incomplete type fx2_programmer.c:45: error: dereferencing pointer to incomplete type fx2_programmer.c: In function ?find_device?: fx2_programmer.c:54: error: ?usb_busses? undeclared (first use in this function) fx2_programmer.c:56: error: dereferencing pointer to incomplete type fx2_programmer.c:57: error: dereferencing pointer to incomplete type fx2_programmer.c:58: error: dereferencing pointer to incomplete type fx2_programmer.c:62: error: dereferencing pointer to incomplete type fx2_programmer.c:63: error: dereferencing pointer to incomplete type fx2_programmer.c:65: error: dereferencing pointer to incomplete type fx2_programmer.c: At top level: fx2_programmer.c:71: error: expected ?=?, ?,?, ?;?, ?asm? or ?__attribute__? before ?*? token fx2_programmer.c: In function ?dump_ram?: fx2_programmer.c:83: error: ?current_handle? undeclared (first use in this function) fx2_programmer.c: In function ?dump_bulkdata?: fx2_programmer.c:108: error: ?current_handle? undeclared (first use in this function) fx2_programmer.c: In function ?bench_bulk?: fx2_programmer.c:143: error: ?current_handle? undeclared (first use in this function) fx2_programmer.c: In function ?upload_ram?: fx2_programmer.c:177: error: ?current_handle? undeclared (first use in this function) fx2_programmer.c: In function ?main?: fx2_programmer.c:299: error: dereferencing pointer to incomplete type fx2_programmer.c:299: error: dereferencing pointer to incomplete type fx2_programmer.c:300: error: ?current_handle? undeclared (first use in this function) make: *** [fx2_programmer] Error 1 Looking around to find a solution of why it didn't cross-compile properly I found that the application uses the library "libusb", and this one is no part of the Toolchain of the cross-compiler, so I was wondering if someone can tell me How can I add this library into the toolchain so the cross-compiler can find the headers that are missing? In case that adding the library into the Toolchain is not the solution, then maybe someone can tell me how to accomplish to cross-compile the application so I can run it from the Davinci DM6446 enviroment. Thanks a lot for your answers and time, Arturo Corrales V. KIST - Robotics System Division CJS Team From amir.yung at gmail.com Wed Sep 1 07:07:22 2010 From: amir.yung at gmail.com (Amir Yungman) Date: Wed, 1 Sep 2010 15:07:22 +0300 Subject: XML parser for DM3xx Message-ID: <4c7e4148.d39ccc0a.1a3c.30b6@mx.google.com> Hi Does anyone know about XML parser for the DM3xx family? May be Tree-based parser, e.g. DOM or just Event-based parser. Amir -------------- next part -------------- An HTML attachment was scrubbed... URL: From dedekind1 at gmail.com Wed Sep 1 18:10:46 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Thu, 02 Sep 2010 02:10:46 +0300 Subject: UBI crashes / fixing NAND subpage writes In-Reply-To: <70E876B0EA86DD4BAF101844BC814DFE0903E02F56@Cloud.RL.local> References: <70E876B0EA86DD4BAF101844BC814DFE0903E02F56@Cloud.RL.local> Message-ID: <1283382646.2209.61.camel@brekeke> On Wed, 2010-09-01 at 08:40 +0100, Jon Povey wrote: > Of course this is not a very good solution. The right thing to do > would seem to be make nand_do_write_ops() properly subpage aware and > either add start and end offsets to the nand_write_page* family of > functions, or add a nand_write_subpage* family of functions. > > I don't mind having a go at some of this but am not confident to start > such major overhaul of nand_base.c without at least seeking comment > from others, so: This email. Maybe there's already something being > worked on? I think nand_write_subpage() is a good way do deal with this. If the chip does not define own nand_write_subpage(), we fall-back to the default one which uses the current way. -- Best Regards, Artem Bityutskiy (???????? ?????) From dedekind1 at gmail.com Wed Sep 1 18:14:58 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Thu, 02 Sep 2010 02:14:58 +0300 Subject: [RFC] nand/davinci: Fix comment to match the code In-Reply-To: <1282738700-30966-1-git-send-email-w.sang@pengutronix.de> References: <1282738700-30966-1-git-send-email-w.sang@pengutronix.de> Message-ID: <1283382898.2209.62.camel@brekeke> On Wed, 2010-08-25 at 14:18 +0200, Wolfram Sang wrote: > Signed-off-by: Wolfram Sang > Cc: Sudhakar Rajashekhara > Cc: Sneha Narnakaje > Cc: Artem Bityutskiy > --- > > Found while debugging a NAND issue with a dm365. Pushed to my l2-mtd-2.6.git / master, thanks. -- Best Regards, Artem Bityutskiy (???????? ?????) From Artem.Bityutskiy at nokia.com Tue Sep 7 03:00:51 2010 From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy) Date: Tue, 07 Sep 2010 11:00:51 +0300 Subject: [PATCH] nand/davinci: relax a timeout for ECC-initialization In-Reply-To: <1283510137-23573-1-git-send-email-w.sang@pengutronix.de> References: <1283382898.2209.62.camel@brekeke> <1283510137-23573-1-git-send-email-w.sang@pengutronix.de> Message-ID: <1283846451.2241.7.camel@localhost> On Fri, 2010-09-03 at 12:35 +0200, Wolfram Sang wrote: > Sudhakar found out that 100us are enough. Sadly, his updated patch was > overlooked and an older version still using 100ms was merged. Fix this. > > Reference: http://patchwork.ozlabs.org/patch/59180/ > > Signed-off-by: Wolfram Sang > Cc: Sudhakar Rajashekhara > Cc: Sneha Narnakaje > Cc: Artem Bityutskiy Pushed to l2-mtd-2.6.git, thanks. FYI, we prefix all MTD patches with "mtd:". -- Best Regards, Artem Bityutskiy (????? ????????) From martinwguy at gmail.com Wed Sep 1 06:41:12 2010 From: martinwguy at gmail.com (Martin Guy) Date: Wed, 1 Sep 2010 13:41:12 +0200 Subject: mmc over SPI on DM6467 based board. card not detected. In-Reply-To: References: <4C516634.5040804@criticallink.com> <877hjd106u.fsf@deeprootsystems.com> <4C7702EB.8040905@criticallink.com> <8762ywrvpt.fsf@deeprootsystems.com> <4C77E6BD.4000303@criticallink.com> <87fwy0orsg.fsf@deeprootsystems.com> Message-ID: On 8/30/10, Steve Chen wrote: > On Sat, Aug 28, 2010 at 8:26 AM, Sumesh Kaana wrote: > > I am trying to mount SD-Card over SPI on our custom DM6467 board. davinci > > spi controller driver and mmc over spi drver are selected in the menuconfig. > > i am using davinci-PSP.03-XX-00-37 kernel. > > > > I have also edited board initialization file to probe the MMC card under SPI > > as below: > > > > > > > > static struct spi_board_info dm646x_spi_info[] __initconst = { > > > > #ifdef CONFIG_MMC_SPI > > > > { > > > > .modalias = "mmc_spi", > > > > .max_speed_hz = (750 * 1000 ), /* max spi clock (SCK) > > speed in HZ */ > > > > .bus_num = 0, > > > > .chip_select = 0, /* CS0 */ > > > > .mode = SPI_MODE_0, > > > > }, > > > > #endif > > > > > > > > The kernel boots with following log > > > ... > > mmc0: Minimum clock frequency too high for identification mode > ... > > Have you tried lower the clock frequency? The initial card identification should be done at 400kHz. If that is successful, the following commands can be sent at your maximum rate. M From w.sang at pengutronix.de Wed Sep 1 03:05:23 2010 From: w.sang at pengutronix.de (Wolfram Sang) Date: Wed, 1 Sep 2010 10:05:23 +0200 Subject: [RFC] nand/davinci: Fix comment to match the code In-Reply-To: <045301cb44d3$2551fef0$6ff5fcd0$@raj@ti.com> References: <1282738700-30966-1-git-send-email-w.sang@pengutronix.de> <039d01cb4450$e8f7d6a0$bae783e0$@raj@ti.com> <1282740906.24044.210.camel@localhost> <045301cb44d3$2551fef0$6ff5fcd0$@raj@ti.com> Message-ID: <20100901080523.GC11407@pengutronix.de> > Yes, this was the patch I was talking about. But this patch seems little > different than the one I submitted to linux-mtd list at > http://patchwork.ozlabs.org/patch/59180/. But I can submit another patch > which corrects it. Ping. Any timeframe for this? -- Pengutronix e.K. | Wolfram Sang | Industrial Linux Solutions | http://www.pengutronix.de/ | -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 198 bytes Desc: Digital signature URL: From w.sang at pengutronix.de Fri Sep 3 05:35:37 2010 From: w.sang at pengutronix.de (Wolfram Sang) Date: Fri, 3 Sep 2010 12:35:37 +0200 Subject: [PATCH] nand/davinci: relax a timeout for ECC-initialization In-Reply-To: <1283382898.2209.62.camel@brekeke> References: <1283382898.2209.62.camel@brekeke> Message-ID: <1283510137-23573-1-git-send-email-w.sang@pengutronix.de> Sudhakar found out that 100us are enough. Sadly, his updated patch was overlooked and an older version still using 100ms was merged. Fix this. Reference: http://patchwork.ozlabs.org/patch/59180/ Signed-off-by: Wolfram Sang Cc: Sudhakar Rajashekhara Cc: Sneha Narnakaje Cc: Artem Bityutskiy --- Artem, if you pick up this one, too, then we have what Sudhakar sent as v3 of his original patch. Except for some minor rewording in the comment. Sudhakar, I hope it is okay if I send this patch now. I just want to have the confusion about the different versions gone. drivers/mtd/nand/davinci_nand.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 53f864a..1ad0eed 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -313,7 +313,7 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd, u32 syndrome[4]; u32 ecc_state; unsigned num_errors, corrected; - unsigned long timeo = jiffies + msecs_to_jiffies(100); + unsigned long timeo; /* All bytes 0xff? It's an erased page; ignore its ECC. */ for (i = 0; i < 10; i++) { @@ -373,6 +373,7 @@ compare: * long as ECC_STATE reads less than 4. After that, ECC HW has entered * correction state. */ + timeo = jiffies + usecs_to_jiffies(100); do { ecc_state = (davinci_nand_readl(info, NANDFSR_OFFSET) >> 8) & 0x0f; -- 1.7.1 From w.sang at pengutronix.de Fri Sep 3 07:15:38 2010 From: w.sang at pengutronix.de (Wolfram Sang) Date: Fri, 3 Sep 2010 14:15:38 +0200 Subject: [PATCH] nand/davinci: relax a timeout for ECC-initialization In-Reply-To: <030d01cb4b58$e18cafd0$a4a60f70$@raj@ti.com> References: <1283382898.2209.62.camel@brekeke> <1283510137-23573-1-git-send-email-w.sang@pengutronix.de> <030d01cb4b58$e18cafd0$a4a60f70$@raj@ti.com> Message-ID: <20100903121538.GB4813@pengutronix.de> Hi Sudhakar, > > Sudhakar, I hope it is okay if I send this patch now. I just want to have > > the confusion about the different versions gone. > > I was tied up for the past few days, so couldn't work on this patch. Thanks > for taking this up. Can you modify the comment also to match my patch and > re-submit this again? Honestly, I think the comments are similar enough, why another change? Regards, Wolfram -- Pengutronix e.K. | Wolfram Sang | Industrial Linux Solutions | http://www.pengutronix.de/ | -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 198 bytes Desc: Digital signature URL: From zhan5425 at 163.com Sun Sep 5 21:16:54 2010 From: zhan5425 at 163.com (=?gbk?B?1bKzyb2t?=) Date: Mon, 6 Sep 2010 10:16:54 +0800 (CST) Subject: when use linuxinput keyboard,ttyS2 console can't be used on OMAPl137_da8xx Message-ID: <1bc23e0.836f.12ae4d4f167.Coremail.zhan5425@163.com> hi, I have a OMAPL137 board,Now I have a problem that I want to use linux input subsystem,linuxinput Keyboard in qt4 for instance, but when I use gpio of omapl137 to register a input device driver,There is a device file found in /dev/input/event0 ,so I set the envionment variables to post the keyboard linuxinput:/dev/input/event0,The keyboard can be pressed and send the event to linux kernel,qt4 can recive the event,and the same time i can't input anything in the console,I don't know why. Thanks very much!! -------------- next part -------------- An HTML attachment was scrubbed... URL: From vm.rod25 at gmail.com Fri Sep 10 09:12:23 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Fri, 10 Sep 2010 09:12:23 -0500 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <87iq2g3z8s.fsf@deeprootsystems.com> References: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> <871v949qqw.fsf@deeprootsystems.com> <87iq2g3z8s.fsf@deeprootsystems.com> Message-ID: On Wed, Sep 8, 2010 at 12:45 PM, Kevin Hilman wrote: > Victor Rodriguez writes: > >> On Wed, Sep 8, 2010 at 10:52 AM, Kevin Hilman >> wrote: >>> Victor Rodriguez writes: >>> >>>>>> +static __init void omapl138_hawk_init(void) >>>>>> +{ >>>>>> + ? ? int ret; >>>>>> + >>>>>> + ? ? davinci_serial_init(&omapl138_hawk_uart_config); >>>>>> + >>>>>> + ? ? /*shut down uart 1; It is not implemented in hardware */ >>>>> >>>>> Should be: /* Shut down ... >>>>> >>>>> I thought there was going to be a note here as to >>>>> why we register UART1, but choose to shut it down? >>>> >>>> The UART1 is not present in the board, we are registering first the >>>> UART0,1 and 2 and then just shut down UART1 because it is not present >>>> in hardware. But what do you suggest. >>> >>> "not implemented in hardware" is not a good enough description, nor is >>> it actually true. >>> >>> IIUC, the issue is that the *pins* used for UART1 are hooked up to other >>> peripherals on the board. ?IOW, UART1 is not *connected* on the board, >>> and due to pin mux conflicts, enabling UART1 will lead to spurious >>> interrupts. >>> >>> A summary of this problem is what needs to accompany the line that shuts >>> down UART1. >>> >>> Victor, I know you inherited this problem from the EVM board file, but >>> it needs to be fixed in both places. ?Maybe you and Sekhar can come up >>> with the right wording for the EVM file, and you can propose a patch for >>> each board file. >>> >>> Thanks, >>> >>> Kevin >>> >> >> HI >> >> Is this paragraph better ? > > It's better except for it doesn't follow the multi-line comment style. :) > (search for 'muti-line' in Documentation/CodingStyle for details) > >> ? ? ? /* >> ? ? ? Shut down UART 1; It shares pins with >> ? ? ? McASP0 transmit/receive master clock. >> ? ? ? Enable it will produce fake interrupts >> ? ? ? */ > > s/fake/spurious/. > > Also, I would like to see this described in terms of how the board is > wired. ?IOW, reading this comment, you might assume you could use UART1 > if you're not using McASP0. ?However, IIUC, you cannot because the board > has been wired such that UART1 is not not connected at all. > >> ? ? ? __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >> >> I will keep in touch with Sekhar to fix this problem. but is there any >> thing else to modify to the hawk board patch? > > Nothing else that I saw, but Sekhar had several comments that need to be > addressed. > > Thanks, > > Kevin > > I Kevin I have changed all the comments, patch V6 is ready for comments, hoping it could be fine and aproved and commited for next rc. Sincerely yours Victor Rodriguez From vm.rod25 at gmail.com Fri Sep 10 09:12:23 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Fri, 10 Sep 2010 09:12:23 -0500 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <87iq2g3z8s.fsf@deeprootsystems.com> References: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> <871v949qqw.fsf@deeprootsystems.com> <87iq2g3z8s.fsf@deeprootsystems.com> Message-ID: On Wed, Sep 8, 2010 at 12:45 PM, Kevin Hilman wrote: > Victor Rodriguez writes: > >> On Wed, Sep 8, 2010 at 10:52 AM, Kevin Hilman >> wrote: >>> Victor Rodriguez writes: >>> >>>>>> +static __init void omapl138_hawk_init(void) >>>>>> +{ >>>>>> + ? ? int ret; >>>>>> + >>>>>> + ? ? davinci_serial_init(&omapl138_hawk_uart_config); >>>>>> + >>>>>> + ? ? /*shut down uart 1; It is not implemented in hardware */ >>>>> >>>>> Should be: /* Shut down ... >>>>> >>>>> I thought there was going to be a note here as to >>>>> why we register UART1, but choose to shut it down? >>>> >>>> The UART1 is not present in the board, we are registering first the >>>> UART0,1 and 2 and then just shut down UART1 because it is not present >>>> in hardware. But what do you suggest. >>> >>> "not implemented in hardware" is not a good enough description, nor is >>> it actually true. >>> >>> IIUC, the issue is that the *pins* used for UART1 are hooked up to other >>> peripherals on the board. ?IOW, UART1 is not *connected* on the board, >>> and due to pin mux conflicts, enabling UART1 will lead to spurious >>> interrupts. >>> >>> A summary of this problem is what needs to accompany the line that shuts >>> down UART1. >>> >>> Victor, I know you inherited this problem from the EVM board file, but >>> it needs to be fixed in both places. ?Maybe you and Sekhar can come up >>> with the right wording for the EVM file, and you can propose a patch for >>> each board file. >>> >>> Thanks, >>> >>> Kevin >>> >> >> HI >> >> Is this paragraph better ? > > It's better except for it doesn't follow the multi-line comment style. :) > (search for 'muti-line' in Documentation/CodingStyle for details) > >> ? ? ? /* >> ? ? ? Shut down UART 1; It shares pins with >> ? ? ? McASP0 transmit/receive master clock. >> ? ? ? Enable it will produce fake interrupts >> ? ? ? */ > > s/fake/spurious/. > > Also, I would like to see this described in terms of how the board is > wired. ?IOW, reading this comment, you might assume you could use UART1 > if you're not using McASP0. ?However, IIUC, you cannot because the board > has been wired such that UART1 is not not connected at all. > >> ? ? ? __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >> >> I will keep in touch with Sekhar to fix this problem. but is there any >> thing else to modify to the hawk board patch? > > Nothing else that I saw, but Sekhar had several comments that need to be > addressed. > > Thanks, > > Kevin > > I Kevin I have changed all the comments, patch V6 is ready for comments, hoping it could be fine and aproved and commited for next rc. Sincerely yours Victor Rodriguez From vm.rod25 at gmail.com Fri Sep 10 09:12:23 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Fri, 10 Sep 2010 09:12:23 -0500 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <87iq2g3z8s.fsf@deeprootsystems.com> References: <1283889724-6878-1-git-send-email-vm.rod25@gmail.com> <871v949qqw.fsf@deeprootsystems.com> <87iq2g3z8s.fsf@deeprootsystems.com> Message-ID: On Wed, Sep 8, 2010 at 12:45 PM, Kevin Hilman wrote: > Victor Rodriguez writes: > >> On Wed, Sep 8, 2010 at 10:52 AM, Kevin Hilman >> wrote: >>> Victor Rodriguez writes: >>> >>>>>> +static __init void omapl138_hawk_init(void) >>>>>> +{ >>>>>> + ? ? int ret; >>>>>> + >>>>>> + ? ? davinci_serial_init(&omapl138_hawk_uart_config); >>>>>> + >>>>>> + ? ? /*shut down uart 1; It is not implemented in hardware */ >>>>> >>>>> Should be: /* Shut down ... >>>>> >>>>> I thought there was going to be a note here as to >>>>> why we register UART1, but choose to shut it down? >>>> >>>> The UART1 is not present in the board, we are registering first the >>>> UART0,1 and 2 and then just shut down UART1 because it is not present >>>> in hardware. But what do you suggest. >>> >>> "not implemented in hardware" is not a good enough description, nor is >>> it actually true. >>> >>> IIUC, the issue is that the *pins* used for UART1 are hooked up to other >>> peripherals on the board. ?IOW, UART1 is not *connected* on the board, >>> and due to pin mux conflicts, enabling UART1 will lead to spurious >>> interrupts. >>> >>> A summary of this problem is what needs to accompany the line that shuts >>> down UART1. >>> >>> Victor, I know you inherited this problem from the EVM board file, but >>> it needs to be fixed in both places. ?Maybe you and Sekhar can come up >>> with the right wording for the EVM file, and you can propose a patch for >>> each board file. >>> >>> Thanks, >>> >>> Kevin >>> >> >> HI >> >> Is this paragraph better ? > > It's better except for it doesn't follow the multi-line comment style. :) > (search for 'muti-line' in Documentation/CodingStyle for details) > >> ? ? ? /* >> ? ? ? Shut down UART 1; It shares pins with >> ? ? ? McASP0 transmit/receive master clock. >> ? ? ? Enable it will produce fake interrupts >> ? ? ? */ > > s/fake/spurious/. > > Also, I would like to see this described in terms of how the board is > wired. ?IOW, reading this comment, you might assume you could use UART1 > if you're not using McASP0. ?However, IIUC, you cannot because the board > has been wired such that UART1 is not not connected at all. > >> ? ? ? __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); >> >> I will keep in touch with Sekhar to fix this problem. but is there any >> thing else to modify to the hawk board patch? > > Nothing else that I saw, but Sekhar had several comments that need to be > addressed. > > Thanks, > > Kevin > > I Kevin I have changed all the comments, patch V6 is ready for comments, hoping it could be fine and aproved and commited for next rc. Sincerely yours Victor Rodriguez From caglarakyuz at gmail.com Fri Sep 10 10:23:52 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Fri, 10 Sep 2010 18:23:52 +0300 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C8950D4.9060102@criticallink.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <4C893ADE.809@ti.com> <4C8950D4.9060102@criticallink.com> Message-ID: <201009101823.52755.caglarakyuz@gmail.com> On Friday 10 September 2010 12:25:40 am Michael Williamson wrote: > Hi Cyril, > > On 09/09/2010 03:51 PM, Cyril Chemparathy wrote: > > Hi Mike, > > > > [...] > > > >> The hang is in wait_for_user_access() in the davinci_mdio_read() call. > >> Looks like the state machine got put back into IDLE somewhere between > >> the MDIO probe and the EMAC probe. Seems like there should be some sort > >> of time-out and error message in the wait_for_user_access() method.... > >> (maybe even a check for IDLE??) > >> > >> If I add a patch to check the state machine for IDLE and then re-enable > >> it in the davinci_mdio_read() call, it is able to press on and come up. > >> I don't see any calls to the davinci_mdio_suspend() call, so I am > >> wondering if the EMAC probe routine, particularly the application of the > >> SOFTRESET, is causing the MDIO to drop back to IDLE / disabled. > >> > >> I can post the patch if you like, but it is a bit of a hack... > > > > An EMAC soft-reset clobbering the MDIO controller state is a > > possibility. I will poll TI designers to see if this could be the case. > > > > In any case, a couple of unanswered questions remain: > > > > 1. Why don't other davinci devices display similar behavior? > > > > 2. If the answer to #1 above is that the timing window is pretty slim > > (i.e., only if an MDIO read/write is in progress during EMAC > > soft-reset), why do we hit this situation consistently on > > mityomap? > > Has it been confirmed that this only happens on mityomap? Has anyone had > success using a da850 evm or other da850 platform? The configuration for Same problem exists on another DA850 board, Hawkboard.(Sorry no support in mainline yet) > the mityomap, wrt to the EMAC/MII/MDIO, is pretty much identical to the > da850 evm using the MII interface. The only difference I am aware of is > the assigned address to the PHY chip. The reference clocks and rates are > identical, AFAIK, to the evm. > > > I have put together a quick patch (tested dm365). See attached. > > Your patch doesn't work with my board. It does attempt to reset the bus on This patch fixes the problem here. I'm using kernel IP auto configuration and mounting fs over NFS. My system boots and I can login to my board. Regards, Caglar > the read call, but following wait_for_user_access() calls are timing out > and the _read() and _write() calls punt. I bumped up the MDIO_TIMEOUT to > 100 ms, and it works. I'm wondering if the scanning logic has to complete > an entire cycle (all 32 phys) before issuing a request, and if it's a lot > slower than expected. > > I also found that the initial scanning logic would not reliably find the > PHY until I bumped up the delay time following the reset operation. > Sometimes it would, sometimes no. > > Also, your while(1) loops with the continue conditions on the second > wait_for_user_access() in the read and writes might need some > consideration, i.e.: > > while (1) { > ret = wait_for_user_access(data); > if (ret == -EAGAIN) > continue; > if (ret < 0) > break; > > __raw_writel(reg, &data->regs->user[0].access); > > ret = wait_for_user_access(data); > if (ret == -EAGAIN) > continue; > ^^^^^^^^^ <--- this will re-issue the request.... > what you want? if (ret < 0) > break; > > reg = __raw_readl(&data->regs->user[0].access); > ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : > -EIO; break; > } > > Also, on the shutdown, I get a major kernel trace. Here is the dump, as > much as I could catch of it.... (I need a better terminal program) > > Deconfiguring network interfaces... ------------[ cut here ]------------ > WARNING: at kernel/softirq.c:143 local_bh_enable+0x40/0xb4() > Modules linked in: > [] (unwind_backtrace+0x0/0xec) from [] > (warn_slowpath_common+0x4c/0x64) [] > (warn_slowpath_common+0x4c/0x64) from [] > (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null+0x1c/0x24) > from [] (local_bh_enable+0x40/0xb4) [] > (local_bh_enable+0x40/0xb4) from [] > (__netif_receive_skb+0xf8/0x3d0) [] > (__netif_receive_skb+0xf8/0x3d0) from [] > (emac_rx_handler+0x40/0xcc) [] (emac_rx_handler+0x40/0xcc) from > [] (__cpdma_chan_free+0xac/0xb0) [] > (__cpdma_chan_free+0xac/0xb0) from [] > (__cpdma_chan_process+0xe4/0x114) [] > (__cpdma_chan_process+0xe4/0x114) from [] > (cpdma_chan_stop+0xf0/0x1c8) [] (cpdma_chan_stop+0xf0/0x1c8) > from [] (cpdma_ctlr_stop+0x80/0xe4) [] > (cpdma_ctlr_stop+0x80/0xe4) from [] (emac_dev_stop+0xb0/0x13c) > [] (emac_dev_stop+0xb0/0x13c) from [] > (__dev_close+0x74/0x98) [] (__dev_close+0x74/0x98) from > [] (__dev_change_flags+0xac/0x13c) [] > (__dev_change_flags+0xac/0x13c) from [] > (dev_change_flags+0x10/0x44) [] (dev_change_flags+0x10/0x44) > from [] (devinet_ioctl+0x2dc/0x6f4) [] > (devinet_ioctl+0x2dc/0x6f4) from [] (sock_ioctl+0x1fc/0x258) > [] (sock_ioctl+0x1fc/0x258) from [] > (do_vfs_ioctl+0x550/0x5c0) [] (do_vfs_ioctl+0x550/0x5c0) from > [] (sys_ioctl+0x38/0x5c) [] (sys_ioctl+0x38/0x5c) from > [] (ret_fast_syscall+0x0/0x2c) ---[ end trace 0e686330480db12e > ]--- > ------------[ cut here ]------------ > WARNING: at drivers/net/davinci_emac.c:1025 __cpdma_chan_free+0xac/0xb0() > Modules linked in: > [] (unwind_backtrace+0x0/0xec) from [] > (warn_slowpath_common+0x4c/0x64) [] > (warn_slowpath_common+0x4c/0x64) from [] > (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null+0x1c/0x24) > from [] (__cpdma_chan_free+0xac/0xb0) [] > (__cpdma_chan_free+0xac/0xb0) from [] > (__cpdma_chan_process+0xe4/0x114) [] > (__cpdma_chan_process+0xe4/0x114) from [] > (cpdma_chan_stop+0xf0/0x1c8) [] (cpdma_chan_stop+0xf0/0x1c8) > from [] (cpdma_ctlr_stop+0x80/0xe4) [] > (cpdma_ctlr_stop+0x80/0xe4) from [] (emac_dev_stop+0xb0/0x13c) > [] (emac_dev_stop+0xb0/0x13c) from [] > (__dev_close+0x74/0x98) [] (__dev_close+0x74/0x98) from > [] (__dev_change_flags+0xac/0x13c) [] > (__dev_change_flags+0xac/0x13c) from [] > (dev_change_flags+0x10/0x44) [] (dev_change_flags+0x10/0x44) > from [] (devinet_ioctl+0x2dc/0x6f4) [] > (devinet_ioctl+0x2dc/0x6f4) from [] (sock_ioctl+0x1fc/0x258) > [] (sock_ioctl+0x1fc/0x258) from [] > (do_vfs_ioctl+0x550/0x5c0) [] (do_vfs_ioctl+0x550/0x5c0) from > [] (sys_ioctl+0x38/0x5c) [] (sys_ioctl+0x38/0x5c) from > [] (ret_fast_syscall+0x0/0x2c) ---[ end trace 0e686330480db12f > ]--- > > > Thanks for the help. > > -Mike > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo at vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > From caglarakyuz at gmail.com Fri Sep 10 11:34:08 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Fri, 10 Sep 2010 19:34:08 +0300 Subject: [PATCH v4 1/2] davinci: Add generic PWM support for PWM control In-Reply-To: <1284028849-16680-1-git-send-email-sugumar@ti.com> References: <1284028849-16680-1-git-send-email-sugumar@ti.com> Message-ID: <201009101934.08045.caglarakyuz@gmail.com> On Thursday 09 September 2010 01:40:49 pm Sugumar Natarajan wrote: > This patch adds generic PWM support where it maintains the > list of PWM control devices that can be added or removed. > > The interface provides a list of functions that can be accessed > by the PWM control driver module and the generic PWM driver. > > The PWM control driver module such as eCAP uses the interface to > register and add itself to the list as a PWM control device. > The generic PWM driver uses the interface to search for a PWM control > device and if present, uses the device for PWM control. > How does real pwm modules fit in this architecture? For instance L-138 have eHRPWM modules for PWM generation. * Should we add a seperate file for eHRPWM module? or * Should we integrate it in davinci_pwm file? Best Regards, Caglar > Signed-off-by: Sugumar Natarajan > --- > Changes since v2: > a) pwm_config_device callback is made more flexible. > b) pwm_request function code has been made more cleaner. > c) Sanity-check/warn has been included. > > arch/arm/mach-davinci/Makefile | 3 + > arch/arm/mach-davinci/davinci_pwm.c | 130 > ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | > 32 ++++++ > 3 files changed, 165 insertions(+), 0 deletions(-) > create mode 100644 arch/arm/mach-davinci/davinci_pwm.c > create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h > > diff --git a/arch/arm/mach-davinci/Makefile > b/arch/arm/mach-davinci/Makefile index a7a70d1..90ca821 100644 > --- a/arch/arm/mach-davinci/Makefile > +++ b/arch/arm/mach-davinci/Makefile > @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o > obj-$(CONFIG_CPU_FREQ) += cpufreq.o > obj-$(CONFIG_CPU_IDLE) += cpuidle.o > obj-$(CONFIG_SUSPEND) += pm.o sleep.o > + > +# Generic PWM control support > +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o > diff --git a/arch/arm/mach-davinci/davinci_pwm.c > b/arch/arm/mach-davinci/davinci_pwm.c new file mode 100644 > index 0000000..c2b8b9a > --- /dev/null > +++ b/arch/arm/mach-davinci/davinci_pwm.c > @@ -0,0 +1,130 @@ > +/* > + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed .as is. WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) > +{ > + unsigned int clock_freq; > + unsigned int period_cycles; > + unsigned int duty_cycle; > + int ret = 0; > + > + if (WARN_ON(!pwm)) > + return -EINVAL; > + > + if (pwm->pwm_config_device) { > + if (!period_ns || duty_ns > period_ns) > + return -EINVAL; > + > + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; > + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; > + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; > + ret = pwm->pwm_config_device(pwm, period_cycles, duty_cycle); > + } > + > + return ret; > +} > +EXPORT_SYMBOL(pwm_config); > + > +int pwm_enable(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return -EINVAL; > + > + return clk_enable(pwm->clk); > +} > +EXPORT_SYMBOL(pwm_enable); > + > +void pwm_disable(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return; > + > + clk_disable(pwm->clk); > +} > +EXPORT_SYMBOL(pwm_disable); > + > +static DEFINE_MUTEX(pwm_lock); > +static LIST_HEAD(pwm_list); > + > +struct pwm_device *pwm_request(int pwm_id, const char *label) > +{ > + struct pwm_device *pwm, *tmp_pwm = ERR_PTR(-ENOENT); > + > + mutex_lock(&pwm_lock); > + > + list_for_each_entry(pwm, &pwm_list, node) { > + if (pwm->pwm_id == pwm_id) { > + if (pwm->use_count == 0) { > + pwm->use_count++; > + pwm->label = label; > + } else { > + pwm = ERR_PTR(-EBUSY); > + } > + tmp_pwm = pwm; > + break; > + } > + } > + > + mutex_unlock(&pwm_lock); > + return tmp_pwm; > +} > +EXPORT_SYMBOL(pwm_request); > + > +void pwm_free(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return; > + > + mutex_lock(&pwm_lock); > + > + if (pwm->use_count) { > + pwm->use_count--; > + pwm->label = NULL; > + } else { > + dev_warn(&pwm->pdev->dev, "PWM device already freed\n"); > + } > + > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(pwm_free); > + > +void pwm_add(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return; > + > + mutex_lock(&pwm_lock); > + list_add_tail(&pwm->node, &pwm_list); > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(pwm_add); > + > +void pwm_remove(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return; > + > + mutex_lock(&pwm_lock); > + list_del(&pwm->node); > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(pwm_remove); > diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h > b/arch/arm/mach-davinci/include/mach/davinci_pwm.h new file mode 100644 > index 0000000..3b7a3c8 > --- /dev/null > +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h > @@ -0,0 +1,32 @@ > +/* > + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed .as is. WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + */ > + > +#ifndef __DAVINCI_PWM_H > +#define __DAVINCI_PWM_H > + > +struct pwm_device { > + struct list_head node; > + struct platform_device *pdev; > + int (*pwm_config_device)(struct pwm_device *pwm, > + unsigned int period, unsigned int dutycycle); > + const char *label; > + struct clk *clk; > + unsigned int use_count; > + unsigned int pwm_id; > +}; > + > +void pwm_add(struct pwm_device *pwm); > +void pwm_remove(struct pwm_device *pwm); > + > +#endif > From caglarakyuz at gmail.com Fri Sep 10 12:42:36 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Fri, 10 Sep 2010 20:42:36 +0300 Subject: [PATCH v4 1/2] davinci: Add generic PWM support for PWM control In-Reply-To: <1284028849-16680-1-git-send-email-sugumar@ti.com> References: <1284028849-16680-1-git-send-email-sugumar@ti.com> Message-ID: <201009102042.36977.caglarakyuz@gmail.com> On Thursday 09 September 2010 01:40:49 pm Sugumar Natarajan wrote: > This patch adds generic PWM support where it maintains the > list of PWM control devices that can be added or removed. > > The interface provides a list of functions that can be accessed > by the PWM control driver module and the generic PWM driver. > > The PWM control driver module such as eCAP uses the interface to > register and add itself to the list as a PWM control device. > The generic PWM driver uses the interface to search for a PWM control > device and if present, uses the device for PWM control. > > Signed-off-by: Sugumar Natarajan > --- Hi, [...] > + > +int pwm_enable(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return -EINVAL; > + > + return clk_enable(pwm->clk); > +} > +EXPORT_SYMBOL(pwm_enable); > + I think 'clk_enable' should be controlled for un-matched pwm_enable/disable operation. Otherwise, disabling PWM won't shut down peripheral clock. If I understand inner workings of DaVinci clock implementation clock use_count is incremented with every clk_enable. Regards, Caglar From cyril at ti.com Fri Sep 10 17:59:38 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Fri, 10 Sep 2010 18:59:38 -0400 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C8950D4.9060102@criticallink.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <871v95f2xv.fsf@deeprootsystems.com> <4C86F369.6040906@criticallink.com> <4C880733.5010909@ti.com> <4C882EAA.9030903@criticallink.com> <4C892AC0.80409@criticallink.com> <4C893ADE.809@ti.com> <4C8950D4.9060102@criticallink.com> Message-ID: <4C8AB85A.8060909@ti.com> Hi Mike, I have merged your latest two emails and responded to both here. [...] > Your patch doesn't work with my board. It does attempt to reset the bus on the read call, > but following wait_for_user_access() calls are timing out and the _read() and _write() calls punt. > I bumped up the MDIO_TIMEOUT to 100 ms, and it works. I'm wondering if the scanning logic > has to complete an entire cycle (all 32 phys) before issuing a request, and if it's a lot > slower than expected. Based on the mdio module's state machine code, the scan does not need to complete before a user-request is issued. However, when the module is first enabled, it _must_ poll at least one phy (phy id 0) before it handles the user-access request. Consequently, the first access after coming out of reset may be slower than subsequent accesses. One of the patches posted on my repo [1] replaces the dumb mdelay() with a bit more logic that calculates the worst-case access time. This mechanism may work a lot better for you. Would you mind trying it out? Since the MDIO_TIMEOUT is simply a defensive measure, I have no objections to raising this timeout (included in the updated stack). > I also found that the initial scanning logic would not reliably find the PHY until I bumped > up the delay time following the reset operation. Sometimes it would, sometimes no. > > Also, your while(1) loops with the continue conditions on the second wait_for_user_access() > in the read and writes might need some consideration, i.e.: > > while (1) { > ret = wait_for_user_access(data); > if (ret == -EAGAIN) > continue; > if (ret < 0) > break; > > __raw_writel(reg, &data->regs->user[0].access); > > ret = wait_for_user_access(data); > if (ret == -EAGAIN) > continue; > ^^^^^^^^^ <--- this will re-issue the request.... what you want? Yes, the wait_for_user_access() would have reset the controller, throwing the current transaction out. The intent here is to restart the current transaction with a newly initialized controller. > if (ret < 0) > break; > > reg = __raw_readl(&data->regs->user[0].access); > ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO; > break; > } > > Also, on the shutdown, I get a major kernel trace. Here is the dump, as much > as I could catch of it.... (I need a better terminal program) [...] > WARNING: at drivers/net/davinci_emac.c:1025 __cpdma_chan_free+0xac/0xb0() The current code spits out a huge volume of stuff as a result of a WARN_ON in the rx handler. The gitweb on [1] has a patch that fixes this. [...] >> > The MDIO module upgrade (rev 1.4 -> 1.5) could have something to do with >> > this behavior. Even so, I can't explain why this issue wasn't seen on >> > da8xx prior to this series. The original code should (at least in >> > theory) have sporadically locked up on emac open. >> > > I think, if I understand it correctly, that in the previous version of > this code, the emac was reset *prior* to enabling, scanning, and assigning > the associated phy on the MDIO bus. The new implementation sets up and scans > the MDIO bus first, then comes back around to the EMAC second... hits a reset, > and doesn't re-ENABLE the MDIO. AFAICS, that isn't entirely accurate. In the previous version, the mdio bus was being brought up at probe time in davinci_emac_probe(). The soft-reset was happening later on when the device is opened, in emac_hw_enable(). The difference, however, is that the original code forced an emac_mii_reset() immediately after the emac_hw_enable(). This is not being done with the separated mdio, and that is the problem. In terms of behavior, with the current work around, the new and old versions should be close to identical. More below... > Also, maybe hitting the EMAC reset while the MDIO state machine is up is *bad*, I > seem to recall some text in the user's guide about waiting for the state > machine to stop before disabling it. I wonder if that also applies to reset? You are correct. EMAC soft-reset stops the MDIO mid-transaction, quite unlike disabling the module via the control register. Therefore, there is a risk that a badly designed phy could be left hanging in an arbitrary state. However, all earlier versions of the emac code have been exposed to this very same vulnerability (i.e. arbitrary emac soft-reset regardless of mdio state) all along. Regards Cyril. [1] http://arago-project.org/git/people/?p=cyril/linux-tnetv107x.git;a=shortlog;h=refs/heads/emac-cpdma-mdio-fixes From caglarakyuz at gmail.com Sat Sep 11 03:54:41 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Sat, 11 Sep 2010 11:54:41 +0300 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <201009101823.52755.caglarakyuz@gmail.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <4C8950D4.9060102@criticallink.com> <201009101823.52755.caglarakyuz@gmail.com> Message-ID: <201009111154.42171.caglarakyuz@gmail.com> On Friday 10 September 2010 06:23:52 pm Caglar Akyuz wrote: > On Friday 10 September 2010 12:25:40 am Michael Williamson wrote: > > Hi Cyril, > > > > On 09/09/2010 03:51 PM, Cyril Chemparathy wrote: > > > Hi Mike, > > > > > > [...] > > > > > >> The hang is in wait_for_user_access() in the davinci_mdio_read() call. > > >> Looks like the state machine got put back into IDLE somewhere between > > >> the MDIO probe and the EMAC probe. Seems like there should be some > > >> sort of time-out and error message in the wait_for_user_access() > > >> method.... (maybe even a check for IDLE??) > > >> > > >> If I add a patch to check the state machine for IDLE and then > > >> re-enable it in the davinci_mdio_read() call, it is able to press on > > >> and come up. I don't see any calls to the davinci_mdio_suspend() call, > > >> so I am wondering if the EMAC probe routine, particularly the > > >> application of the SOFTRESET, is causing the MDIO to drop back to IDLE > > >> / disabled. > > >> > > >> I can post the patch if you like, but it is a bit of a hack... > > > > > > An EMAC soft-reset clobbering the MDIO controller state is a > > > possibility. I will poll TI designers to see if this could be the > > > case. > > > > > > In any case, a couple of unanswered questions remain: > > > > > > 1. Why don't other davinci devices display similar behavior? > > > > > > 2. If the answer to #1 above is that the timing window is pretty slim > > > (i.e., only if an MDIO read/write is in progress during EMAC > > > soft-reset), why do we hit this situation consistently on > > > mityomap? > > > > Has it been confirmed that this only happens on mityomap? Has anyone had > > success using a da850 evm or other da850 platform? The configuration > > for > > Same problem exists on another DA850 board, Hawkboard.(Sorry no support in > mainline yet) > > > the mityomap, wrt to the EMAC/MII/MDIO, is pretty much identical to the > > da850 evm using the MII interface. The only difference I am aware of is > > the assigned address to the PHY chip. The reference clocks and rates > > are identical, AFAIK, to the evm. > > > > > I have put together a quick patch (tested dm365). See attached. > > > > Your patch doesn't work with my board. It does attempt to reset the bus > > on > > This patch fixes the problem here. I'm using kernel IP auto configuration > and mounting fs over NFS. My system boots and I can login to my board. > > Regards, > Caglar > Unfortunately emac driver is not stable after this series. I face lock-ups time to time, followed by attached kernel trace. Regards, Caglar _________________________________________________________________ [ 1651.440000] nfs: server 192.168.2.34 not responding, still trying [ 1859.010000] ------------[ cut here ]------------ [ 1859.010000] WARNING: at net/sched/sch_generic.c:258 dev_watchdog+0x184/0x294() [ 1859.020000] NETDEV WATCHDOG: eth0 (davinci_emac): transmit queue 0 timed out [ 1859.020000] Modules linked in: [ 1859.030000] Backtrace: [ 1859.030000] [] (dump_backtrace+0x0/0x10c) from [] (dump_stack+0x18/0x1c) [ 1859.040000] r7:c03b5de8 r6:c025a13c r5:c039045c r4:00000102 [ 1859.040000] [] (dump_stack+0x0/0x1c) from [] (warn_slowpath_common+0x58/0x70) [ 1859.050000] [] (warn_slowpath_common+0x0/0x70) from [] (warn_slowpath_fmt+0x38/0x40) [ 1859.060000] r8:c03b4000 r7:00000030 r6:c0437564 r5:c7bbc000 r4:00000000 [ 1859.070000] [] (warn_slowpath_fmt+0x0/0x40) from [] (dev_watchdog+0x184/0x294) [ 1859.080000] r3:c7bbc000 r2:c0390474 [ 1859.080000] [] (dev_watchdog+0x0/0x294) from [] (run_timer_softirq+0x1c4/0x29c) [ 1859.090000] [] (run_timer_softirq+0x0/0x29c) from [] (__do_softirq+0x98/0x12c) [ 1859.100000] [] (__do_softirq+0x0/0x12c) from [] (irq_exit+0x48/0x9c) [ 1859.110000] [] (irq_exit+0x0/0x9c) from [] (asm_do_IRQ+0x80/0xa0) [ 1859.120000] [] (asm_do_IRQ+0x0/0xa0) from [] (__irq_svc+0x4c/0x9c) [ 1859.120000] Exception stack(0xc03b5f38 to 0xc03b5f80) [ 1859.130000] 5f20: 00000000 0005317f [ 1859.140000] 5f40: 0005217f 60000013 c03b4000 c03b8ba0 c03b89d4 c03dcc50 c0023e04 41069265 [ 1859.150000] 5f60: c0023d94 c03b5f8c 600000d3 c03b5f80 c002da6c c002da78 60000013 ffffffff [ 1859.150000] r5:febfd000 r4:ffffffff [ 1859.160000] [] (default_idle+0x0/0x34) from [] (cpu_idle+0x74/0xdc) [ 1859.170000] [] (cpu_idle+0x0/0xdc) from [] (rest_init+0xa4/0xbc) [ 1859.170000] r7:c03b89c8 r6:c0026018 r5:c03dcc1c r4:00000002 [ 1859.180000] [] (rest_init+0x0/0xbc) from [] (start_kernel+0x270/0x2d0) [ 1859.190000] r4:c042d70c [ 1859.190000] [] (start_kernel+0x0/0x2d0) from [] (__enable_mmu+0x0/0x2c) [ 1859.200000] r6:c002641c r5:c03dcc78 r4:00053175 [ 1859.200000] ---[ end trace d278f645c502dc20 ]--- From lamiaposta71 at gmail.com Sat Sep 11 06:29:57 2010 From: lamiaposta71 at gmail.com (Raffaele Recalcati) Date: Sat, 11 Sep 2010 13:29:57 +0200 Subject: Driver In-Reply-To: References: Message-ID: > Hi, I'm a novice embedded engineer who works in a IPTV STB project. We are > using a DaVinci DM6446 based evaluation board for developing a firmware for > our STB.? Unfortunetaly I am the only engineer who work in the software > development side, and? don't have enough backround to deal with problems > which I encountered.? Could you please enlighten me about these issues I'm working on DM365 kernel support development for our boards. I think, first of all, you need to become familiar with www.ti.com and Ti E2E community. Design Support -> Ti E2E community then Support Forums than Embedded software and finally Linux .. Here you can find some help about Ti releases. But first read carefully the documentation. > 1. I will use the open source Linux DaVinci kernel for development, and I > didn't understand the driver side, in documents of TI its been said that LSP > is integrated with Montavista kernel, is it still available to use LSP with > open community Linux kernel? If it is,how can I do this? In the case of DM365 (check for DM6446) the PSP kernel release is an easier way than open source Linux DaVinci kernel. Here you have the specifications of the latest PSP release http://processors.wiki.ti.com/index.php/DaVinci_PSP_03.01_GA_%28r37%29_Release_Notes > 2. Is there any pre-builded open source Linux kernel that all these drivers > work completely within ? PSP kernel release is opensource > 3. It seems that the video-display? driver not functional? for Dm644x, in > the http://processors.wiki.ti.com/index.php/DaVinci_GIT_Linux_Kernel If not you have to develop it or ask for a roadmap to Ti > 4. What is the difference between LSP and PSP.? I couldn't find any document > that gives detail about these issues . Could you give me any advice about > where to start? ? LSP = montavista PSP = free and Ti made Bye, Raffaele From michael.williamson at criticallink.com Sat Sep 11 08:14:14 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Sat, 11 Sep 2010 09:14:14 -0400 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C8AB85A.8060909@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <871v95f2xv.fsf@deeprootsystems.com> <4C86F369.6040906@criticallink.com> <4C880733.5010909@ti.com> <4C882EAA.9030903@criticallink.com> <4C892AC0.80409@criticallink.com> <4C893ADE.809@ti.com> <4C8950D4.9060102@criticallink.com> <4C8AB85A.8060909@ti.com> Message-ID: <4C8B80A6.5060609@criticallink.com> Hi Cyril, On 09/10/2010 06:59 PM, Cyril Chemparathy wrote: > Hi Mike, > > I have merged your latest two emails and responded to both here. > [...] > One of the patches posted on my repo [1] replaces the dumb mdelay() with > a bit more logic that calculates the worst-case access time. This > mechanism may work a lot better for you. Would you mind trying it out? > You patch from [1] is working much more reliably now (well, 6 for 6 boot cycles as well as several ifup/ifdown cycles). I do get the "resetting idled controlled" console message every cycle, it seems that will be expected now. [...] >> >> Also, your while(1) loops with the continue conditions on the second wait_for_user_access() >> in the read and writes might need some consideration, i.e.: >> >> while (1) { >> ret = wait_for_user_access(data); >> if (ret == -EAGAIN) >> continue; >> if (ret < 0) >> break; >> >> __raw_writel(reg, &data->regs->user[0].access); >> >> ret = wait_for_user_access(data); >> if (ret == -EAGAIN) >> continue; >> ^^^^^^^^^ <--- this will re-issue the request.... what you want? > > Yes, the wait_for_user_access() would have reset the controller, > throwing the current transaction out. The intent here is to restart the > current transaction with a newly initialized controller. > OK. Makes sense. Looking at it felt like there was a chance for end endless spin, but that seems unlikely given how that condition might fire. [...] >> Also, on the shutdown, I get a major kernel trace. Here is the dump, as much >> as I could catch of it.... (I need a better terminal program) > > [...] >> WARNING: at drivers/net/davinci_emac.c:1025 __cpdma_chan_free+0xac/0xb0() > > The current code spits out a huge volume of stuff as a result of a > WARN_ON in the rx handler. The gitweb on [1] has a patch that fixes this. > Yes, these messages are no longer issued with the patches from [1]. Thanks. > [...] >>>> The MDIO module upgrade (rev 1.4 -> 1.5) could have something to do with >>>> this behavior. Even so, I can't explain why this issue wasn't seen on >>>> da8xx prior to this series. The original code should (at least in >>>> theory) have sporadically locked up on emac open. >>>> >> I think, if I understand it correctly, that in the previous version of >> this code, the emac was reset *prior* to enabling, scanning, and assigning >> the associated phy on the MDIO bus. The new implementation sets up and scans >> the MDIO bus first, then comes back around to the EMAC second... hits a reset, >> and doesn't re-ENABLE the MDIO. > > AFAICS, that isn't entirely accurate. In the previous version, the mdio > bus was being brought up at probe time in davinci_emac_probe(). The > soft-reset was happening later on when the device is opened, in > emac_hw_enable(). > > The difference, however, is that the original code forced an > emac_mii_reset() immediately after the emac_hw_enable(). This is not > being done with the separated mdio, and that is the problem. In terms > of behavior, with the current work around, the new and old versions > should be close to identical. More below... > >> Also, maybe hitting the EMAC reset while the MDIO state machine is up is *bad*, I >> seem to recall some text in the user's guide about waiting for the state >> machine to stop before disabling it. I wonder if that also applies to reset? > > You are correct. EMAC soft-reset stops the MDIO mid-transaction, quite > unlike disabling the module via the control register. Therefore, there > is a risk that a badly designed phy could be left hanging in an > arbitrary state. However, all earlier versions of the emac code have > been exposed to this very same vulnerability (i.e. arbitrary emac > soft-reset regardless of mdio state) all along. > Thanks for straightening me out on this, Cryil. Your patch series in [1] seems to have resolved the issues I've been able to see on the da850 based board I'm using here. I appreciate your patience and quick response. I may try to beat on it a bit more with some network performance tests (even though it's not at all related to the immediate problems you've fixed) -- we've had that on our list of todos anyway for this module. I think it would be good to float your patches over to davinci-next, if possible, before the 37 merge window opens... Speaking, of course, from a very partial perspective. > [1] > http://arago-project.org/git/people/?p=cyril/linux-tnetv107x.git;a=shortlog;h=refs/heads/emac-cpdma-mdio-fixes -Mike From chtpatil at gmail.com Sat Sep 11 08:35:59 2010 From: chtpatil at gmail.com (chetan patil) Date: Sat, 11 Sep 2010 19:05:59 +0530 Subject: Davinci-linux-open-source Digest, Vol 57, Issue 43 In-Reply-To: References: Message-ID: Help me with Linux Toolchain. So that i can do some programming on Board. Linux fedora 12 has been installed on my laptop.!! Confused a lot. As nothing is visually available. On Sat, Sep 11, 2010 at 6:44 PM, < davinci-linux-open-source-request at linux.davincidsp.com> wrote: > Send Davinci-linux-open-source mailing list submissions to > davinci-linux-open-source at linux.davincidsp.com > > To subscribe or unsubscribe via the World Wide Web, visit > > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source > > or, via email, send a message with subject or body 'help' to > davinci-linux-open-source-request at linux.davincidsp.com > > You can reach the person managing the list at > davinci-linux-open-source-owner at linux.davincidsp.com > > When replying, please edit your Subject line so it is more specific > than "Re: Contents of Davinci-linux-open-source digest..." > > > Today's Topics: > > 1. Re: [PATCH v4 1/2] davinci: Add generic PWM support for PWM > control (Caglar Akyuz) > 2. Re: [PATCH v3 00/10] split out emac cpdma and mdio for reuse > (Cyril Chemparathy) > 3. Re: [PATCH v3 00/10] split out emac cpdma and mdio for reuse > (Caglar Akyuz) > 4. Re: Driver (Raffaele Recalcati) > 5. Re: [PATCH v3 00/10] split out emac cpdma and mdio for reuse > (Michael Williamson) > > > ---------------------------------------------------------------------- > > Message: 1 > Date: Fri, 10 Sep 2010 20:42:36 +0300 > From: Caglar Akyuz > To: Sugumar Natarajan > Cc: davinci-linux-open-source at linux.davincidsp.com > Subject: Re: [PATCH v4 1/2] davinci: Add generic PWM support for PWM > control > Message-ID: <201009102042.36977.caglarakyuz at gmail.com> > Content-Type: Text/Plain; charset="iso-8859-1" > > On Thursday 09 September 2010 01:40:49 pm Sugumar Natarajan wrote: > > This patch adds generic PWM support where it maintains the > > list of PWM control devices that can be added or removed. > > > > The interface provides a list of functions that can be accessed > > by the PWM control driver module and the generic PWM driver. > > > > The PWM control driver module such as eCAP uses the interface to > > register and add itself to the list as a PWM control device. > > The generic PWM driver uses the interface to search for a PWM control > > device and if present, uses the device for PWM control. > > > > Signed-off-by: Sugumar Natarajan > > --- > > Hi, > > [...] > > > + > > +int pwm_enable(struct pwm_device *pwm) > > +{ > > + if (WARN_ON(!pwm)) > > + return -EINVAL; > > + > > + return clk_enable(pwm->clk); > > +} > > +EXPORT_SYMBOL(pwm_enable); > > + > > I think 'clk_enable' should be controlled for un-matched pwm_enable/disable > operation. Otherwise, disabling PWM won't shut down peripheral clock. If I > understand inner workings of DaVinci clock implementation clock use_count > is > incremented with every clk_enable. > > Regards, > Caglar > > > ------------------------------ > > Message: 2 > Date: Fri, 10 Sep 2010 18:59:38 -0400 > From: Cyril Chemparathy > To: Michael Williamson > Cc: "davinci-linux-open-source at linux.davincidsp.com" > , > "netdev at vger.kernel.org" , " > tony at atomide.com" > , "linux-omap at vger.kernel.org" > , "davem at davemloft.net" > > Subject: Re: [PATCH v3 00/10] split out emac cpdma and mdio for reuse > Message-ID: <4C8AB85A.8060909 at ti.com> > Content-Type: text/plain; charset=UTF-8 > > Hi Mike, > > I have merged your latest two emails and responded to both here. > > [...] > > Your patch doesn't work with my board. It does attempt to reset the bus > on the read call, > > but following wait_for_user_access() calls are timing out and the _read() > and _write() calls punt. > > I bumped up the MDIO_TIMEOUT to 100 ms, and it works. I'm wondering if > the scanning logic > > has to complete an entire cycle (all 32 phys) before issuing a request, > and if it's a lot > > slower than expected. > > Based on the mdio module's state machine code, the scan does not need to > complete before a user-request is issued. However, when the module is > first enabled, it _must_ poll at least one phy (phy id 0) before it > handles the user-access request. Consequently, the first access after > coming out of reset may be slower than subsequent accesses. > > One of the patches posted on my repo [1] replaces the dumb mdelay() with > a bit more logic that calculates the worst-case access time. This > mechanism may work a lot better for you. Would you mind trying it out? > > Since the MDIO_TIMEOUT is simply a defensive measure, I have no > objections to raising this timeout (included in the updated stack). > > > I also found that the initial scanning logic would not reliably find the > PHY until I bumped > > up the delay time following the reset operation. Sometimes it would, > sometimes no. > > > > Also, your while(1) loops with the continue conditions on the second > wait_for_user_access() > > in the read and writes might need some consideration, i.e.: > > > > while (1) { > > ret = wait_for_user_access(data); > > if (ret == -EAGAIN) > > continue; > > if (ret < 0) > > break; > > > > __raw_writel(reg, &data->regs->user[0].access); > > > > ret = wait_for_user_access(data); > > if (ret == -EAGAIN) > > continue; > > ^^^^^^^^^ <--- this will re-issue the request.... > what you want? > > Yes, the wait_for_user_access() would have reset the controller, > throwing the current transaction out. The intent here is to restart the > current transaction with a newly initialized controller. > > > if (ret < 0) > > break; > > > > reg = __raw_readl(&data->regs->user[0].access); > > ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : > -EIO; > > break; > > } > > > > Also, on the shutdown, I get a major kernel trace. Here is the dump, as > much > > as I could catch of it.... (I need a better terminal program) > > [...] > > WARNING: at drivers/net/davinci_emac.c:1025 __cpdma_chan_free+0xac/0xb0() > > The current code spits out a huge volume of stuff as a result of a > WARN_ON in the rx handler. The gitweb on [1] has a patch that fixes this. > > [...] > >> > The MDIO module upgrade (rev 1.4 -> 1.5) could have something to do > with > >> > this behavior. Even so, I can't explain why this issue wasn't seen on > >> > da8xx prior to this series. The original code should (at least in > >> > theory) have sporadically locked up on emac open. > >> > > > I think, if I understand it correctly, that in the previous version of > > this code, the emac was reset *prior* to enabling, scanning, and > assigning > > the associated phy on the MDIO bus. The new implementation sets up and > scans > > the MDIO bus first, then comes back around to the EMAC second... hits a > reset, > > and doesn't re-ENABLE the MDIO. > > AFAICS, that isn't entirely accurate. In the previous version, the mdio > bus was being brought up at probe time in davinci_emac_probe(). The > soft-reset was happening later on when the device is opened, in > emac_hw_enable(). > > The difference, however, is that the original code forced an > emac_mii_reset() immediately after the emac_hw_enable(). This is not > being done with the separated mdio, and that is the problem. In terms > of behavior, with the current work around, the new and old versions > should be close to identical. More below... > > > Also, maybe hitting the EMAC reset while the MDIO state machine is up is > *bad*, I > > seem to recall some text in the user's guide about waiting for the state > > machine to stop before disabling it. I wonder if that also applies to > reset? > > You are correct. EMAC soft-reset stops the MDIO mid-transaction, quite > unlike disabling the module via the control register. Therefore, there > is a risk that a badly designed phy could be left hanging in an > arbitrary state. However, all earlier versions of the emac code have > been exposed to this very same vulnerability (i.e. arbitrary emac > soft-reset regardless of mdio state) all along. > > Regards > Cyril. > > > [1] > > http://arago-project.org/git/people/?p=cyril/linux-tnetv107x.git;a=shortlog;h=refs/heads/emac-cpdma-mdio-fixes > > > ------------------------------ > > Message: 3 > Date: Sat, 11 Sep 2010 11:54:41 +0300 > From: Caglar Akyuz > To: cyril at ti.com > Cc: "netdev at vger.kernel.org" , > "davinci-linux-open-source at linux.davincidsp.com" > , > "linux-omap at vger.kernel.org" > Subject: Re: [PATCH v3 00/10] split out emac cpdma and mdio for reuse > Message-ID: <201009111154.42171.caglarakyuz at gmail.com> > Content-Type: Text/Plain; charset="utf-8" > > On Friday 10 September 2010 06:23:52 pm Caglar Akyuz wrote: > > On Friday 10 September 2010 12:25:40 am Michael Williamson wrote: > > > Hi Cyril, > > > > > > On 09/09/2010 03:51 PM, Cyril Chemparathy wrote: > > > > Hi Mike, > > > > > > > > [...] > > > > > > > >> The hang is in wait_for_user_access() in the davinci_mdio_read() > call. > > > >> Looks like the state machine got put back into IDLE somewhere > between > > > >> the MDIO probe and the EMAC probe. Seems like there should be some > > > >> sort of time-out and error message in the wait_for_user_access() > > > >> method.... (maybe even a check for IDLE??) > > > >> > > > >> If I add a patch to check the state machine for IDLE and then > > > >> re-enable it in the davinci_mdio_read() call, it is able to press on > > > >> and come up. I don't see any calls to the davinci_mdio_suspend() > call, > > > >> so I am wondering if the EMAC probe routine, particularly the > > > >> application of the SOFTRESET, is causing the MDIO to drop back to > IDLE > > > >> / disabled. > > > >> > > > >> I can post the patch if you like, but it is a bit of a hack... > > > > > > > > An EMAC soft-reset clobbering the MDIO controller state is a > > > > possibility. I will poll TI designers to see if this could be the > > > > case. > > > > > > > > In any case, a couple of unanswered questions remain: > > > > > > > > 1. Why don't other davinci devices display similar behavior? > > > > > > > > 2. If the answer to #1 above is that the timing window is pretty > slim > > > > (i.e., only if an MDIO read/write is in progress during EMAC > > > > soft-reset), why do we hit this situation consistently on > > > > mityomap? > > > > > > Has it been confirmed that this only happens on mityomap? Has anyone > had > > > success using a da850 evm or other da850 platform? The configuration > > > for > > > > Same problem exists on another DA850 board, Hawkboard.(Sorry no support > in > > mainline yet) > > > > > the mityomap, wrt to the EMAC/MII/MDIO, is pretty much identical to > the > > > da850 evm using the MII interface. The only difference I am aware of > is > > > the assigned address to the PHY chip. The reference clocks and rates > > > are identical, AFAIK, to the evm. > > > > > > > I have put together a quick patch (tested dm365). See attached. > > > > > > Your patch doesn't work with my board. It does attempt to reset the > bus > > > on > > > > This patch fixes the problem here. I'm using kernel IP auto configuration > > and mounting fs over NFS. My system boots and I can login to my board. > > > > Regards, > > Caglar > > > > Unfortunately emac driver is not stable after this series. I face lock-ups > time to time, followed by attached kernel trace. > > Regards, > Caglar > _________________________________________________________________ > > [ 1651.440000] nfs: server 192.168.2.34 not responding, still trying > [ 1859.010000] ------------[ cut here ]------------ > [ 1859.010000] WARNING: at net/sched/sch_generic.c:258 > dev_watchdog+0x184/0x294() > [ 1859.020000] NETDEV WATCHDOG: eth0 (davinci_emac): transmit queue 0 timed > out > [ 1859.020000] Modules linked in: > [ 1859.030000] Backtrace: > [ 1859.030000] [] (dump_backtrace+0x0/0x10c) from [] > (dump_stack+0x18/0x1c) > [ 1859.040000] r7:c03b5de8 r6:c025a13c r5:c039045c r4:00000102 > [ 1859.040000] [] (dump_stack+0x0/0x1c) from [] > (warn_slowpath_common+0x58/0x70) > [ 1859.050000] [] (warn_slowpath_common+0x0/0x70) from > [] > (warn_slowpath_fmt+0x38/0x40) > [ 1859.060000] r8:c03b4000 r7:00000030 r6:c0437564 r5:c7bbc000 r4:00000000 > [ 1859.070000] [] (warn_slowpath_fmt+0x0/0x40) from [] > (dev_watchdog+0x184/0x294) > [ 1859.080000] r3:c7bbc000 r2:c0390474 > [ 1859.080000] [] (dev_watchdog+0x0/0x294) from [] > (run_timer_softirq+0x1c4/0x29c) > [ 1859.090000] [] (run_timer_softirq+0x0/0x29c) from [] > (__do_softirq+0x98/0x12c) > [ 1859.100000] [] (__do_softirq+0x0/0x12c) from [] > (irq_exit+0x48/0x9c) > [ 1859.110000] [] (irq_exit+0x0/0x9c) from [] > (asm_do_IRQ+0x80/0xa0) > [ 1859.120000] [] (asm_do_IRQ+0x0/0xa0) from [] > (__irq_svc+0x4c/0x9c) > [ 1859.120000] Exception stack(0xc03b5f38 to 0xc03b5f80) > [ 1859.130000] 5f20: > 00000000 0005317f > [ 1859.140000] 5f40: 0005217f 60000013 c03b4000 c03b8ba0 c03b89d4 c03dcc50 > c0023e04 41069265 > [ 1859.150000] 5f60: c0023d94 c03b5f8c 600000d3 c03b5f80 c002da6c c002da78 > 60000013 ffffffff > [ 1859.150000] r5:febfd000 r4:ffffffff > [ 1859.160000] [] (default_idle+0x0/0x34) from [] > (cpu_idle+0x74/0xdc) > [ 1859.170000] [] (cpu_idle+0x0/0xdc) from [] > (rest_init+0xa4/0xbc) > [ 1859.170000] r7:c03b89c8 r6:c0026018 r5:c03dcc1c r4:00000002 > [ 1859.180000] [] (rest_init+0x0/0xbc) from [] > (start_kernel+0x270/0x2d0) > [ 1859.190000] r4:c042d70c > [ 1859.190000] [] (start_kernel+0x0/0x2d0) from [] > (__enable_mmu+0x0/0x2c) > [ 1859.200000] r6:c002641c r5:c03dcc78 r4:00053175 > [ 1859.200000] ---[ end trace d278f645c502dc20 ]--- > > > ------------------------------ > > Message: 4 > Date: Sat, 11 Sep 2010 13:29:57 +0200 > From: Raffaele Recalcati > To: ?zg?r Ozan Yusufo?lu > Cc: davinci-linux-open-source at linux.davincidsp.com > Subject: Re: Driver > Message-ID: > > Content-Type: text/plain; charset=UTF-8 > > > Hi, I'm a novice embedded engineer who works in a IPTV STB project. We > are > > using a DaVinci DM6446 based evaluation board for developing a firmware > for > > our STB.? Unfortunetaly I am the only engineer who work in the software > > development side, and? don't have enough backround to deal with problems > > which I encountered.? Could you please enlighten me about these issues > > I'm working on DM365 kernel support development for our boards. > I think, first of all, you need to become familiar with www.ti.com and > Ti E2E community. > Design Support -> Ti E2E community > then Support Forums > than Embedded software > and finally Linux .. > Here you can find some help about Ti releases. > But first read carefully the documentation. > > > 1. I will use the open source Linux DaVinci kernel for development, and I > > didn't understand the driver side, in documents of TI its been said that > LSP > > is integrated with Montavista kernel, is it still available to use LSP > with > > open community Linux kernel? If it is,how can I do this? > > In the case of DM365 (check for DM6446) the PSP kernel release is an > easier way than open source Linux DaVinci kernel. > Here you have the specifications of the latest PSP release > > http://processors.wiki.ti.com/index.php/DaVinci_PSP_03.01_GA_%28r37%29_Release_Notes > > > 2. Is there any pre-builded open source Linux kernel that all these > drivers > > work completely within ? > > PSP kernel release is opensource > > > > 3. It seems that the video-display? driver not functional? for Dm644x, in > > the http://processors.wiki.ti.com/index.php/DaVinci_GIT_Linux_Kernel > > If not you have to develop it or ask for a roadmap to Ti > > > 4. What is the difference between LSP and PSP.? I couldn't find any > document > > that gives detail about these issues . Could you give me any advice about > > where to start? ? > > LSP = montavista > PSP = free and Ti made > > Bye, > Raffaele > > > ------------------------------ > > Message: 5 > Date: Sat, 11 Sep 2010 09:14:14 -0400 > From: Michael Williamson > To: cyril at ti.com > Cc: "davinci-linux-open-source at linux.davincidsp.com" > , > "netdev at vger.kernel.org" , " > tony at atomide.com" > , "linux-omap at vger.kernel.org" > , "davem at davemloft.net" > > Subject: Re: [PATCH v3 00/10] split out emac cpdma and mdio for reuse > Message-ID: <4C8B80A6.5060609 at criticallink.com> > Content-Type: text/plain; charset=UTF-8 > > Hi Cyril, > > On 09/10/2010 06:59 PM, Cyril Chemparathy wrote: > > Hi Mike, > > > > I have merged your latest two emails and responded to both here. > > > [...] > > One of the patches posted on my repo [1] replaces the dumb mdelay() with > > a bit more logic that calculates the worst-case access time. This > > mechanism may work a lot better for you. Would you mind trying it out? > > > > You patch from [1] is working much more reliably now (well, 6 for 6 boot > cycles as well as > several ifup/ifdown cycles). I do get the "resetting idled controlled" > console message > every cycle, it seems that will be expected now. > > [...] > > >> > >> Also, your while(1) loops with the continue conditions on the second > wait_for_user_access() > >> in the read and writes might need some consideration, i.e.: > >> > >> while (1) { > >> ret = wait_for_user_access(data); > >> if (ret == -EAGAIN) > >> continue; > >> if (ret < 0) > >> break; > >> > >> __raw_writel(reg, &data->regs->user[0].access); > >> > >> ret = wait_for_user_access(data); > >> if (ret == -EAGAIN) > >> continue; > >> ^^^^^^^^^ <--- this will re-issue the > request.... what you want? > > > > Yes, the wait_for_user_access() would have reset the controller, > > throwing the current transaction out. The intent here is to restart the > > current transaction with a newly initialized controller. > > > > OK. Makes sense. Looking at it felt like there was a chance for end > endless spin, but that > seems unlikely given how that condition might fire. > > [...] > > >> Also, on the shutdown, I get a major kernel trace. Here is the dump, as > much > >> as I could catch of it.... (I need a better terminal program) > > > > [...] > >> WARNING: at drivers/net/davinci_emac.c:1025 > __cpdma_chan_free+0xac/0xb0() > > > > The current code spits out a huge volume of stuff as a result of a > > WARN_ON in the rx handler. The gitweb on [1] has a patch that fixes > this. > > > > Yes, these messages are no longer issued with the patches from [1]. > Thanks. > > > [...] > >>>> The MDIO module upgrade (rev 1.4 -> 1.5) could have something to do > with > >>>> this behavior. Even so, I can't explain why this issue wasn't seen on > >>>> da8xx prior to this series. The original code should (at least in > >>>> theory) have sporadically locked up on emac open. > >>>> > >> I think, if I understand it correctly, that in the previous version of > >> this code, the emac was reset *prior* to enabling, scanning, and > assigning > >> the associated phy on the MDIO bus. The new implementation sets up and > scans > >> the MDIO bus first, then comes back around to the EMAC second... hits a > reset, > >> and doesn't re-ENABLE the MDIO. > > > > AFAICS, that isn't entirely accurate. In the previous version, the mdio > > bus was being brought up at probe time in davinci_emac_probe(). The > > soft-reset was happening later on when the device is opened, in > > emac_hw_enable(). > > > > The difference, however, is that the original code forced an > > emac_mii_reset() immediately after the emac_hw_enable(). This is not > > being done with the separated mdio, and that is the problem. In terms > > of behavior, with the current work around, the new and old versions > > should be close to identical. More below... > > > >> Also, maybe hitting the EMAC reset while the MDIO state machine is up is > *bad*, I > >> seem to recall some text in the user's guide about waiting for the state > >> machine to stop before disabling it. I wonder if that also applies to > reset? > > > > You are correct. EMAC soft-reset stops the MDIO mid-transaction, quite > > unlike disabling the module via the control register. Therefore, there > > is a risk that a badly designed phy could be left hanging in an > > arbitrary state. However, all earlier versions of the emac code have > > been exposed to this very same vulnerability (i.e. arbitrary emac > > soft-reset regardless of mdio state) all along. > > > > Thanks for straightening me out on this, Cryil. Your patch series in [1] > seems to > have resolved the issues I've been able to see on the da850 based board I'm > using > here. I appreciate your patience and quick response. I may try to beat on > it a > bit more with some network performance tests (even though it's not at all > related > to the immediate problems you've fixed) -- we've had that on our list of > todos > anyway for this module. > > I think it would be good to float your patches over to davinci-next, if > possible, before the > 37 merge window opens... Speaking, of course, from a very partial > perspective. > > > [1] > > > http://arago-project.org/git/people/?p=cyril/linux-tnetv107x.git;a=shortlog;h=refs/heads/emac-cpdma-mdio-fixes > > -Mike > > > ------------------------------ > > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source at linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source > > > End of Davinci-linux-open-source Digest, Vol 57, Issue 43 > ********************************************************* > -- Regards, Chetan Arvind Patil, +919970018364 http://sites.google.com/site/chtpatil/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From sshtylyov at ru.mvista.com Sat Sep 11 13:23:12 2010 From: sshtylyov at ru.mvista.com (Sergei Shtylyov) Date: Sat, 11 Sep 2010 22:23:12 +0400 Subject: [PATCH] musb_gadget: restart request on clearing endpoint halt Message-ID: <201009112223.12768.sshtylyov@ru.mvista.com> Commit 46034dca515bc4ddca0399ae58106d1f5f0d809f (USB: musb_gadget_ep0: stop abusing musb_gadget_set_halt()) forgot to add in the code to restart a queued request to the code handling clearing the endpoint halt. This results in a couple of USB resets while enumerating the file-backed storage gadget due to CSW packet not being sent for the MODE SENSE(10) command. Signed-off-by: Sergei Shtylyov Cc: stable at kernel.org --- The patch is against the recent Linus' tree. The regression was introduced back in 2.6.33 times. drivers/usb/musb/musb_gadget.c | 2 +- drivers/usb/musb/musb_gadget.h | 2 ++ drivers/usb/musb/musb_gadget_ep0.c | 9 +++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) Index: linux-davinci/drivers/usb/musb/musb_gadget.c =================================================================== --- linux-davinci.orig/drivers/usb/musb/musb_gadget.c +++ linux-davinci/drivers/usb/musb/musb_gadget.c @@ -1081,7 +1081,7 @@ struct free_record { /* * Context: controller locked, IRQs blocked. */ -static void musb_ep_restart(struct musb *musb, struct musb_request *req) +void musb_ep_restart(struct musb *musb, struct musb_request *req) { DBG(3, "<== %s request %p len %u on hw_ep%d\n", req->tx ? "TX/IN" : "RX/OUT", Index: linux-davinci/drivers/usb/musb/musb_gadget.h =================================================================== --- linux-davinci.orig/drivers/usb/musb/musb_gadget.h +++ linux-davinci/drivers/usb/musb/musb_gadget.h @@ -105,4 +105,6 @@ extern void musb_gadget_cleanup(struct m extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int); +extern void musb_ep_restart(struct musb *, struct musb_request *); + #endif /* __MUSB_GADGET_H */ Index: linux-davinci/drivers/usb/musb/musb_gadget_ep0.c =================================================================== --- linux-davinci.orig/drivers/usb/musb/musb_gadget_ep0.c +++ linux-davinci/drivers/usb/musb/musb_gadget_ep0.c @@ -261,6 +261,7 @@ __acquires(musb->lock) ctrlrequest->wIndex & 0x0f; struct musb_ep *musb_ep; struct musb_hw_ep *ep; + struct musb_request *request; void __iomem *regs; int is_in; u16 csr; @@ -302,6 +303,14 @@ __acquires(musb->lock) musb_writew(regs, MUSB_RXCSR, csr); } + /* Maybe start the first request in the queue */ + request = to_musb_request( + next_request(musb_ep)); + if (!musb_ep->busy && request) { + DBG(3, "restarting the request\n"); + musb_ep_restart(musb, request); + } + /* select ep0 again */ musb_ep_select(mbase, 0); } break; From sugumar at ti.com Mon Sep 13 03:46:21 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Mon, 13 Sep 2010 14:16:21 +0530 Subject: [PATCH v4 1/2] davinci: Add generic PWM support for PWM control In-Reply-To: <201009101934.08045.caglarakyuz@gmail.com> References: <1284028849-16680-1-git-send-email-sugumar@ti.com> <201009101934.08045.caglarakyuz@gmail.com> Message-ID: <000001cb5320$2d402af0$87c080d0$@com> On Fri, Sep 10, 2010 at 22:04:08, Caglar Akyuz wrote: > On Thursday 09 September 2010 01:40:49 pm Sugumar Natarajan wrote: > > This patch adds generic PWM support where it maintains the list of PWM > > control devices that can be added or removed. > > > > The interface provides a list of functions that can be accessed by the > > PWM control driver module and the generic PWM driver. > > > > The PWM control driver module such as eCAP uses the interface to > > register and add itself to the list as a PWM control device. > > The generic PWM driver uses the interface to search for a PWM control > > device and if present, uses the device for PWM control. > > > > How does real pwm modules fit in this architecture? For instance L-138 have eHRPWM modules for PWM generation. > > * Should we add a seperate file for eHRPWM module? > > or > > * Should we integrate it in davinci_pwm file? > > Best Regards, > Caglar > > > Signed-off-by: Sugumar Natarajan > > --- > > Changes since v2: > > a) pwm_config_device callback is made more flexible. > > b) pwm_request function code has been made more cleaner. > > c) Sanity-check/warn has been included. > > > > arch/arm/mach-davinci/Makefile | 3 + > > arch/arm/mach-davinci/davinci_pwm.c | 130 > > ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | > > 32 ++++++ > > 3 files changed, 165 insertions(+), 0 deletions(-) create mode > > 100644 arch/arm/mach-davinci/davinci_pwm.c > > create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h > > > > diff --git a/arch/arm/mach-davinci/Makefile > > b/arch/arm/mach-davinci/Makefile index a7a70d1..90ca821 100644 > > --- a/arch/arm/mach-davinci/Makefile > > +++ b/arch/arm/mach-davinci/Makefile > > @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o > > obj-$(CONFIG_CPU_FREQ) += cpufreq.o > > obj-$(CONFIG_CPU_IDLE) += cpuidle.o > > obj-$(CONFIG_SUSPEND) += pm.o sleep.o > > + > > +# Generic PWM control support > > +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o > > diff --git a/arch/arm/mach-davinci/davinci_pwm.c > > b/arch/arm/mach-davinci/davinci_pwm.c new file mode 100644 index > > 0000000..c2b8b9a > > --- /dev/null > > +++ b/arch/arm/mach-davinci/davinci_pwm.c > > @@ -0,0 +1,130 @@ > > +/* > > + * Copyright (C) 2010 Texas Instruments Incorporated - > > +http://www.ti.com/ > > + * > > + * This program is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU General Public License as > > + * published by the Free Software Foundation version 2. > > + * > > + * This program is distributed .as is. WITHOUT ANY WARRANTY of any > > + * kind, whether express or implied; without even the implied > > +warranty > > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) { > > + unsigned int clock_freq; > > + unsigned int period_cycles; > > + unsigned int duty_cycle; > > + int ret = 0; > > + > > + if (WARN_ON(!pwm)) > > + return -EINVAL; > > + > > + if (pwm->pwm_config_device) { > > + if (!period_ns || duty_ns > period_ns) > > + return -EINVAL; > > + > > + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; > > + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; > > + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; > > + ret = pwm->pwm_config_device(pwm, period_cycles, duty_cycle); > > + } > > + > > + return ret; > > +} > > +EXPORT_SYMBOL(pwm_config); > > + > > +int pwm_enable(struct pwm_device *pwm) { > > + if (WARN_ON(!pwm)) > > + return -EINVAL; > > + > > + return clk_enable(pwm->clk); > > +} > > +EXPORT_SYMBOL(pwm_enable); > > + > > +void pwm_disable(struct pwm_device *pwm) { > > + if (WARN_ON(!pwm)) > > + return; > > + > > + clk_disable(pwm->clk); > > +} > > +EXPORT_SYMBOL(pwm_disable); > > + > > +static DEFINE_MUTEX(pwm_lock); > > +static LIST_HEAD(pwm_list); > > + > > +struct pwm_device *pwm_request(int pwm_id, const char *label) { > > + struct pwm_device *pwm, *tmp_pwm = ERR_PTR(-ENOENT); > > + > > + mutex_lock(&pwm_lock); > > + > > + list_for_each_entry(pwm, &pwm_list, node) { > > + if (pwm->pwm_id == pwm_id) { > > + if (pwm->use_count == 0) { > > + pwm->use_count++; > > + pwm->label = label; > > + } else { > > + pwm = ERR_PTR(-EBUSY); > > + } > > + tmp_pwm = pwm; > > + break; > > + } > > + } > > + > > + mutex_unlock(&pwm_lock); > > + return tmp_pwm; > > +} > > +EXPORT_SYMBOL(pwm_request); > > + > > +void pwm_free(struct pwm_device *pwm) { > > + if (WARN_ON(!pwm)) > > + return; > > + > > + mutex_lock(&pwm_lock); > > + > > + if (pwm->use_count) { > > + pwm->use_count--; > > + pwm->label = NULL; > > + } else { > > + dev_warn(&pwm->pdev->dev, "PWM device already freed\n"); > > + } > > + > > + mutex_unlock(&pwm_lock); > > +} > > +EXPORT_SYMBOL(pwm_free); > > + > > +void pwm_add(struct pwm_device *pwm) > > +{ > > + if (WARN_ON(!pwm)) > > + return; > > + > > + mutex_lock(&pwm_lock); > > + list_add_tail(&pwm->node, &pwm_list); > > + mutex_unlock(&pwm_lock); > > +} > > +EXPORT_SYMBOL(pwm_add); > > + > > +void pwm_remove(struct pwm_device *pwm) { > > + if (WARN_ON(!pwm)) > > + return; > > + > > + mutex_lock(&pwm_lock); > > + list_del(&pwm->node); > > + mutex_unlock(&pwm_lock); > > +} > > +EXPORT_SYMBOL(pwm_remove); > > diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h > > b/arch/arm/mach-davinci/include/mach/davinci_pwm.h new file mode > > 100644 index 0000000..3b7a3c8 > > --- /dev/null > > +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h > > @@ -0,0 +1,32 @@ > > +/* > > + * Copyright (C) 2010 Texas Instruments Incorporated - > > +http://www.ti.com/ > > + * > > + * This program is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU General Public License as > > + * published by the Free Software Foundation version 2. > > + * > > + * This program is distributed .as is. WITHOUT ANY WARRANTY of any > > + * kind, whether express or implied; without even the implied > > +warranty > > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + * > > + */ > > + > > +#ifndef __DAVINCI_PWM_H > > +#define __DAVINCI_PWM_H > > + > > +struct pwm_device { > > + struct list_head node; > > + struct platform_device *pdev; > > + int (*pwm_config_device)(struct pwm_device *pwm, > > + unsigned int period, unsigned int dutycycle); > > + const char *label; > > + struct clk *clk; > > + unsigned int use_count; > > + unsigned int pwm_id; > > +}; > > + > > +void pwm_add(struct pwm_device *pwm); void pwm_remove(struct > > +pwm_device *pwm); > > + > > +#endif > > > Caglar, We have to add separate file for eHRPWM module. Regards, N.Sugumar From sugumar at ti.com Mon Sep 13 03:49:40 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Mon, 13 Sep 2010 14:19:40 +0530 Subject: [PATCH v4 1/2] davinci: Add generic PWM support for PWM control In-Reply-To: <201009102042.36977.caglarakyuz@gmail.com> References: <1284028849-16680-1-git-send-email-sugumar@ti.com> <201009102042.36977.caglarakyuz@gmail.com> Message-ID: <000101cb5320$a3b729e0$eb257da0$@com> On Fri, Sep 10, 2010 at 23:12:36, Caglar Akyuz wrote: > On Thursday 09 September 2010 01:40:49 pm Sugumar Natarajan wrote: > > This patch adds generic PWM support where it maintains the list of PWM > > control devices that can be added or removed. > > > > The interface provides a list of functions that can be accessed by the > > PWM control driver module and the generic PWM driver. > > > > The PWM control driver module such as eCAP uses the interface to > > register and add itself to the list as a PWM control device. > > The generic PWM driver uses the interface to search for a PWM control > > device and if present, uses the device for PWM control. > > > > Signed-off-by: Sugumar Natarajan > > --- > > Hi, > > [...] > > > + > > +int pwm_enable(struct pwm_device *pwm) { > > + if (WARN_ON(!pwm)) > > + return -EINVAL; > > + > > + return clk_enable(pwm->clk); > > +} > > +EXPORT_SYMBOL(pwm_enable); > > + > > I think 'clk_enable' should be controlled for un-matched pwm_enable/disable operation. Otherwise, disabling PWM won't shut down peripheral clock. If I understand inner workings of DaVinci clock implementation clock use_count is incremented with every clk_enable. > > Regards, > Caglar > Caglar, I could not understand what you mean by "un-match" .could you please explain? Regards, N.sugumar From albertbu at gmail.com Mon Sep 13 07:12:58 2010 From: albertbu at gmail.com (Albert Burbea) Date: Mon, 13 Sep 2010 14:12:58 +0200 Subject: voice codec driver Message-ID: Hi everybody are there any plans/schedule to add the DM365 internal voice codec to the linux tree? Thanks all -- Albert Burbea Harishonim 8 Ramat Gan 52502, Israel Tel/Fax + 972-3-7526016 Mobile: +972-52-3541842 -------------- next part -------------- An HTML attachment was scrubbed... URL: From sshtylyov at mvista.com Mon Sep 13 08:28:25 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Mon, 13 Sep 2010 17:28:25 +0400 Subject: voice codec driver In-Reply-To: References: Message-ID: <4C8E26F9.1020205@mvista.com> Hello. Albert Burbea wrote: > Hi everybody > are there any plans/schedule to add the DM365 internal voice codec to > the linux tree? The DM365 voice codec support has been merged back in March already. WBR, Sergei From lamiaposta71 at gmail.com Mon Sep 13 09:06:38 2010 From: lamiaposta71 at gmail.com (Raffaele Recalcati) Date: Mon, 13 Sep 2010 16:06:38 +0200 Subject: voice codec driver In-Reply-To: <4C8E26F9.1020205@mvista.com> References: <4C8E26F9.1020205@mvista.com> Message-ID: On Mon, Sep 13, 2010 at 3:28 PM, Sergei Shtylyov wrote: > Hello. > > Albert Burbea wrote: > >> Hi everybody >> are there any plans/schedule to add the DM365 internal voice codec to the >> linux tree? > > ? The DM365 voice codec support has been merged back in March already. And I have checked it in 2.6.32 arago kernel. Some fixes are needed. Look at the following for more info: http://e2e.ti.com/support/embedded/f/354/p/56231/226155.aspx#226155 From cyril at ti.com Mon Sep 13 09:09:15 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 10:09:15 -0400 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <201009111154.42171.caglarakyuz@gmail.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <4C8950D4.9060102@criticallink.com> <201009101823.52755.caglarakyuz@gmail.com> <201009111154.42171.caglarakyuz@gmail.com> Message-ID: <4C8E308B.7020003@ti.com> Hi Caglar, [...] > Unfortunately emac driver is not stable after this series. I face lock-ups > time to time, followed by attached kernel trace. Could you elaborate on your test scenario so that I can try and reproduce the problem at my end? Also, did you have the contents of my commit stack in this particular kernel build? Assuming that the DMA got stuck at some point leading up to the transmit timeout, any ideas as to why a host error was not thrown? To help debug, I'll post out a set of patches that dump out the MAC (and DMA) registers on timeout. That should give us some visibility into the problem. > [ 1651.440000] nfs: server 192.168.2.34 not responding, still trying > [ 1859.010000] ------------[ cut here ]------------ > [ 1859.010000] WARNING: at net/sched/sch_generic.c:258 > dev_watchdog+0x184/0x294() > [ 1859.020000] NETDEV WATCHDOG: eth0 (davinci_emac): transmit queue 0 timed > out [...] Regards Cyril. From pablo.bitton at gmail.com Mon Sep 13 09:23:00 2010 From: pablo.bitton at gmail.com (Pablo Bitton) Date: Mon, 13 Sep 2010 16:23:00 +0200 Subject: [PATCH 6/6] i2c: davinci: bus recovery procedure to clear the bus In-Reply-To: <1264549293-25556-7-git-send-email-khilman@deeprootsystems.com> References: <1264549293-25556-1-git-send-email-khilman@deeprootsystems.com> <1264549293-25556-7-git-send-email-khilman@deeprootsystems.com> Message-ID: Hi Philby, On Wed, Jan 27, 2010 at 1:41 AM, Kevin Hilman wrote: > From: Philby John > > Come out of i2c time out condition by following the > bus recovery procedure outlined in the i2c protocol v3 spec. > The kernel must be robust enough to gracefully recover > from i2c bus failure without having to reset the machine. > This is done by first NACKing the slave, pulsing the SCL > line 9 times and then sending the stop command. > > This patch has been tested on a DM6446 and DM355 > > Signed-off-by: Philby John > Signed-off-by: Srinivasan, Nageswari > Acked-by: Kevin Hilman > --- > drivers/i2c/busses/i2c-davinci.c | 57 > +++++++++++++++++++++++++++++++++++-- > 1 files changed, 53 insertions(+), 4 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-davinci.c > b/drivers/i2c/busses/i2c-davinci.c > index 35f9daa..5459065 100644 > --- a/drivers/i2c/busses/i2c-davinci.c > +++ b/drivers/i2c/busses/i2c-davinci.c > @@ -36,6 +36,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -43,6 +44,7 @@ > /* ----- global defines ----------------------------------------------- */ > > #define DAVINCI_I2C_TIMEOUT (1*HZ) > +#define DAVINCI_I2C_MAX_TRIES 2 > #define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_AAS | \ > DAVINCI_I2C_IMR_SCD | \ > DAVINCI_I2C_IMR_ARDY | \ > @@ -130,6 +132,44 @@ static inline u16 davinci_i2c_read_reg(struct > davinci_i2c_dev *i2c_dev, int reg) > return __raw_readw(i2c_dev->base + reg); > } > > +/* Generate a pulse on the i2c clock pin. */ > +static void generic_i2c_clock_pulse(unsigned int scl_pin) > +{ > + u16 i; > + > + if (scl_pin) { > + /* Send high and low on the SCL line */ > + for (i = 0; i < 9; i++) { > + gpio_set_value(scl_pin, 0); > + udelay(20); > + gpio_set_value(scl_pin, 1); > + udelay(20); > + } > + } > +} > + > +/* This routine does i2c bus recovery as specified in the > + * i2c protocol Rev. 03 section 3.16 titled "Bus clear" > + */ > +static void i2c_recover_bus(struct davinci_i2c_dev *dev) > +{ > + u32 flag = 0; > + struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; > + > + dev_err(dev->dev, "initiating i2c bus recovery\n"); > + /* Send NACK to the slave */ > + flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); > + flag |= DAVINCI_I2C_MDR_NACK; > + /* write the data into mode register */ > + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); > + if (pdata) > + generic_i2c_clock_pulse(pdata->scl_pin); > + /* Send STOP */ > + flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); > + flag |= DAVINCI_I2C_MDR_STP; > + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); > +} > + > static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev, > int val) > { > @@ -235,14 +275,22 @@ static int i2c_davinci_wait_bus_not_busy(struct > davinci_i2c_dev *dev, > char allow_sleep) > { > unsigned long timeout; > + static u16 to_cnt; > > timeout = jiffies + dev->adapter.timeout; > while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) > & DAVINCI_I2C_STR_BB) { > - if (time_after(jiffies, timeout)) { > - dev_warn(dev->dev, > - "timeout waiting for bus ready\n"); > - return -ETIMEDOUT; > + if (to_cnt <= DAVINCI_I2C_MAX_TRIES) { > + if (time_after(jiffies, timeout)) { > + dev_warn(dev->dev, > + "timeout waiting for bus ready\n"); > + to_cnt++; > + return -ETIMEDOUT; > + } else { > + to_cnt = 0; > + i2c_recover_bus(dev); > + i2c_davinci_init(dev); > + } > } > if (allow_sleep) > schedule_timeout(1); > The resulting loop has the following drawbacks: 1) If to_cnt reaches DAVINCI_I2C_MAX_TRIES+1 (which it currently can't, see 2) and the i2c bus collapses, the kernel will be stuck in the loop forever, especially if allow_sleep is false. 2) The to_cnt static var never increments beyond 1. It's initialized to zero and then kept at zero until the timeout expires. When the timeout expires, to_cnt is incremented once, until the next call to the function, where it will be zeroed again. 3) Do we really want to retry recovering the bus thousands of times, until the timeout arrives? It seems to me that if the bus recovery procedure didn't help after one or two tries, it probably never will. I also have the following nitpicks: a) The timeout variable actually holds the finish time. b) The i2c_recover_bus function uses dev_err to report a bus recovery process, but if all recovery attempts failed and the timeout was reached, only dev_warn is used to report the timeout. Other than that the patch is very helpful, thanks a lot. Below is my suggestion for the wait_bus_not_busy function. My patch has been tested on a DM6446. Signed-off-by: Pablo Bitton -- diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -220,16 +261,24 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev, char allow_sleep) { - unsigned long timeout; + unsigned long finish_time; + unsigned long to_cnt = 0; - timeout = jiffies + dev->adapter.timeout; + finish_time = jiffies + dev->adapter.timeout; + /* While bus busy */ while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) & DAVINCI_I2C_STR_BB) { - if (time_after(jiffies, timeout)) { + if (time_after(jiffies, finish_time)) { dev_warn(dev->dev, "timeout waiting for bus ready\n"); return -ETIMEDOUT; } + else if (to_cnt <= DAVINCI_I2C_MAX_TRIES) { + dev_warn(dev->dev, "bus busy, performing bus recovery\n"); + ++to_cnt; + i2c_recover_bus(dev); + i2c_davinci_init(dev); + } if (allow_sleep) schedule_timeout(1); } -------------- next part -------------- An HTML attachment was scrubbed... URL: From cyril at ti.com Mon Sep 13 10:46:00 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 11:46:00 -0400 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C8E308B.7020003@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <4C8950D4.9060102@criticallink.com> <201009101823.52755.caglarakyuz@gmail.com> <201009111154.42171.caglarakyuz@gmail.com> <4C8E308B.7020003@ti.com> Message-ID: <4C8E4738.3040809@ti.com> Hi Caglar, [...] > Assuming that the DMA got stuck at some point leading up to the transmit > timeout, any ideas as to why a host error was not thrown? To help > debug, I'll post out a set of patches that dump out the MAC (and DMA) > registers on timeout. That should give us some visibility into the problem. I have posted a couple of additional patches for this on [1]. Would you mind giving these a quick try? The register dumps should prove useful in figuring this out. Regards Cyril. [1] http://arago-project.org/git/people/?p=cyril/linux-tnetv107x.git;a=shortlog;h=refs/heads/emac-cpdma-mdio-fixes From cyril at ti.com Mon Sep 13 11:29:41 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 12:29:41 -0400 Subject: [PATCH 0/7] add tnetv107x input drivers Message-ID: <1284395388-32687-1-git-send-email-cyril@ti.com> Texas Instruments' TNETV107X is an ARM1176 based SoC, with on-chip touchscreen and keypad controllers. This patch series adds drivers for these controllers. Cyril Chemparathy (7): davinci: define tnetv107x keypad platform data input: add driver for tnetv107x on-chip keypad controller davinci: add tnetv107x keypad platform device davinci: add keypad config for tnetv107x evm board input: add driver for tnetv107x touchscreen controller davinci: add tnetv107x touchscreen platform device davinci: add touchscreen config for tnetv107x evm board arch/arm/mach-davinci/board-tnetv107x-evm.c | 51 +++ arch/arm/mach-davinci/devices-tnetv107x.c | 54 +++ arch/arm/mach-davinci/include/mach/tnetv107x.h | 24 ++ drivers/input/keyboard/Kconfig | 9 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/tnetv107x-keypad.c | 324 ++++++++++++++++ drivers/input/touchscreen/Kconfig | 6 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/tnetv107x-ts.c | 481 ++++++++++++++++++++++++ 9 files changed, 951 insertions(+), 0 deletions(-) create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c From cyril at ti.com Mon Sep 13 11:29:43 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 12:29:43 -0400 Subject: [PATCH 2/7] input: add driver for tnetv107x on-chip keypad controller In-Reply-To: <1284395388-32687-1-git-send-email-cyril@ti.com> References: <1284395388-32687-1-git-send-email-cyril@ti.com> Message-ID: <1284395388-32687-3-git-send-email-cyril@ti.com> This patch adds support for tnetv107x's on-chip keypad controller. Signed-off-by: Cyril Chemparathy --- drivers/input/keyboard/Kconfig | 9 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/tnetv107x-keypad.c | 324 +++++++++++++++++++++++++++++ 3 files changed, 334 insertions(+), 0 deletions(-) create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 9cc488d..0ea8648 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -457,4 +457,13 @@ config KEYBOARD_W90P910 To compile this driver as a module, choose M here: the module will be called w90p910_keypad. +config KEYBOARD_TNETV107X + tristate "TI TNETV107X keypad support" + depends on ARCH_DAVINCI_TNETV107X + help + Say Y here if you want to use the TNETV107X keypad. + + To compile this driver as a module, choose M here: the + module will be called tnetv107x-keypad. + endif diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 504b591..63261b0 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -41,3 +41,4 @@ obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o +obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c new file mode 100644 index 0000000..5039164 --- /dev/null +++ b/drivers/input/keyboard/tnetv107x-keypad.c @@ -0,0 +1,324 @@ +/* + * Texas Instruments TNETV107X Keypad Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define KEYPAD_ROWS 9 +#define KEYPAD_COLS 9 + +struct keypad_regs { + u32 rev; + u32 mode; + u32 mask; + u32 pol; + u32 dclock; + u32 rclock; + u32 stable_cnt; + u32 in_en; + u32 out; + u32 out_en; + u32 in; + u32 lock; + u32 pres[3]; +}; + +#define keypad_read(kp, reg) __raw_readl(&(kp)->regs->reg) +#define keypad_write(kp, reg, val) __raw_writel(val, &(kp)->regs->reg) + +struct keypad_data { + struct tnetv107x_keypad_data data; + struct input_dev *input_dev; + struct resource *res; + struct keypad_regs __iomem *regs; + struct clk *clk; + struct device *dev; + u32 irq_press; + u32 irq_release; + u32 curr_keys[3]; + u32 prev_keys[3]; +}; + +static void handle_change(struct keypad_data *kp) +{ + int bit, i; + + for (bit = 0; bit < (KEYPAD_ROWS * KEYPAD_COLS); bit++) { + int idx = bit / 32; + u32 mask = 1 << (bit % 32); + u32 curr = kp->curr_keys[idx] & mask; + u32 prev = kp->prev_keys[idx] & mask; + int row = bit / KEYPAD_COLS; + int col = bit % KEYPAD_COLS; + int ofs = row * kp->data.cols + col; + + if (col >= kp->data.cols || row >= kp->data.rows) + continue; + + if (curr && !prev) { + /* Report key press */ + if (kp->data.keynames && kp->data.keynames[ofs]) + dev_dbg(kp->dev, "%s (%d) pressed\n", + kp->data.keynames[ofs], ofs); + input_report_key(kp->input_dev, + kp->data.keymap[ofs], 1); + } else if (!curr && prev) { + /* Report key release */ + if (kp->data.keynames && kp->data.keynames[ofs]) + dev_dbg(kp->dev, "%s (%d) released\n", + kp->data.keynames[ofs], ofs); + input_report_key(kp->input_dev, + kp->data.keymap[ofs], 0); + } + } + + /* Update shadow copy */ + for (i = 0; i < 3; i++) + kp->prev_keys[i] = kp->curr_keys[i]; + + input_sync(kp->input_dev); +} + +static irqreturn_t keypad_irq_press(int irq, void *data) +{ + struct keypad_data *kp = (struct keypad_data *)data; + int i; + + for (i = 0; i < 3; i++) + kp->curr_keys[i] = keypad_read(kp, pres[i]); + handle_change(kp); + keypad_write(kp, lock, 0); /* Allow hardware updates */ + return IRQ_HANDLED; +} + +static irqreturn_t keypad_irq_release(int irq, void *data) +{ + struct keypad_data *kp = (struct keypad_data *)data; + int i; + + /* Hardware says all keys have been released */ + for (i = 0; i < 3; i++) + kp->curr_keys[i] = 0; + handle_change(kp); + return IRQ_HANDLED; +} + +static int tnetv107x_keypad_probe(struct platform_device *pdev) +{ + struct tnetv107x_keypad_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct keypad_data *kp; + int i, ret = 0; + u32 rev = 0; + + ret = -EINVAL; + if (!pdata) { + dev_err(dev, "cannot find device data\n"); + return ret; + } + + ret = -ENOMEM; + kp = kzalloc(sizeof(struct keypad_data), GFP_KERNEL); + if (!kp) { + dev_err(dev, "cannot allocate device info\n"); + return ret; + } + + dev_set_drvdata(dev, kp); + kp->data = *pdata; + kp->dev = dev; + + ret = -ENOMEM; + kp->input_dev = input_allocate_device(); + if (!kp->input_dev) { + dev_err(dev, "cannot allocate input device\n"); + goto error0; + } + + ret = -ENODEV; + kp->irq_press = platform_get_irq_byname(pdev, "press"); + kp->irq_release = platform_get_irq_byname(pdev, "release"); + if (kp->irq_press < 0 || kp->irq_release < 0) { + dev_err(dev, "cannot determine device interrupts\n"); + goto error1; + } + + ret = -ENODEV; + kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!kp->res) { + dev_err(dev, "cannot determine register area\n"); + goto error1; + } + + ret = -EINVAL; + if (!request_mem_region(kp->res->start, resource_size(kp->res), + pdev->name)) { + dev_err(dev, "cannot claim register memory\n"); + goto error1; + } + + ret = -ENOMEM; + kp->regs = ioremap(kp->res->start, resource_size(kp->res)); + if (!kp->regs) { + dev_err(dev, "cannot map register memory\n"); + goto error2; + } + + ret = -EINVAL; + kp->clk = clk_get(dev, NULL); + if (!kp->clk) { + dev_err(dev, "cannot claim device clock\n"); + goto error3; + } + clk_enable(kp->clk); + + /* Initialize device registers */ + keypad_write(kp, mode, 0); + keypad_write(kp, mask, ~((((1 << kp->data.rows)-1) << 9) | + (((1 << kp->data.cols)-1)))); + keypad_write(kp, pol, 0x3ffff); + keypad_write(kp, dclock, kp->data.debounce); + keypad_write(kp, rclock, 4*kp->data.debounce); + keypad_write(kp, stable_cnt, kp->data.stable); + + /* Enable Input */ + keypad_write(kp, in_en, 0); + mdelay(1); + keypad_write(kp, in_en, 1); + + ret = request_irq(kp->irq_press, keypad_irq_press, 0, + "keypad-press", kp); + if (ret < 0) { + dev_err(dev, "Could not allocate keypad press key irq\n"); + goto error4; + } + + ret = request_irq(kp->irq_release, keypad_irq_release, 0, + "keypad-release", kp); + if (ret < 0) { + dev_err(dev, "Could not allocate keypad release key irq\n"); + goto error5; + } + + set_bit(EV_KEY, kp->input_dev->evbit); + for (i = 0; i < kp->data.keymap_size; i++) + set_bit(kp->data.keymap[i] & KEY_MAX, kp->input_dev->keybit); + + kp->input_dev->name = "tnetv107x-keypad"; + kp->input_dev->phys = "tnetv107x-keypad/input0"; + kp->input_dev->dev.parent = &pdev->dev; + kp->input_dev->id.bustype = BUS_HOST; + kp->input_dev->id.vendor = 0x0001; + + rev = keypad_read(kp, rev); + kp->input_dev->id.product = ((rev >> 8) & 0x07); + kp->input_dev->id.version = ((rev >> 16) & 0xfff); + + kp->input_dev->keycode = kp->data.keymap; + kp->input_dev->keycodesize = sizeof(int); + kp->input_dev->keycodemax = kp->data.keymap_size; + ret = input_register_device(kp->input_dev); + if (ret < 0) { + dev_err(dev, "Could not register input device\n"); + goto error6; + } + + dev_info(dev, "registered keypad device\n"); + return 0; + +error6: + free_irq(kp->irq_release, kp); +error5: + free_irq(kp->irq_press, kp); +error4: + clk_disable(kp->clk); + clk_put(kp->clk); +error3: + iounmap(kp->regs); +error2: + release_mem_region(kp->res->start, resource_size(kp->res)); +error1: + input_free_device(kp->input_dev); +error0: + platform_set_drvdata(pdev, NULL); + kfree(kp); + return ret; +} + +static int tnetv107x_keypad_remove(struct platform_device *pdev) +{ + struct keypad_data *kp = dev_get_drvdata(&pdev->dev); + + if (kp) { + input_unregister_device(kp->input_dev); + free_irq(kp->irq_release, kp); + free_irq(kp->irq_press, kp); + clk_disable(kp->clk); + clk_put(kp->clk); + iounmap(kp->regs); + release_mem_region(kp->res->start, resource_size(kp->res)); + input_free_device(kp->input_dev); + platform_set_drvdata(pdev, NULL); + kfree(kp); + } + return 0; +} + +static int tnetv107x_keypad_suspend(struct platform_device *pdev, + pm_message_t state) +{ + /* Nothing yet */ + return 0; +} + +static int tnetv107x_keypad_resume(struct platform_device *pdev) +{ + /* Nothing yet */ + return 0; +} + +static struct platform_driver tnetv107x_keypad_driver = { + .probe = tnetv107x_keypad_probe, + .remove = tnetv107x_keypad_remove, + .suspend = tnetv107x_keypad_suspend, + .resume = tnetv107x_keypad_resume, + .driver.name = "tnetv107x-keypad", +}; + +static int __init tnetv107x_keypad_init(void) +{ + return platform_driver_register(&tnetv107x_keypad_driver); +} + +static void __exit tnetv107x_keypad_exit(void) +{ + platform_driver_unregister(&tnetv107x_keypad_driver); +} + +module_init(tnetv107x_keypad_init); +module_exit(tnetv107x_keypad_exit); + +MODULE_AUTHOR("Cyril Chemparathy"); +MODULE_DESCRIPTION("TNETV107X Keypad Driver"); +MODULE_LICENSE("GPL"); -- 1.7.0.4 From cyril at ti.com Mon Sep 13 11:29:42 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 12:29:42 -0400 Subject: [PATCH 1/7] davinci: define tnetv107x keypad platform data In-Reply-To: <1284395388-32687-1-git-send-email-cyril@ti.com> References: <1284395388-32687-1-git-send-email-cyril@ti.com> Message-ID: <1284395388-32687-2-git-send-email-cyril@ti.com> This patch adds a definition for the platform data structure needed to configure the keypad controller on tnetv107x socs. Since this controller is (so far) present only on tnetv107x devices, the data structure definition has been kept local to tnetv107x. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/include/mach/tnetv107x.h | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h index c720647..1ee3035 100644 --- a/arch/arm/mach-davinci/include/mach/tnetv107x.h +++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h @@ -37,6 +37,16 @@ #include #include +struct tnetv107x_keypad_data { + int *keymap; + const char **keynames; + int keymap_size; + int rows; + int cols; + u32 debounce; + u32 stable; +}; + struct tnetv107x_device_info { struct davinci_uart_config *serial_config; struct davinci_mmc_config *mmc_config[2]; /* 2 controllers */ -- 1.7.0.4 From cyril at ti.com Mon Sep 13 11:29:45 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 12:29:45 -0400 Subject: [PATCH 4/7] davinci: add keypad config for tnetv107x evm board In-Reply-To: <1284395388-32687-1-git-send-email-cyril@ti.com> References: <1284395388-32687-1-git-send-email-cyril@ti.com> Message-ID: <1284395388-32687-5-git-send-email-cyril@ti.com> This patch adds evm board specific keymap definitions and controller configuration data for on-chip keypad controller on tnetv107x silicon. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/board-tnetv107x-evm.c | 42 +++++++++++++++++++++++++++ 1 files changed, 42 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c index fe2a9d9..2fe7a3f 100644 --- a/arch/arm/mach-davinci/board-tnetv107x-evm.c +++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -141,10 +142,51 @@ static struct davinci_uart_config serial_config __initconst = { .enabled_uarts = BIT(1), }; +static int keymap[] = { + /* row 0 */ + KEY_NUMERIC_1, KEY_NUMERIC_2, KEY_NUMERIC_3, KEY_FN_F1, KEY_MENU, + /* row 1 */ + KEY_NUMERIC_4, KEY_NUMERIC_5, KEY_NUMERIC_6, KEY_UP, KEY_FN_F2, + /* row 2 */ + KEY_NUMERIC_7, KEY_NUMERIC_8, KEY_NUMERIC_9, KEY_LEFT, KEY_ENTER, + /* row 3 */ + KEY_NUMERIC_STAR, KEY_NUMERIC_0, KEY_NUMERIC_POUND, KEY_DOWN, KEY_RIGHT, + /* row 4 */ + KEY_FN_F3, KEY_FN_F4, KEY_MUTE, KEY_HOME, KEY_BACK, + /* row 5 */ + KEY_VOLUMEDOWN, KEY_VOLUMEUP, KEY_F1, KEY_F2, KEY_F3, +}; + +static const char *keynames[] = { + /* row 0 */ + "1", "2", "3", "S1 (FN_F1)", "MENU", + /* row 1 */ + "4", "5", "6", "UP", "S2 (FN_F2)", + /* row 2 */ + "7", "8", "9", "LEFT", "ENTER", + /* row 3 */ + "*", "0", "#", "DOWN", "RIGHT", + /* row 4 */ + "SPEAKER (FN_F3)", "HEADSET (FN_F4)", "MUTE", "HOME", "BACK", + /* row 5 */ + "VOL_DOWN", "VOL_UP", "F1", "F2", "F3", +}; + +static struct tnetv107x_keypad_data keypad_config = { + .keynames = keynames, + .keymap = keymap, + .keymap_size = ARRAY_SIZE(keymap), + .rows = 6, + .cols = 5, + .debounce = 0x400, + .stable = 0x3, +}; + static struct tnetv107x_device_info evm_device_info __initconst = { .serial_config = &serial_config, .mmc_config[1] = &mmc_config, /* controller 1 */ .nand_config[0] = &nand_config, /* chip select 0 */ + .keypad_config = &keypad_config, }; static __init void tnetv107x_evm_board_init(void) -- 1.7.0.4 From cyril at ti.com Mon Sep 13 11:29:46 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 12:29:46 -0400 Subject: [PATCH 5/7] input: add driver for tnetv107x touchscreen controller In-Reply-To: <1284395388-32687-1-git-send-email-cyril@ti.com> References: <1284395388-32687-1-git-send-email-cyril@ti.com> Message-ID: <1284395388-32687-6-git-send-email-cyril@ti.com> This patch adds support for tnetv107x's on-chip touchscreen controller. Signed-off-by: Cyril Chemparathy --- drivers/input/touchscreen/Kconfig | 6 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/tnetv107x-ts.c | 481 ++++++++++++++++++++++++++++++ 3 files changed, 488 insertions(+), 0 deletions(-) create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 0069d97..e56a170 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -638,4 +638,10 @@ config TOUCHSCREEN_STMPE To compile this driver as a module, choose M here: the module will be called stmpe-ts. +config TOUCHSCREEN_TNETV107X + tristate "TI TNETV107X touchscreen support" + depends on ARCH_DAVINCI_TNETV107X + help + Say Y here if you want to use the TNETV107X touchscreen. + endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 28217e1..55a7db9 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -52,3 +52,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o +obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c new file mode 100644 index 0000000..a8543c5 --- /dev/null +++ b/drivers/input/touchscreen/tnetv107x-ts.c @@ -0,0 +1,481 @@ +/* + * Texas Instruments TNETV107X Touchscreen Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Poll Rates */ +#define TSC_PENUP_POLL (HZ / 5) + +/* + * The first and last samples of a touch interval are usually garbage and need + * to be filtered out with these devices. The following definitions control + * the number of samples skipped. + */ +#define TSC_HEAD_SKIP 1 +#define TSC_TAIL_SKIP 1 +#define TSC_SKIP (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1) +#define TSC_SAMPLES (TSC_SKIP + 1) + +/* Register Offsets */ +struct tsc_regs { + u32 rev; + u32 tscm; + u32 bwcm; + u32 swc; + u32 adcchnl; + u32 adcdata; + u32 chval[4]; +}; + +/* TSC Mode Configuration Register (tscm) bits */ +#define WMODE BIT(0) +#define TSKIND BIT(1) +#define ZMEASURE_EN BIT(2) +#define IDLE BIT(3) +#define TSC_EN BIT(4) +#define STOP BIT(5) +#define ONE_SHOT BIT(6) +#define SINGLE BIT(7) +#define AVG BIT(8) +#define AVGNUM(x) (((x) & 0x03) << 9) +#define PVSTC(x) (((x) & 0x07) << 11) +#define PON BIT(14) +#define PONBG BIT(15) +#define AFERST BIT(16) + +/* ADC DATA Capture Register bits */ +#define DATA_VALID BIT(16) + +/* Register Access Macros */ +#define tsc_read(ts, reg) __raw_readl(&(ts)->regs->reg) +#define tsc_write(ts, reg, val) __raw_writel(val, &(ts)->regs->reg); +#define tsc_set_bits(ts, reg, val) \ + tsc_write(ts, reg, tsc_read(ts, reg) | (val)) +#define tsc_clr_bits(ts, reg, val) \ + tsc_write(ts, reg, tsc_read(ts, reg) & ~(val)) + +struct sample { + int x, y, p; +}; + +struct tsc_data { + struct tnetv107x_tsc_data data; + struct input_dev *input_dev; + struct resource *res; + struct tsc_regs __iomem *regs; + struct timer_list timer; + spinlock_t lock; + struct clk *clk; + struct device *dev; + int sample_count; + struct sample samples[TSC_SAMPLES]; + int tsc_irq; + int cal[TSC_CAL_SIZE]; +}; + +/* default calibration that works for most evm boards */ +static int tscal_set; +static int tscal[TSC_CAL_SIZE]; +module_param_array(tscal, int, &tscal_set, 0); + +static inline int +tsc_read_sample(struct tsc_data *ts, struct sample* sample) +{ + int x, y, z1, z2, t, p = 0; + u32 val; + + val = tsc_read(ts, chval[0]); + if (val & DATA_VALID) + x = val & 0xffff; + else + return -EINVAL; + + y = tsc_read(ts, chval[1]) & 0xffff; + z1 = tsc_read(ts, chval[2]) & 0xffff; + z2 = tsc_read(ts, chval[3]) & 0xffff; + + if (z1) { + t = ((600 * x) * (z2 - z1)); + p = t / (u32) (z1 << 12); + if (p < 0) + p = 0; + } + + sample->x = (ts->cal[2] + ts->cal[0] * x + ts->cal[1] * y); + sample->x /= ts->cal[6]; + sample->y = (ts->cal[5] + ts->cal[3] * x + ts->cal[4] * y); + sample->y /= ts->cal[6]; + sample->p = p; + + return 0; +} + +static inline void tsc_report_up(struct tsc_data *ts) +{ + input_report_abs(ts->input_dev, ABS_PRESSURE, 0); + input_report_key(ts->input_dev, BTN_TOUCH, 0); + input_sync(ts->input_dev); +} + +static inline void tsc_report(struct tsc_data *ts, int x, int y, int p) +{ + input_report_abs(ts->input_dev, ABS_X, x); + input_report_abs(ts->input_dev, ABS_Y, y); + input_report_abs(ts->input_dev, ABS_PRESSURE, p); +} + +static inline void tsc_report_down(struct tsc_data *ts, bool touch) +{ + if (touch) + input_report_key(ts->input_dev, BTN_TOUCH, 1); + input_sync(ts->input_dev); +} + +static inline void tsc_poll(unsigned long data) +{ + struct tsc_data *ts = (struct tsc_data *)data; + unsigned long flags; + int i, val, x, y, p; + + spin_lock_irqsave(&ts->lock, flags); + + if (ts->sample_count >= TSC_SKIP) { + tsc_report_up(ts); + } else if (ts->sample_count > 0) { + /* + * A touch event lasted less than our skip count. Salvage and + * report anyway. + */ + for (i = 0, val = 0; i < ts->sample_count; i++) + val += ts->samples[i].x; + x = val / ts->sample_count; + + for (i = 0, val = 0; i < ts->sample_count; i++) + val += ts->samples[i].y; + y = val / ts->sample_count; + + for (i = 0, val = 0; i < ts->sample_count; i++) + val += ts->samples[i].p; + p = val / ts->sample_count; + + tsc_report(ts, x, y, p); + tsc_report_down(ts, true); + } + + ts->sample_count = 0; + + spin_unlock_irqrestore(&ts->lock, flags); +} + +static irqreturn_t tsc_irq(int irq, void *dev_id) +{ + struct tsc_data *ts = (struct tsc_data *)dev_id; + struct sample *sample; + int index; + + spin_lock(&ts->lock); + + index = ts->sample_count % TSC_SAMPLES; + sample = &ts->samples[index]; + if (tsc_read_sample(ts, sample) >= 0) { + ++ts->sample_count; + + if (ts->sample_count < TSC_SKIP) + goto done; + + index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES; + sample = &ts->samples[index]; + + tsc_report(ts, sample->x, sample->y, sample->y); + tsc_report_down(ts, (ts->sample_count == TSC_SKIP)); +done: + mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL); + } + + spin_unlock(&ts->lock); + return IRQ_HANDLED; +} + +static ssize_t tsc_cal_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tsc_data *ts = dev_get_drvdata(dev); + ssize_t len = 0; + int i; + + for (i = 0; i < 6; i++) + len += snprintf(buf+len, PAGE_SIZE-len, "%d ", ts->cal[i]); + + len += snprintf(buf+len, PAGE_SIZE-len, "%d\n", ts->cal[6]); + + return len; +} + +/* + * The calibration data format is identical to the contents of tslib's + * generated output + */ +static ssize_t tsc_cal_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct tsc_data *ts = dev_get_drvdata(dev); + int index = 0; + int cal[TSC_CAL_SIZE]; + const char *cur = buf, *end = buf + count; + char *tmp; + unsigned long flags; + + for (index = 0; index < TSC_CAL_SIZE; index++) { + while (isspace(*cur) && cur < end) + cur++; + if (cur >= end) { + dev_err(ts->dev, "premature end in calib data\n"); + return -EINVAL; + } + + if (isdigit(*cur) || *cur == '-') { + cal[index] = simple_strtol(cur, &tmp, 0); + cur = tmp; + } + } + + spin_lock_irqsave(&ts->lock, flags); + memcpy(ts->cal, cal, sizeof(cal)); + spin_unlock_irqrestore(&ts->lock, flags); + + return count; +} + +static struct device_attribute tsc_attr_cal = + __ATTR(tscal, S_IWUSR | S_IRUGO, tsc_cal_show, tsc_cal_store); + +static int tsc_probe(struct platform_device *pdev) +{ + struct tnetv107x_tsc_data *pdata = pdev->dev.platform_data; + struct tsc_data *ts; + int ret = 0, *cal; + u32 rev = 0, val = 0; + struct device *dev = &pdev->dev; + + if (!pdata) { + dev_err(dev, "could not find platform data\n"); + return -EINVAL; + } + + ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL); + if (!ts) { + dev_err(dev, "cannot allocate device info\n"); + return -ENOMEM; + } + + ts->dev = dev; + ts->data = *pdata; + dev_set_drvdata(dev, ts); + + cal = (tscal_set == TSC_CAL_SIZE) ? tscal : ts->data.calibration_data; + memcpy(ts->cal, cal, TSC_CAL_SIZE * sizeof(int)); + + ret = -ENOMEM; + ts->input_dev = input_allocate_device(); + if (!ts->input_dev) { + dev_err(dev, "cannot allocate input device\n"); + goto error0; + } + + ret = -ENODEV; + ts->tsc_irq = platform_get_irq(pdev, 0); + if (ts->tsc_irq < 0) { + dev_err(dev, "cannot determine device interrupt\n"); + goto error1; + } + + ret = -ENODEV; + ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!ts->res) { + dev_err(dev, "cannot determine register area\n"); + goto error1; + } + + ret = -EINVAL; + if (!request_mem_region(ts->res->start, resource_size(ts->res), + pdev->name)) { + dev_err(dev, "cannot claim register memory\n"); + goto error1; + } + + ret = -ENOMEM; + ts->regs = ioremap(ts->res->start, resource_size(ts->res)); + if (!ts->regs) { + dev_err(dev, "cannot map register memory\n"); + goto error2; + } + + ret = -EINVAL; + ts->clk = clk_get(dev, NULL); + if (!ts->clk) { + dev_err(dev, "cannot claim device clock\n"); + goto error3; + } + clk_enable(ts->clk); + + spin_lock_init(&ts->lock); + + init_timer(&ts->timer); + setup_timer(&ts->timer, tsc_poll, (unsigned long)ts); + + /* Go to idle mode, before any initialization */ + while ((tsc_read(ts, tscm) & IDLE) == 0) + barrier(); + + /* Configure the TSC Control register*/ + val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN); + tsc_write(ts, tscm, val); + + /* Bring TSC out of reset: Clear AFE reset bit */ + val &= ~(AFERST); + tsc_write(ts, tscm, val); + udelay(10); + + /* Configure all pins for hardware control*/ + tsc_write(ts, bwcm, 0); + + /* Finally enable the TSC */ + tsc_set_bits(ts, tscm, TSC_EN); + + ret = -EINVAL; + if (request_irq(ts->tsc_irq, tsc_irq, 0, "tnetv107x-ts", ts)) { + dev_err(dev, "Could not allocate ts irq\n"); + goto error4; + } + + ret = device_create_file(ts->dev, &tsc_attr_cal); + if (ret < 0) { + dev_err(dev, "Could not create sysfs entry!\n"); + goto error5; + } + + rev = tsc_read(ts, rev); + ts->input_dev->name = "tnetv107x-ts"; + ts->input_dev->phys = "tnetv107x-ts/input0"; + ts->input_dev->id.bustype = BUS_HOST; + ts->input_dev->id.vendor = 0x0001; + ts->input_dev->id.product = ((rev >> 8) & 0x07); + ts->input_dev->id.version = ((rev >> 16) & 0xfff); + ts->input_dev->dev.parent = &pdev->dev; + + /* Declare capabilities */ + set_bit(EV_KEY, ts->input_dev->evbit); + set_bit(BTN_TOUCH, ts->input_dev->keybit); + set_bit(EV_ABS, ts->input_dev->evbit); + set_bit(ABS_X, ts->input_dev->absbit); + set_bit(ABS_Y, ts->input_dev->absbit); + set_bit(ABS_PRESSURE, ts->input_dev->absbit); + + input_set_abs_params(ts->input_dev, ABS_X, 0, ts->data.xres, 5, 0); + input_set_abs_params(ts->input_dev, ABS_Y, 0, ts->data.yres, 5, 0); + input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0); + + ret = input_register_device(ts->input_dev); + if (ret < 0) + goto error6; + + return 0; + +error6: + device_remove_file(ts->dev, &tsc_attr_cal); +error5: + free_irq(ts->tsc_irq, ts); +error4: + clk_disable(ts->clk); + clk_put(ts->clk); +error3: + iounmap(ts->regs); +error2: + release_mem_region(ts->res->start, resource_size(ts->res)); +error1: + input_free_device(ts->input_dev); +error0: + kfree(ts); + dev_set_drvdata(dev, NULL); + return ret; +} + +static int tsc_remove(struct platform_device *pdev) +{ + struct tsc_data *ts = dev_get_drvdata(&pdev->dev); + + if (!ts) + return 0; + + tsc_clr_bits(ts, tscm, TSC_EN); + del_timer_sync(&ts->timer); + device_remove_file(ts->dev, &tsc_attr_cal); + free_irq(ts->tsc_irq, ts); + clk_disable(ts->clk); + clk_put(ts->clk); + iounmap(ts->regs); + release_mem_region(ts->res->start, resource_size(ts->res)); + input_free_device(ts->input_dev); + kfree(ts); + dev_set_drvdata(&pdev->dev, NULL); + return 0; +} + +static int tsc_suspend(struct platform_device *pdev, pm_message_t state) +{ + /* Nothing yet */ + return 0; +} + +static int tsc_resume(struct platform_device *pdev) +{ + /* Nothing yet */ + return 0; +} + +static struct platform_driver tsc_driver = { + .probe = tsc_probe, + .remove = tsc_remove, + .suspend = tsc_suspend, + .resume = tsc_resume, + .driver.name = "tnetv107x-ts", +}; + +static int __init tsc_init(void) +{ + return platform_driver_register(&tsc_driver); +} + +static void __exit tsc_exit(void) +{ + platform_driver_unregister(&tsc_driver); +} + +module_init(tsc_init); +module_exit(tsc_exit); + +MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); +MODULE_LICENSE("GPL"); -- 1.7.0.4 From cyril at ti.com Mon Sep 13 11:29:44 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 12:29:44 -0400 Subject: [PATCH 3/7] davinci: add tnetv107x keypad platform device In-Reply-To: <1284395388-32687-1-git-send-email-cyril@ti.com> References: <1284395388-32687-1-git-send-email-cyril@ti.com> Message-ID: <1284395388-32687-4-git-send-email-cyril@ti.com> This patch adds a platform device definition for tnetv107x's keypad controller. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/devices-tnetv107x.c | 30 ++++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/tnetv107x.h | 1 + 2 files changed, 31 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c index 2718a3a..086269f 100644 --- a/arch/arm/mach-davinci/devices-tnetv107x.c +++ b/arch/arm/mach-davinci/devices-tnetv107x.c @@ -33,6 +33,7 @@ #define TNETV107X_WDOG_BASE 0x08086700 #define TNETV107X_SDIO0_BASE 0x08088700 #define TNETV107X_SDIO1_BASE 0x08088800 +#define TNETV107X_KEYPAD_BASE 0x08088a00 #define TNETV107X_ASYNC_EMIF_CNTRL_BASE 0x08200000 #define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE 0x30000000 #define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE 0x40000000 @@ -298,6 +299,30 @@ static int __init nand_init(int chipsel, struct davinci_nand_pdata *data) return platform_device_register(pdev); } +static struct resource keypad_resources[] = { + { + .start = TNETV107X_KEYPAD_BASE, + .end = TNETV107X_KEYPAD_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_TNETV107X_KEYPAD, + .flags = IORESOURCE_IRQ, + .name = "press", + }, + { + .start = IRQ_TNETV107X_KEYPAD_FREE, + .flags = IORESOURCE_IRQ, + .name = "release", + }, +}; + +static struct platform_device keypad_device = { + .name = "tnetv107x-keypad", + .num_resources = ARRAY_SIZE(keypad_resources), + .resource = keypad_resources, +}; + void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) { int i; @@ -317,4 +342,9 @@ void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) for (i = 0; i < 4; i++) if (info->nand_config[i]) nand_init(i, info->nand_config[i]); + + if (info->keypad_config) { + keypad_device.dev.platform_data = info->keypad_config; + platform_device_register(&keypad_device); + } } diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h index 1ee3035..9f5350f 100644 --- a/arch/arm/mach-davinci/include/mach/tnetv107x.h +++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h @@ -51,6 +51,7 @@ struct tnetv107x_device_info { struct davinci_uart_config *serial_config; struct davinci_mmc_config *mmc_config[2]; /* 2 controllers */ struct davinci_nand_pdata *nand_config[4]; /* 4 chipsels */ + struct tnetv107x_keypad_data *keypad_config; }; extern struct platform_device tnetv107x_wdt_device; -- 1.7.0.4 From cyril at ti.com Mon Sep 13 11:29:48 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 12:29:48 -0400 Subject: [PATCH 7/7] davinci: add touchscreen config for tnetv107x evm board In-Reply-To: <1284395388-32687-1-git-send-email-cyril@ti.com> References: <1284395388-32687-1-git-send-email-cyril@ti.com> Message-ID: <1284395388-32687-8-git-send-email-cyril@ti.com> This patch adds evm board specific definitions (dimensions, default calibration, etc.) for the on-chip keypad controller on tnetv107x silicon. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/board-tnetv107x-evm.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c index 2fe7a3f..287c5ee 100644 --- a/arch/arm/mach-davinci/board-tnetv107x-evm.c +++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c @@ -182,11 +182,20 @@ static struct tnetv107x_keypad_data keypad_config = { .stable = 0x3, }; +static struct tnetv107x_tsc_data tsc_config = { + .xres = 800, + .yres = 480, + .calibration_data = { + 217, 14019, -2540712, 8690, -140, -1651470, 65536, + }, +}; + static struct tnetv107x_device_info evm_device_info __initconst = { .serial_config = &serial_config, .mmc_config[1] = &mmc_config, /* controller 1 */ .nand_config[0] = &nand_config, /* chip select 0 */ .keypad_config = &keypad_config, + .tsc_config = &tsc_config, }; static __init void tnetv107x_evm_board_init(void) -- 1.7.0.4 From cyril at ti.com Mon Sep 13 11:29:47 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 12:29:47 -0400 Subject: [PATCH 6/7] davinci: add tnetv107x touchscreen platform device In-Reply-To: <1284395388-32687-1-git-send-email-cyril@ti.com> References: <1284395388-32687-1-git-send-email-cyril@ti.com> Message-ID: <1284395388-32687-7-git-send-email-cyril@ti.com> This patch adds a platform device definition for tnetv107x's touchscreen controller. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/devices-tnetv107x.c | 24 ++++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/tnetv107x.h | 13 +++++++++++++ 2 files changed, 37 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c index 086269f..018ca13 100644 --- a/arch/arm/mach-davinci/devices-tnetv107x.c +++ b/arch/arm/mach-davinci/devices-tnetv107x.c @@ -31,6 +31,7 @@ #define TNETV107X_TPTC0_BASE 0x01c10000 #define TNETV107X_TPTC1_BASE 0x01c10400 #define TNETV107X_WDOG_BASE 0x08086700 +#define TNETV107X_TSC_BASE 0x08088500 #define TNETV107X_SDIO0_BASE 0x08088700 #define TNETV107X_SDIO1_BASE 0x08088800 #define TNETV107X_KEYPAD_BASE 0x08088a00 @@ -323,6 +324,24 @@ static struct platform_device keypad_device = { .resource = keypad_resources, }; +static struct resource tsc_resources[] = { + { + .start = TNETV107X_TSC_BASE, + .end = TNETV107X_TSC_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_TNETV107X_TSC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device tsc_device = { + .name = "tnetv107x-ts", + .num_resources = ARRAY_SIZE(tsc_resources), + .resource = tsc_resources, +}; + void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) { int i; @@ -347,4 +366,9 @@ void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) keypad_device.dev.platform_data = info->keypad_config; platform_device_register(&keypad_device); } + + if (info->tsc_config) { + tsc_device.dev.platform_data = info->tsc_config; + platform_device_register(&tsc_device); + } } diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h index 9f5350f..7e33148 100644 --- a/arch/arm/mach-davinci/include/mach/tnetv107x.h +++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h @@ -47,11 +47,24 @@ struct tnetv107x_keypad_data { u32 stable; }; +struct tnetv107x_tsc_data { + int xres, yres; + + /* + * Calibration info: + * out_x = (C0 * in_x + C1 * in_y + C2) / C6 + * out_y = (C3 * in_x + C4 * in_y + C5) / C6 + */ +#define TSC_CAL_SIZE 7 + int calibration_data[TSC_CAL_SIZE]; +}; + struct tnetv107x_device_info { struct davinci_uart_config *serial_config; struct davinci_mmc_config *mmc_config[2]; /* 2 controllers */ struct davinci_nand_pdata *nand_config[4]; /* 4 chipsels */ struct tnetv107x_keypad_data *keypad_config; + struct tnetv107x_tsc_data *tsc_config; }; extern struct platform_device tnetv107x_wdt_device; -- 1.7.0.4 From caglarakyuz at gmail.com Mon Sep 13 12:51:46 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Mon, 13 Sep 2010 20:51:46 +0300 Subject: [PATCH v3 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <4C8E308B.7020003@ti.com> References: <1283891142-15522-1-git-send-email-cyril@ti.com> <201009111154.42171.caglarakyuz@gmail.com> <4C8E308B.7020003@ti.com> Message-ID: <201009132051.46042.caglarakyuz@gmail.com> On Monday 13 September 2010 05:09:15 pm Cyril Chemparathy wrote: > Hi Caglar, > > [...] > > > Unfortunately emac driver is not stable after this series. I face > > lock-ups time to time, followed by attached kernel trace. > > Could you elaborate on your test scenario so that I can try and > reproduce the problem at my end? Also, did you have the contents of my > commit stack in this particular kernel build? > Ooops! I didn't noticed your commits till you noted, I was working with DaVinci head. Applying patches in your tree solves all my problems and all my use cases are working now. However, I just barely tested them. To make myself forgiven here are my 'netperf' numbers before and after your patches applied: TCP_STREAM : 54.64 Mbit vs 52.84 Mbit UDP_STREAM : 96.27 Mbit vs 96.22 Mbit Regards, Caglar > Assuming that the DMA got stuck at some point leading up to the transmit > timeout, any ideas as to why a host error was not thrown? To help > debug, I'll post out a set of patches that dump out the MAC (and DMA) > registers on timeout. That should give us some visibility into the > problem. > > > [ 1651.440000] nfs: server 192.168.2.34 not responding, still trying > > [ 1859.010000] ------------[ cut here ]------------ > > [ 1859.010000] WARNING: at net/sched/sch_generic.c:258 > > dev_watchdog+0x184/0x294() > > [ 1859.020000] NETDEV WATCHDOG: eth0 (davinci_emac): transmit queue 0 > > timed out > > [...] > > Regards > Cyril. > From caglarakyuz at gmail.com Mon Sep 13 13:06:08 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Mon, 13 Sep 2010 21:06:08 +0300 Subject: [PATCH v4 1/2] davinci: Add generic PWM support for PWM control In-Reply-To: <201009102042.36977.caglarakyuz@gmail.com> References: <1284028849-16680-1-git-send-email-sugumar@ti.com> <201009102042.36977.caglarakyuz@gmail.com> Message-ID: <201009132106.08932.caglarakyuz@gmail.com> > Sugumar Natarajan wrote: >On Fri, Sep 10, 2010 at 23:12:36, Caglar Akyuz wrote: >> On Thursday 09 September 2010 01:40:49 pm Sugumar Natarajan wrote: >> > This patch adds generic PWM support where it maintains the list of PWM >> > control devices that can be added or removed. >> > >> > The interface provides a list of functions that can be accessed by the >> > PWM control driver module and the generic PWM driver. >> > >> > The PWM control driver module such as eCAP uses the interface to >> > register and add itself to the list as a PWM control device. >> > The generic PWM driver uses the interface to search for a PWM control >> > device and if present, uses the device for PWM control. >> > >> > Signed-off-by: Sugumar Natarajan >> > --- >> >> Hi, >> >> [...] >> >> > + >> > +int pwm_enable(struct pwm_device *pwm) { >> > + if (WARN_ON(!pwm)) >> > + return -EINVAL; >> > + >> > + return clk_enable(pwm->clk); >> > +} >> > +EXPORT_SYMBOL(pwm_enable); >> > + >> >> I think 'clk_enable' should be controlled for un-matched pwm_enable/disable >operation. Otherwise, disabling PWM won't shut down >peripheral clock. If I understand inner workings of DaVinci clock >implementation clock use_count is incremented with every >clk_enable. >> >> Regards, >> Caglar >> > >Caglar, > I could not understand what you mean by "un-match" .could you please >explain? >Regards, >N.sugumar List server didn't deliver this mail to me, I saw it from the archives. I mean something like this: int pwm_enable(struct pwm_device *pwm) { int rc = 0; if (WARN_ON(!pwm)) return -EINVAL; if (!pwm->clk_enabled) { rc = clk_enable(pwm->clk); if (!rc) pwm->clk_enabled = 1; } return rc; } The reason is 'pwm_enable' can be called over and over without 'pwm_disable' and vice versa. For instance, every time backlight value is changed, pwm_enable is called by the backlight framework. Regards, Caglar From cyril at ti.com Mon Sep 13 13:07:23 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 14:07:23 -0400 Subject: [PATCH 1/9] net: davinci_emac: allow forced 100/full via phy_id In-Reply-To: <1284401251-8846-1-git-send-email-cyril@ti.com> References: <1284401251-8846-1-git-send-email-cyril@ti.com> Message-ID: <1284401251-8846-2-git-send-email-cyril@ti.com> With this patch, phy_id can be one of the following: 1) NULL : use the first phy on the bus, 2) "" : force to 100/full, no mdio control 3) ":" : use the specified bus and phy The ability to force 100/full is necessary on some platforms (e.g. da830 evm), where an on-board switch may be connected on the emac mii. Signed-off-by: Cyril Chemparathy Signed-off-by: Michael Williamson Signed-off-by: Caglar Akyuz --- drivers/net/davinci_emac.c | 2 +- include/linux/davinci_emac.h | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 525b84c..363c970 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -1566,7 +1566,7 @@ static int emac_dev_open(struct net_device *ndev) priv->phy_id = dev_name(phy); } - if (priv->phy_id) { + if (priv->phy_id && *priv->phy_id) { priv->phydev = phy_connect(ndev, priv->phy_id, &emac_adjust_link, 0, PHY_INTERFACE_MODE_MII); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index 7508e49..9ae9ff0 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -25,6 +25,13 @@ struct emac_platform_data { u32 ctrl_ram_offset; u32 hw_ram_addr; u32 ctrl_ram_size; + + /* + * phy_id can be one of the following: + * - NULL : use the first phy on the bus, + * - "" : force to 100/full, no mdio control + * - ":" : use the specified bus and phy + */ const char *phy_id; u8 rmii_en; u8 version; -- 1.7.0.4 From cyril at ti.com Mon Sep 13 13:07:26 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 14:07:26 -0400 Subject: [PATCH 4/9] net: davinci_emac: fix rx error handling In-Reply-To: <1284401251-8846-1-git-send-email-cyril@ti.com> References: <1284401251-8846-1-git-send-email-cyril@ti.com> Message-ID: <1284401251-8846-5-git-send-email-cyril@ti.com> This patch adds the following fixes to the emac receive handler: 1. WARN_ON during interface shutdown. Although harmless, these complaints were quite disconcerting. With this patch, the receive handler explicitly checks for the shutdown condition, in which case is bails quietly. 2. Update rx_error stats on dma receive error 3. Rate limit error messages on buffer allocation failures Signed-off-by: Cyril Chemparathy Signed-off-by: Michael Williamson Signed-off-by: Caglar Akyuz --- drivers/net/davinci_emac.c | 25 +++++++++++++++++++------ 1 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 363c970..9e866ae 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -1002,13 +1002,22 @@ static void emac_rx_handler(void *token, int len, int status) struct sk_buff *skb = token; struct net_device *ndev = skb->dev; struct emac_priv *priv = netdev_priv(ndev); + struct device *emac_dev = &ndev->dev; int ret; + /* free and bail if we are shutting down */ + if (unlikely(!netif_running(ndev))) { + dev_kfree_skb_any(skb); + return; + } + + /* recycle on recieve error */ if (status < 0) { - /* error */ + ndev->stats.rx_errors++; goto recycle; } + /* feed received packet up the stack */ skb_put(skb, len); skb->protocol = eth_type_trans(skb, ndev); netif_receive_skb(skb); @@ -1017,13 +1026,17 @@ static void emac_rx_handler(void *token, int len, int status) /* alloc a new packet for receive */ skb = emac_rx_alloc(priv); + if (!skb) { + if (netif_msg_rx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "failed rx buffer alloc\n"); + return; + } recycle: - if (skb) { - ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, - skb_tailroom(skb), GFP_KERNEL); - WARN_ON(ret < 0); - } + ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, + skb_tailroom(skb), GFP_KERNEL); + if (WARN_ON(ret < 0)) + dev_kfree_skb_any(skb); } static void emac_tx_handler(void *token, int len, int status) -- 1.7.0.4 From cyril at ti.com Mon Sep 13 13:07:25 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 14:07:25 -0400 Subject: [PATCH 3/9] net: davinci_cpdma: requeue on early end-of-queue In-Reply-To: <1284401251-8846-1-git-send-email-cyril@ti.com> References: <1284401251-8846-1-git-send-email-cyril@ti.com> Message-ID: <1284401251-8846-4-git-send-email-cyril@ti.com> When chaining descriptors to the end of a cpdma queue, there is a chance that the cpdma engine has already traversed the last descriptor and signalled an end-of-queue. The original cpdma code detected this condition and requeued descriptors on submission. With this patch, an early end-of-queue condition is detected on descriptor submission as well. This is necessary on davinci style emac controllers, and prevents transmit timeouts when sending out a burst of packets. Signed-off-by: Cyril Chemparathy Signed-off-by: Michael Williamson Signed-off-by: Caglar Akyuz --- drivers/net/davinci_cpdma.c | 12 ++++++++++-- drivers/net/davinci_cpdma.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c index ab7ecd7..abc2b14 100644 --- a/drivers/net/davinci_cpdma.c +++ b/drivers/net/davinci_cpdma.c @@ -488,6 +488,7 @@ static void __cpdma_chan_submit(struct cpdma_chan *chan, struct cpdma_desc __iomem *prev = chan->tail; struct cpdma_desc_pool *pool = ctlr->pool; dma_addr_t desc_dma; + u32 mode; desc_dma = desc_phys(pool, desc); @@ -507,8 +508,10 @@ static void __cpdma_chan_submit(struct cpdma_chan *chan, chan->stats.tail_enqueue++; /* next check if EOQ has been triggered already */ - if (desc_read(prev, hw_mode) & CPDMA_DESC_EOQ && - chan->state == CPDMA_STATE_ACTIVE) { + mode = desc_read(prev, hw_mode); + if (((mode & (CPDMA_DESC_EOQ | CPDMA_DESC_OWNER)) == CPDMA_DESC_EOQ) && + (chan->state == CPDMA_STATE_ACTIVE)) { + desc_write(prev, hw_mode, mode & ~CPDMA_DESC_EOQ); chan_write(chan, hdp, desc_dma); chan->stats.misqueued++; } @@ -618,6 +621,11 @@ static int __cpdma_chan_process(struct cpdma_chan *chan) chan->count--; chan->stats.good_dequeue++; + if (status & CPDMA_DESC_EOQ) { + chan->stats.requeue++; + chan_write(chan, hdp, desc_phys(pool, chan->head)); + } + spin_unlock_irqrestore(&chan->lock, flags); __cpdma_chan_free(chan, desc, outlen, status); diff --git a/drivers/net/davinci_cpdma.h b/drivers/net/davinci_cpdma.h index d50ee35..9baacca 100644 --- a/drivers/net/davinci_cpdma.h +++ b/drivers/net/davinci_cpdma.h @@ -56,6 +56,7 @@ struct cpdma_chan_stats { u32 empty_dequeue; u32 busy_dequeue; u32 good_dequeue; + u32 requeue; u32 teardown_dequeue; }; -- 1.7.0.4 From cyril at ti.com Mon Sep 13 13:07:22 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 14:07:22 -0400 Subject: [PATCH 0/9] post cpdma/mdio refactoring fixes Message-ID: <1284401251-8846-1-git-send-email-cyril@ti.com> This series consists of fixes for issues found during broader testing of the davinci cpdma/mdio separation series. The fixes included here are: 1. Ability to force 100/full rather than auto-detect phy. This is necessary for the external switch on the da830 evm platform 2. Fix end-of-queue requeue to include checks at submission time (in addition to pre-existing completion time checks). 3. Cleanups to rx path error handling. This prevents unnecessary stack dumps for perfectly legal situations. 4. Work around for emac-soft-reset tie-up to mdio controller. This affects all da8xx family devices (and possibly am35xx as well). 5. Reworked hard-coded scan-time estimate to use a more accurate calculated number instead. 6. Code to generate cpdma register dumps, useful during debug. Many thanks to Mike and Caglar for patiently working with me through these issues, I've taken the liberty of adding their sign offs. Cyril Chemparathy (9): net: davinci_emac: allow forced 100/full via phy_id davinci: specify phy_id rather than auto-detect net: davinci_cpdma: requeue on early end-of-queue net: davinci_emac: fix rx error handling net: davinci_mdio: separate out controller reset net: davinci_mdio: use calculated bus access times net: davinci_mdio: work around emac soft-reset during i/o net: davinci_cpdma: add register dump routines net: davinci_emac: extended register dumps on tx timeout arch/arm/mach-davinci/board-da830-evm.c | 2 + arch/arm/mach-davinci/board-da850-evm.c | 3 + arch/arm/mach-davinci/board-dm365-evm.c | 4 + arch/arm/mach-davinci/board-dm644x-evm.c | 3 + arch/arm/mach-davinci/board-dm646x-evm.c | 5 + arch/arm/mach-davinci/board-mityomapl138.c | 3 + arch/arm/mach-davinci/board-neuros-osd2.c | 4 + arch/arm/mach-davinci/board-sffsdr.c | 4 + drivers/net/davinci_cpdma.c | 132 ++++++++++++++++++- drivers/net/davinci_cpdma.h | 3 + drivers/net/davinci_emac.c | 31 ++++- drivers/net/davinci_mdio.c | 195 ++++++++++++++++++++-------- include/linux/davinci_emac.h | 7 + 13 files changed, 334 insertions(+), 62 deletions(-) From cyril at ti.com Mon Sep 13 13:07:24 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 14:07:24 -0400 Subject: [PATCH 2/9] davinci: specify phy_id rather than auto-detect In-Reply-To: <1284401251-8846-1-git-send-email-cyril@ti.com> References: <1284401251-8846-1-git-send-email-cyril@ti.com> Message-ID: <1284401251-8846-3-git-send-email-cyril@ti.com> The cpdma/mdio refactoring incorrectly defaulted to using the first phy detected on the platform. Although auto detection works on most sane platforms, it can prove to be problematic on some. For example, the da830/omap-l137 evm has an on-board switch that always connects 100/full. Consequently, normal phy auto-detection does not work on this platform. Rather than risk breaking other boards, this patch reverts to using hard-coded phy ids on platforms that did so earlier. Signed-off-by: Cyril Chemparathy Signed-off-by: Michael Williamson Signed-off-by: Caglar Akyuz --- arch/arm/mach-davinci/board-da830-evm.c | 2 ++ arch/arm/mach-davinci/board-da850-evm.c | 3 +++ arch/arm/mach-davinci/board-dm365-evm.c | 4 ++++ arch/arm/mach-davinci/board-dm644x-evm.c | 3 +++ arch/arm/mach-davinci/board-dm646x-evm.c | 5 +++++ arch/arm/mach-davinci/board-mityomapl138.c | 3 +++ arch/arm/mach-davinci/board-neuros-osd2.c | 4 ++++ arch/arm/mach-davinci/board-sffsdr.c | 4 ++++ 8 files changed, 28 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index 2613324..1bb89d3 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -31,6 +31,7 @@ #include #include +#define DA830_EVM_PHY_ID "" /* * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4]. */ @@ -556,6 +557,7 @@ static __init void da830_evm_init(void) da830_evm_usb_init(); soc_info->emac_pdata->rmii_en = 1; + soc_info->emac_pdata->phy_id = DA830_EVM_PHY_ID; ret = davinci_cfg_reg_list(da830_cpgmac_pins); if (ret) diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 9d4dfcb..5e435b0 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -38,6 +38,7 @@ #include #include +#define DA850_EVM_PHY_ID "0:00" #define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8) #define DA850_LCD_BL_PIN GPIO_TO_PIN(2, 15) @@ -675,6 +676,8 @@ static int __init da850_evm_config_emac(void) /* Enable/Disable MII MDIO clock */ gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en); + soc_info->emac_pdata->phy_id = DA850_EVM_PHY_ID; + ret = da8xx_register_emac(); if (ret) pr_warning("da850_evm_init: emac registration failed: %d\n", diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index f697914..86d9abc 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -54,6 +54,7 @@ static inline int have_tvp7002(void) return 0; } +#define DM365_EVM_PHY_ID "0:01" /* * A MAX-II CPLD is used for various board control functions. */ @@ -527,12 +528,15 @@ fail: /* externally mux MMC1/ENET/AIC33 to imager */ mux |= BIT(6) | BIT(5) | BIT(3); } else { + struct davinci_soc_info *soc_info = &davinci_soc_info; + /* we can use MMC1 ... */ dm365evm_mmc_configure(); davinci_setup_mmc(1, &dm365evm_mmc_config); /* ... and ENET ... */ dm365evm_emac_configure(); + soc_info->emac_pdata->phy_id = DM365_EVM_PHY_ID; resets &= ~BIT(3); /* ... and AIC33 */ diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index c86bf23..44a2f0a 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -39,6 +39,7 @@ #include #include +#define DM644X_EVM_PHY_ID "0:01" #define LXT971_PHY_ID (0x001378e2) #define LXT971_PHY_MASK (0xfffffff0) @@ -669,6 +670,7 @@ static int davinci_phy_fixup(struct phy_device *phydev) static __init void davinci_evm_init(void) { struct clk *aemif_clk; + struct davinci_soc_info *soc_info = &davinci_soc_info; aemif_clk = clk_get(NULL, "aemif"); clk_enable(aemif_clk); @@ -703,6 +705,7 @@ static __init void davinci_evm_init(void) davinci_serial_init(&uart_config); dm644x_init_asp(&dm644x_evm_snd_data); + soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID; /* Register the fixup for PHY on DaVinci */ phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK, davinci_phy_fixup); diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 3f34221..67669bb 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -729,6 +729,7 @@ static struct davinci_uart_config uart_config __initdata = { .enabled_uarts = (1 << 0), }; +#define DM646X_EVM_PHY_ID "0:01" /* * The following EDMA channels/slots are not being used by drivers (for * example: Timer, GPIO, UART events etc) on dm646x, hence they are being @@ -764,6 +765,8 @@ static struct edma_rsv_info dm646x_edma_rsv[] = { static __init void evm_init(void) { + struct davinci_soc_info *soc_info = &davinci_soc_info; + evm_init_i2c(); davinci_serial_init(&uart_config); dm646x_init_mcasp0(&dm646x_evm_snd_data[0]); @@ -778,6 +781,8 @@ static __init void evm_init(void) if (HAS_ATA) davinci_init_ide(); + + soc_info->emac_pdata->phy_id = DM646X_EVM_PHY_ID; } #define DM646X_EVM_REF_FREQ 27000000 diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index e872fcc..6f12a18 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -24,6 +24,7 @@ #include #include +#define MITYOMAPL138_PHY_ID "0:03" static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = { .bus_freq = 100, /* kHz */ .bus_delay = 0, /* usec */ @@ -270,6 +271,8 @@ static void __init mityomapl138_config_emac(void) /* configure the CFGCHIP3 register for RMII or MII */ __raw_writel(val, cfg_chip3_base); + soc_info->emac_pdata->phy_id = MITYOMAPL138_PHY_ID; + ret = da8xx_register_emac(); if (ret) pr_warning("emac registration failed: %d\n", ret); diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index 4b32f0a..04a8d16 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -39,6 +39,7 @@ #include #include +#define NEUROS_OSD2_PHY_ID "0:01" #define LXT971_PHY_ID 0x001378e2 #define LXT971_PHY_MASK 0xfffffff0 @@ -215,6 +216,7 @@ static struct davinci_mmc_config davinci_ntosd2_mmc_config = { static __init void davinci_ntosd2_init(void) { struct clk *aemif_clk; + struct davinci_soc_info *soc_info = &davinci_soc_info; int status; aemif_clk = clk_get(NULL, "aemif"); @@ -248,6 +250,8 @@ static __init void davinci_ntosd2_init(void) davinci_serial_init(&uart_config); dm644x_init_asp(&dm644x_ntosd2_snd_data); + soc_info->emac_pdata->phy_id = NEUROS_OSD2_PHY_ID; + davinci_setup_usb(1000, 8); /* * Mux the pins to be GPIOs, VLYNQEN is already done at startup. diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index b372d7f..ab4292d 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -42,6 +42,7 @@ #include #include +#define SFFSDR_PHY_ID "0:01" static struct mtd_partition davinci_sffsdr_nandflash_partition[] = { /* U-Boot Environment: Block 0 * UBL: Block 1 @@ -134,10 +135,13 @@ static void __init davinci_sffsdr_map_io(void) static __init void davinci_sffsdr_init(void) { + struct davinci_soc_info *soc_info = &davinci_soc_info; + platform_add_devices(davinci_sffsdr_devices, ARRAY_SIZE(davinci_sffsdr_devices)); sffsdr_init_i2c(); davinci_serial_init(&uart_config); + soc_info->emac_pdata->phy_id = SFFSDR_PHY_ID; davinci_setup_usb(0, 0); /* We support only peripheral mode. */ /* mux VLYNQ pins */ -- 1.7.0.4 From cyril at ti.com Mon Sep 13 13:07:29 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 14:07:29 -0400 Subject: [PATCH 7/9] net: davinci_mdio: work around emac soft-reset during i/o In-Reply-To: <1284401251-8846-1-git-send-email-cyril@ti.com> References: <1284401251-8846-1-git-send-email-cyril@ti.com> Message-ID: <1284401251-8846-8-git-send-email-cyril@ti.com> On certain devices (e.g. da8xx), the hardware design ties emac soft-reset to the mdio module. In these cases, when the emac device is opened, an in-flight mdio transaction could fail by returning the controller to idle state. This patch detects this condition and works around it by retrying the failed transaction. In addition, defensive timeouts have been added to prevent an indefinite lockup in case of an unexpected hardware error. Signed-off-by: Cyril Chemparathy Signed-off-by: Michael Williamson Signed-off-by: Caglar Akyuz --- drivers/net/davinci_mdio.c | 92 ++++++++++++++++++++++++++++++++++++------- 1 files changed, 77 insertions(+), 15 deletions(-) diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c index f2d7639..7615040 100644 --- a/drivers/net/davinci_mdio.c +++ b/drivers/net/davinci_mdio.c @@ -36,6 +36,13 @@ #include #include +/* + * This timeout definition is a worst-case ultra defensive measure against + * unexpected controller lock ups. Ideally, we should never ever hit this + * scenario in practice. + */ +#define MDIO_TIMEOUT 100 /* msecs */ + #define PHY_REG_MASK 0x1f #define PHY_ID_MASK 0x1f @@ -150,30 +157,53 @@ static int davinci_mdio_reset(struct mii_bus *bus) } /* wait until hardware is ready for another user access */ -static inline u32 wait_for_user_access(struct davinci_mdio_data *data) +static inline int wait_for_user_access(struct davinci_mdio_data *data) { struct davinci_mdio_regs __iomem *regs = data->regs; + unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT); u32 reg; - while ((reg = __raw_readl(®s->user[0].access)) & USERACCESS_GO) - ; - - return reg; + while (time_after(timeout, jiffies)) { + reg = __raw_readl(®s->user[0].access); + if ((reg & USERACCESS_GO) == 0) + return 0; + + reg = __raw_readl(®s->control); + if ((reg & CONTROL_IDLE) == 0) + continue; + + /* + * An emac soft_reset may have clobbered the mdio controller's + * state machine. We need to reset and retry the current + * operation + */ + dev_warn(data->dev, "resetting idled controller\n"); + __davinci_mdio_reset(data); + return -EAGAIN; + } + dev_err(data->dev, "timed out waiting for user access\n"); + return -ETIMEDOUT; } /* wait until hardware state machine is idle */ -static inline void wait_for_idle(struct davinci_mdio_data *data) +static inline int wait_for_idle(struct davinci_mdio_data *data) { struct davinci_mdio_regs __iomem *regs = data->regs; + unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT); - while ((__raw_readl(®s->control) & CONTROL_IDLE) == 0) - ; + while (time_after(timeout, jiffies)) { + if (__raw_readl(®s->control) & CONTROL_IDLE) + return 0; + } + dev_err(data->dev, "timed out waiting for idle\n"); + return -ETIMEDOUT; } static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg) { struct davinci_mdio_data *data = bus->priv; u32 reg; + int ret; if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) return -EINVAL; @@ -185,14 +215,32 @@ static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg) return -ENODEV; } - wait_for_user_access(data); reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) | (phy_id << 16)); - __raw_writel(reg, &data->regs->user[0].access); - reg = wait_for_user_access(data); + + while (1) { + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + if (ret < 0) + break; + + __raw_writel(reg, &data->regs->user[0].access); + + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + if (ret < 0) + break; + + reg = __raw_readl(&data->regs->user[0].access); + ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO; + break; + } + spin_unlock(&data->lock); - return (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO; + return ret; } static int davinci_mdio_write(struct mii_bus *bus, int phy_id, @@ -200,6 +248,7 @@ static int davinci_mdio_write(struct mii_bus *bus, int phy_id, { struct davinci_mdio_data *data = bus->priv; u32 reg; + int ret; if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) return -EINVAL; @@ -211,11 +260,24 @@ static int davinci_mdio_write(struct mii_bus *bus, int phy_id, return -ENODEV; } - wait_for_user_access(data); reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) | (phy_id << 16) | (phy_data & USERACCESS_DATA)); - __raw_writel(reg, &data->regs->user[0].access); - wait_for_user_access(data); + + while (1) { + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + if (ret < 0) + break; + + __raw_writel(reg, &data->regs->user[0].access); + + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + break; + } + spin_unlock(&data->lock); return 0; -- 1.7.0.4 From cyril at ti.com Mon Sep 13 13:07:30 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 14:07:30 -0400 Subject: [PATCH 8/9] net: davinci_cpdma: add register dump routines In-Reply-To: <1284401251-8846-1-git-send-email-cyril@ti.com> References: <1284401251-8846-1-git-send-email-cyril@ti.com> Message-ID: <1284401251-8846-9-git-send-email-cyril@ti.com> This patch adds register dump routines at both controller and channel levels. These are intended to be used in higher level driver debug dumps, e.g. emac_dump_regs(). Signed-off-by: Cyril Chemparathy Signed-off-by: Michael Williamson Signed-off-by: Caglar Akyuz --- drivers/net/davinci_cpdma.c | 120 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/davinci_cpdma.h | 2 + 2 files changed, 122 insertions(+), 0 deletions(-) diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c index abc2b14..e92b2b6 100644 --- a/drivers/net/davinci_cpdma.c +++ b/drivers/net/davinci_cpdma.c @@ -91,6 +91,8 @@ enum cpdma_state { CPDMA_STATE_TEARDOWN, }; +const char *cpdma_state_str[] = { "idle", "active", "teardown" }; + struct cpdma_ctlr { enum cpdma_state state; struct cpdma_params params; @@ -345,6 +347,76 @@ int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr) return 0; } +int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr) +{ + struct device *dev = ctlr->dev; + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + + dev_info(dev, "CPDMA: state: %s", cpdma_state_str[ctlr->state]); + + dev_info(dev, "CPDMA: txidver: %x", + dma_reg_read(ctlr, CPDMA_TXIDVER)); + dev_info(dev, "CPDMA: txcontrol: %x", + dma_reg_read(ctlr, CPDMA_TXCONTROL)); + dev_info(dev, "CPDMA: txteardown: %x", + dma_reg_read(ctlr, CPDMA_TXTEARDOWN)); + dev_info(dev, "CPDMA: rxidver: %x", + dma_reg_read(ctlr, CPDMA_RXIDVER)); + dev_info(dev, "CPDMA: rxcontrol: %x", + dma_reg_read(ctlr, CPDMA_RXCONTROL)); + dev_info(dev, "CPDMA: softreset: %x", + dma_reg_read(ctlr, CPDMA_SOFTRESET)); + dev_info(dev, "CPDMA: rxteardown: %x", + dma_reg_read(ctlr, CPDMA_RXTEARDOWN)); + dev_info(dev, "CPDMA: txintstatraw: %x", + dma_reg_read(ctlr, CPDMA_TXINTSTATRAW)); + dev_info(dev, "CPDMA: txintstatmasked: %x", + dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED)); + dev_info(dev, "CPDMA: txintmaskset: %x", + dma_reg_read(ctlr, CPDMA_TXINTMASKSET)); + dev_info(dev, "CPDMA: txintmaskclear: %x", + dma_reg_read(ctlr, CPDMA_TXINTMASKCLEAR)); + dev_info(dev, "CPDMA: macinvector: %x", + dma_reg_read(ctlr, CPDMA_MACINVECTOR)); + dev_info(dev, "CPDMA: maceoivector: %x", + dma_reg_read(ctlr, CPDMA_MACEOIVECTOR)); + dev_info(dev, "CPDMA: rxintstatraw: %x", + dma_reg_read(ctlr, CPDMA_RXINTSTATRAW)); + dev_info(dev, "CPDMA: rxintstatmasked: %x", + dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED)); + dev_info(dev, "CPDMA: rxintmaskset: %x", + dma_reg_read(ctlr, CPDMA_RXINTMASKSET)); + dev_info(dev, "CPDMA: rxintmaskclear: %x", + dma_reg_read(ctlr, CPDMA_RXINTMASKCLEAR)); + dev_info(dev, "CPDMA: dmaintstatraw: %x", + dma_reg_read(ctlr, CPDMA_DMAINTSTATRAW)); + dev_info(dev, "CPDMA: dmaintstatmasked: %x", + dma_reg_read(ctlr, CPDMA_DMAINTSTATMASKED)); + dev_info(dev, "CPDMA: dmaintmaskset: %x", + dma_reg_read(ctlr, CPDMA_DMAINTMASKSET)); + dev_info(dev, "CPDMA: dmaintmaskclear: %x", + dma_reg_read(ctlr, CPDMA_DMAINTMASKCLEAR)); + + if (!ctlr->params.has_ext_regs) { + dev_info(dev, "CPDMA: dmacontrol: %x", + dma_reg_read(ctlr, CPDMA_DMACONTROL)); + dev_info(dev, "CPDMA: dmastatus: %x", + dma_reg_read(ctlr, CPDMA_DMASTATUS)); + dev_info(dev, "CPDMA: rxbuffofs: %x", + dma_reg_read(ctlr, CPDMA_RXBUFFOFS)); + } + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) + if (ctlr->channels[i]) + cpdma_chan_dump(ctlr->channels[i]); + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr) { unsigned long flags; @@ -481,6 +553,54 @@ int cpdma_chan_get_stats(struct cpdma_chan *chan, return 0; } +int cpdma_chan_dump(struct cpdma_chan *chan) +{ + unsigned long flags; + struct device *dev = chan->ctlr->dev; + + spin_lock_irqsave(&chan->lock, flags); + + dev_info(dev, "channel %d (%s %d) state %s", + chan->chan_num, is_rx_chan(chan) ? "rx" : "tx", + chan_linear(chan), cpdma_state_str[chan->state]); + dev_info(dev, "\thdp: %x\n", chan_read(chan, hdp)); + dev_info(dev, "\tcp: %x\n", chan_read(chan, cp)); + if (chan->rxfree) { + dev_info(dev, "\trxfree: %x\n", + chan_read(chan, rxfree)); + } + + dev_info(dev, "\tstats head_enqueue: %d\n", + chan->stats.head_enqueue); + dev_info(dev, "\tstats tail_enqueue: %d\n", + chan->stats.tail_enqueue); + dev_info(dev, "\tstats pad_enqueue: %d\n", + chan->stats.pad_enqueue); + dev_info(dev, "\tstats misqueued: %d\n", + chan->stats.misqueued); + dev_info(dev, "\tstats desc_alloc_fail: %d\n", + chan->stats.desc_alloc_fail); + dev_info(dev, "\tstats pad_alloc_fail: %d\n", + chan->stats.pad_alloc_fail); + dev_info(dev, "\tstats runt_receive_buff: %d\n", + chan->stats.runt_receive_buff); + dev_info(dev, "\tstats runt_transmit_buff: %d\n", + chan->stats.runt_transmit_buff); + dev_info(dev, "\tstats empty_dequeue: %d\n", + chan->stats.empty_dequeue); + dev_info(dev, "\tstats busy_dequeue: %d\n", + chan->stats.busy_dequeue); + dev_info(dev, "\tstats good_dequeue: %d\n", + chan->stats.good_dequeue); + dev_info(dev, "\tstats requeue: %d\n", + chan->stats.requeue); + dev_info(dev, "\tstats teardown_dequeue: %d\n", + chan->stats.teardown_dequeue); + + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + static void __cpdma_chan_submit(struct cpdma_chan *chan, struct cpdma_desc __iomem *desc) { diff --git a/drivers/net/davinci_cpdma.h b/drivers/net/davinci_cpdma.h index 9baacca..868e50e 100644 --- a/drivers/net/davinci_cpdma.h +++ b/drivers/net/davinci_cpdma.h @@ -69,12 +69,14 @@ struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params); int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr); int cpdma_ctlr_start(struct cpdma_ctlr *ctlr); int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr); struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, cpdma_handler_fn handler); int cpdma_chan_destroy(struct cpdma_chan *chan); int cpdma_chan_start(struct cpdma_chan *chan); int cpdma_chan_stop(struct cpdma_chan *chan); +int cpdma_chan_dump(struct cpdma_chan *chan); int cpdma_chan_get_stats(struct cpdma_chan *chan, struct cpdma_chan_stats *stats); -- 1.7.0.4 From cyril at ti.com Mon Sep 13 13:07:28 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 14:07:28 -0400 Subject: [PATCH 6/9] net: davinci_mdio: use calculated bus access times In-Reply-To: <1284401251-8846-1-git-send-email-cyril@ti.com> References: <1284401251-8846-1-git-send-email-cyril@ti.com> Message-ID: <1284401251-8846-7-git-send-email-cyril@ti.com> This patch replaces the hardcoded scan delay with a calculated delay that adjusts to clock rates. This delay is calculated on the basis of a worst case bus transaction time, with generous built-in margins of error. Signed-off-by: Cyril Chemparathy Signed-off-by: Michael Williamson Signed-off-by: Caglar Akyuz --- drivers/net/davinci_mdio.c | 33 +++++++++++++++++++++++---------- 1 files changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c index a9fbc26..f2d7639 100644 --- a/drivers/net/davinci_mdio.c +++ b/drivers/net/davinci_mdio.c @@ -83,11 +83,12 @@ struct davinci_mdio_data { struct device *dev; struct mii_bus *bus; bool suspended; + unsigned long access_time; /* jiffies */ }; static void __davinci_mdio_reset(struct davinci_mdio_data *data) { - u32 mdio_in, div; + u32 mdio_in, div, mdio_out_khz, access_time; mdio_in = clk_get_rate(data->clk); div = (mdio_in / data->pdata.bus_freq) - 1; @@ -96,6 +97,25 @@ static void __davinci_mdio_reset(struct davinci_mdio_data *data) /* set enable and clock divider */ __raw_writel(div | CONTROL_ENABLE, &data->regs->control); + + /* + * One mdio transaction consists of: + * 32 bits of preamble + * 32 bits of transferred data + * 24 bits of bus yield (not needed unless shared?) + */ + mdio_out_khz = mdio_in / (1000 * (div + 1)); + access_time = (88 * 1000) / mdio_out_khz; + + /* + * In the worst case, we could be kicking off a user-access immediately + * after the mdio bus scan state-machine triggered its own read. If + * so, our request could get deferred by one access cycle. We + * defensively allow for 4 access cycles. + */ + data->access_time = usecs_to_jiffies(access_time * 4); + if (!data->access_time) + data->access_time = 1; } static int davinci_mdio_reset(struct mii_bus *bus) @@ -105,15 +125,8 @@ static int davinci_mdio_reset(struct mii_bus *bus) __davinci_mdio_reset(data); - /* - * wait for scan logic to settle: - * the scan time consists of (a) a large fixed component, and (b) a - * small component that varies with the mii bus frequency. These - * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x - * silicon. Since the effect of (b) was found to be largely - * negligible, we keep things simple here. - */ - mdelay(1); + /* wait for scan logic to settle */ + msleep(PHY_MAX_ADDR * data->access_time); /* dump hardware version info */ ver = __raw_readl(&data->regs->version); -- 1.7.0.4 From cyril at ti.com Mon Sep 13 13:07:27 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 14:07:27 -0400 Subject: [PATCH 5/9] net: davinci_mdio: separate out controller reset In-Reply-To: <1284401251-8846-1-git-send-email-cyril@ti.com> References: <1284401251-8846-1-git-send-email-cyril@ti.com> Message-ID: <1284401251-8846-6-git-send-email-cyril@ti.com> This patch separates out the controller reset logic, and makes this available via mii_bus->reset. Signed-off-by: Cyril Chemparathy Signed-off-by: Michael Williamson Signed-off-by: Caglar Akyuz --- drivers/net/davinci_mdio.c | 90 +++++++++++++++++++++++++------------------ 1 files changed, 52 insertions(+), 38 deletions(-) diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c index d34a53a..a9fbc26 100644 --- a/drivers/net/davinci_mdio.c +++ b/drivers/net/davinci_mdio.c @@ -85,6 +85,57 @@ struct davinci_mdio_data { bool suspended; }; +static void __davinci_mdio_reset(struct davinci_mdio_data *data) +{ + u32 mdio_in, div; + + mdio_in = clk_get_rate(data->clk); + div = (mdio_in / data->pdata.bus_freq) - 1; + if (div > CONTROL_MAX_DIV) + div = CONTROL_MAX_DIV; + + /* set enable and clock divider */ + __raw_writel(div | CONTROL_ENABLE, &data->regs->control); +} + +static int davinci_mdio_reset(struct mii_bus *bus) +{ + struct davinci_mdio_data *data = bus->priv; + u32 phy_mask, ver; + + __davinci_mdio_reset(data); + + /* + * wait for scan logic to settle: + * the scan time consists of (a) a large fixed component, and (b) a + * small component that varies with the mii bus frequency. These + * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x + * silicon. Since the effect of (b) was found to be largely + * negligible, we keep things simple here. + */ + mdelay(1); + + /* dump hardware version info */ + ver = __raw_readl(&data->regs->version); + dev_info(data->dev, "davinci mdio revision %d.%d\n", + (ver >> 8) & 0xff, ver & 0xff); + + /* get phy mask from the alive register */ + phy_mask = __raw_readl(&data->regs->alive); + if (phy_mask) { + /* restrict mdio bus to live phys only */ + dev_info(data->dev, "detected phy mask %x\n", ~phy_mask); + phy_mask = ~phy_mask; + } else { + /* desperately scan all phys */ + dev_warn(data->dev, "no live phy, scanning all\n"); + phy_mask = 0; + } + data->bus->phy_mask = phy_mask; + + return 0; +} + /* wait until hardware is ready for another user access */ static inline u32 wait_for_user_access(struct davinci_mdio_data *data) { @@ -163,7 +214,6 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct davinci_mdio_data *data; struct resource *res; - u32 mdio_in_freq, mdio_out_freq, div, phy_mask, ver; struct phy_device *phy; int ret, addr; @@ -185,6 +235,7 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev) data->bus->name = dev_name(dev); data->bus->read = davinci_mdio_read, data->bus->write = davinci_mdio_write, + data->bus->reset = davinci_mdio_reset, data->bus->parent = dev; data->bus->priv = data; snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); @@ -225,43 +276,6 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev) goto bail_out; } - mdio_in_freq = clk_get_rate(data->clk); - div = (mdio_in_freq / data->pdata.bus_freq) - 1; - if (div > CONTROL_MAX_DIV) - div = CONTROL_MAX_DIV; - mdio_out_freq = mdio_in_freq / (div + 1); - - /* set enable and clock divider */ - __raw_writel(div | CONTROL_ENABLE, &data->regs->control); - - /* - * wait for scan logic to settle: - * the scan time consists of (a) a large fixed component, and (b) a - * small component that varies with the mii bus frequency. These - * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x - * silicon. Since the effect of (b) was found to be largely - * negligible, we keep things simple here. - */ - mdelay(1); - - /* dump hardware version info */ - ver = __raw_readl(&data->regs->version); - dev_info(dev, "davinci mdio revision %d.%d\n", - (ver >> 8) & 0xff, ver & 0xff); - - /* get phy mask from the alive register */ - phy_mask = __raw_readl(&data->regs->alive); - if (phy_mask) { - /* restrict mdio bus to live phys only */ - dev_info(dev, "detected phy mask %x\n", ~phy_mask); - phy_mask = ~phy_mask; - } else { - /* desperately scan all phys */ - dev_warn(dev, "failed to detect live phys, scanning all\n"); - phy_mask = 0; - } - data->bus->phy_mask = phy_mask; - /* register the mii bus */ ret = mdiobus_register(data->bus); if (ret) -- 1.7.0.4 From cyril at ti.com Mon Sep 13 13:07:31 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 13 Sep 2010 14:07:31 -0400 Subject: [PATCH 9/9] net: davinci_emac: extended register dumps on tx timeout In-Reply-To: <1284401251-8846-1-git-send-email-cyril@ti.com> References: <1284401251-8846-1-git-send-email-cyril@ti.com> Message-ID: <1284401251-8846-10-git-send-email-cyril@ti.com> This patch hooks up the emac_dump_regs() function to use cpdma dump routines. Further, we dump registers on transmit timeout, to make such timeouts debuggable. Signed-off-by: Cyril Chemparathy Signed-off-by: Michael Williamson Signed-off-by: Caglar Akyuz --- drivers/net/davinci_emac.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 9e866ae..2a628d1 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -460,6 +460,8 @@ static void emac_dump_regs(struct emac_priv *priv) emac_read(EMAC_RXMOFOVERRUNS)); dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n", emac_read(EMAC_RXDMAOVERRUNS)); + + cpdma_ctlr_dump(priv->dma); } /** @@ -1115,6 +1117,8 @@ static void emac_dev_tx_timeout(struct net_device *ndev) if (netif_msg_tx_err(priv)) dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX"); + emac_dump_regs(priv); + ndev->stats.tx_errors++; emac_int_disable(priv); cpdma_chan_stop(priv->txchan); -- 1.7.0.4 From locanosouvenir at gmail.com Fri Sep 10 21:10:43 2010 From: locanosouvenir at gmail.com (locanojakarta@yahoo.com) Date: Fri, 10 Sep 2010 19:10:43 -0700 Subject: Penawaran mouse, mouse pad dan flash drive In-Reply-To: References: Message-ID: Kami menerima pesanan: Mouse dan Flash Disk bisa sebagai souvenir perusahaan. Kapasitas Flash Disk = 64M sampai 16G hub kami untuk keterangan lebih lanjut. Terima kasih. locanojakarta at yahoo.com CORPORATE UNIFORM & MERCHANDISE Telp. 3731 9388 (Jakarta - Indonesia) -- Best Regards -- Best Regards -- Best Regards -- Best Regards -- Best Regards -- Best Regards -- Best Regards -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: hotsel 2.bmp Type: image/bmp Size: 484254 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: hotsel 3.bmp Type: image/bmp Size: 491454 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: hotsell 1.bmp Type: image/bmp Size: 442854 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 3489.bmp Type: image/bmp Size: 589878 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 2969.bmp Type: image/bmp Size: 712758 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 3223.bmp Type: image/bmp Size: 589878 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 3323.bmp Type: image/bmp Size: 768054 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 3341.bmp Type: image/bmp Size: 768054 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 3344.bmp Type: image/bmp Size: 692790 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 3433.bmp Type: image/bmp Size: 589878 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: JEWEL ITEMS.bmp Type: image/bmp Size: 589878 bytes Desc: not available URL: From balbi at ti.com Mon Sep 13 06:09:30 2010 From: balbi at ti.com (Felipe Balbi) Date: Mon, 13 Sep 2010 14:09:30 +0300 Subject: [PATCH] musb_gadget: restart request on clearing endpoint halt In-Reply-To: <201009112223.12768.sshtylyov@ru.mvista.com> References: <201009112223.12768.sshtylyov@ru.mvista.com> Message-ID: <20100913110930.GB30468@legolas.emea.dhcp.ti.com> On Sat, Sep 11, 2010 at 01:23:12PM -0500, Sergei Shtylyov wrote: >Commit 46034dca515bc4ddca0399ae58106d1f5f0d809f (USB: musb_gadget_ep0: stop >abusing musb_gadget_set_halt()) forgot to add in the code to restart a queued >request to the code handling clearing the endpoint halt. This results in a >couple of USB resets while enumerating the file-backed storage gadget due to >CSW packet not being sent for the MODE SENSE(10) command. > >Signed-off-by: Sergei Shtylyov >Cc: stable at kernel.org applied, thanks -- balbi From yanir.lubetkin at galilsoft.com Mon Sep 13 17:57:07 2010 From: yanir.lubetkin at galilsoft.com (Yanir Lubetkin) Date: Tue, 14 Sep 2010 00:57:07 +0200 Subject: mt9p031 driver for dm355 (for the latest arago staging 2.6.32 tree) Message-ID: <4C8EAC43.9050805@galilsoft.com> Hi The patch below was tested against the following kernel: http://arago-project.org/git/projects/?p=linux-davinci.git;a=commit;h=0a9d0bc0057964ba667de67395ba5de0447d23b2 The driver supports the full speeds as advertised by micron From e282f467860f58a5b32081521f5219a7de333f99 Mon Sep 17 00:00:00 2001 From: Yanir Lubetkin Date: Mon, 13 Sep 2010 13:51:47 +0200 Subject: [PATCH] mt9p031 support for dm355-evm --- arch/arm/mach-davinci/board-dm355-evm.c | 49 ++- drivers/media/video/Kconfig | 10 + drivers/media/video/Makefile | 1 + drivers/media/video/davinci/vpfe_capture.c | 2 +- drivers/media/video/mt9p031.c | 834 ++++++++++++++++++++++++++++ drivers/mfd/dm355evm_msp.c | 12 +- include/media/davinci/vpfe_capture.h | 1 + include/media/v4l2-chip-ident.h | 3 + 8 files changed, 902 insertions(+), 10 deletions(-) create mode 100644 drivers/media/video/mt9p031.c diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c index 5d3946e..dd329dd 100644 --- a/arch/arm/mach-davinci/board-dm355-evm.c +++ b/arch/arm/mach-davinci/board-dm355-evm.c @@ -179,9 +179,11 @@ static struct i2c_board_info dm355evm_i2c_info[] = { { I2C_BOARD_INFO("dm355evm_msp", 0x25), .platform_data = dm355evm_mmcsd_gpios, }, +#if defined(CONFIG_SOC_CAMERA_MT9T031) { I2C_BOARD_INFO("PCA9543A", 0x73), }, +#endif /* { plus irq }, */ { I2C_BOARD_INFO("tlv320aic33", 0x1b), }, }; @@ -190,8 +192,10 @@ static struct i2c_board_info dm355evm_i2c_info[] = { static inline int have_sensor(void) { #if defined(CONFIG_SOC_CAMERA_MT9T031) || \ - defined(CONFIG_SOC_CAMERA_MT9T031_MODULE) - return 1; + defined(CONFIG_SOC_CAMERA_MT9T031_MODULE) || \ + defined(CONFIG_VIDEO_MT9P031) || \ + defined(CONFIG_VIDEO_MT9P031_MODULE) + return 1; #else return 0; #endif @@ -204,8 +208,10 @@ static void __init evm_init_i2c(void) gpio_request(5, "dm355evm_msp"); gpio_direction_input(5); dm355evm_i2c_info[0].irq = gpio_to_irq(5); +#if defined(CONFIG_SOC_CAMERA_MT9T031) if (have_sensor()) i2c_add_driver(&pca9543a_driver); +#endif i2c_register_board_info(1, dm355evm_i2c_info, ARRAY_SIZE(dm355evm_i2c_info)); } @@ -266,18 +272,21 @@ static int dm355evm_enable_pca9543a(int en) */ static int dm355evm_setup_video_input(enum vpfe_subdev_id id) { - int ret; - + int ret = 0; +#if defined CONFIG_VIDEO_CAPTURE_DRIVERS switch (id) { + case VPFE_SUBDEV_MT9P031: case VPFE_SUBDEV_MT9T031: { ret = dm355evm_msp_write(MSP_VIDEO_IMAGER, DM355EVM_MSP_VIDEO_IN); +#if defined(CONFIG_SOC_CAMERA_MT9T031) if (ret>= 0) ret = dm355evm_enable_pca9543a(1); else /* switch off i2c switch since we failed */ ret = dm355evm_enable_pca9543a(0); +#endif break; } case VPFE_SUBDEV_TVP5146: @@ -288,6 +297,7 @@ static int dm355evm_setup_video_input(enum vpfe_subdev_id id) default: return -EINVAL; } +#endif return (ret>= 0 ? 0 : ret); } @@ -300,6 +310,15 @@ static struct v4l2_input mt9t031_inputs[] = { } }; +/* Input available at the mt9p031 */ +static struct v4l2_input mt9p031_inputs[] = { + { + .index = 0, + .name = "Camera", + .type = V4L2_INPUT_TYPE_CAMERA, + } +}; + static struct tvp514x_platform_data tvp5146_pdata = { .clk_polarity = 0, .hs_polarity = 1, @@ -357,6 +376,7 @@ static struct vpfe_subdev_info vpfe_sub_devs[] = { .platform_data =&tvp5146_pdata, }, }, +#if defined(CONFIG_SOC_CAMERA_MT9T031) { .module_name = "mt9t031", .is_camera = 1, @@ -373,7 +393,26 @@ static struct vpfe_subdev_info vpfe_sub_devs[] = { /* this is for PCLK rising edge */ .platform_data = (void *)1, }, - } + }, +#elif defined(CONFIG_VIDEO_MT9P031) /* mutually exclusive (same i2c addr) */ + { + .module_name = "mt9p031", + .is_camera = 1, + .grp_id = VPFE_SUBDEV_MT9P031, + .num_inputs = ARRAY_SIZE(mt9p031_inputs), + .inputs = mt9p031_inputs, + .ccdc_if_params = { + .if_type = VPFE_RAW_BAYER, + .hdpol = VPFE_PINPOL_POSITIVE, + .vdpol = VPFE_PINPOL_POSITIVE, + }, + .board_info = { + I2C_BOARD_INFO("mt9p031", 0x5d), + /* this is for PCLK rising edge */ +// .platform_data = (void *)1, + }, + }, +#endif }; static struct vpfe_config vpfe_cfg = { diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index becefc9..866f72c 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -1002,6 +1002,16 @@ config SOC_CAMERA_MT9T031 depends on I2C help This driver supports MT9T031 cameras from Micron. +config VIDEO_MT9P031 + tristate "mt9p031 support" + depends on I2C + depends on !SOC_CAMERA_MT9T031 + ---help--- + This is a Video4Linux2 sensor-level driver for the aptina mt9p031 + decoder. It is currently working with the TI dm355evm board. + + To compile this driver as a module, choose M here: the + module will be called mt9p031. config SOC_CAMERA_MT9V022 tristate "mt9v022 support" diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 5327ff4..a48d5d6 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_VIDEO_KS0127) += ks0127.o obj-$(CONFIG_VIDEO_THS7303) += ths7303.o obj-$(CONFIG_VIDEO_THS7353) += ths7353.o obj-$(CONFIG_VIDEO_VINO) += indycam.o +obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 033ceda..77cef74 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c @@ -87,7 +87,7 @@ static int debug; static u32 numbuffers = 3; static u32 bufsize = HD_IMAGE_SIZE + SECOND_IMAGE_SIZE_MAX; -static int interface; +static int interface=1; static u32 cont_bufoffset; static u32 cont_bufsize; diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c new file mode 100644 index 0000000..fa8eaa5 --- /dev/null +++ b/drivers/media/video/mt9p031.c @@ -0,0 +1,834 @@ +/* + * drivers/media/video/mt9p031.c + * + * Aptina mt9p031 cmos sensor driver + * Copyright (C) 2009 Galil Soft Ltd. (http://www.galilsoft.com) + * Authors: Ran Eitan& Yanir Lubetkin galilsoft.com> + * + * This driver is heavily based on and derived from work previously published + * by Guennadi Liakhovetski, DENX Software Engineering and many + * other contributors to the kernel sources. + * all kudos, credits and rights are humbly acknoledged and granted. + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or later as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the linux kernel sources; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define MT9P031_MODULE_NAME "mt9p031" + +/* we use this number to decide if we can increase the exposure, move from skipping to binning, etc. + the constraint is that this is the minimal frame rate that can still be considered smooth video. +*/ +#define MIN_VIDEO_FPS 21 + +MODULE_AUTHOR("Ran Eitan& Yanir Lubetkin (Galil Soft LTD.) galil galilsoft.com"); +MODULE_DESCRIPTION("MT9P031 sensor driver for use with davinci dm355 vpfe."); +MODULE_LICENSE("GPL"); + +#define MT9P031_MAX_HEIGHT 1944 +#define MT9P031_MAX_WIDTH 2592 +#define MT9P031_MIN_HEIGHT 2 +#define MT9P031_MIN_WIDTH 2 + + +#define REG_MT9P031_CHIP_VERSION 0x00 +#define REG_MT9P031_ROWSTART 0x01 +#define REG_MT9P031_COLSTART 0x02 +#define REG_MT9P031_HEIGHT 0x03 +#define REG_MT9P031_WIDTH 0x04 +#define REG_MT9P031_HBLANK 0x05 +#define REG_MT9P031_VBLANK 0x06 +#define REG_MT9P031_OUT_CTRL 0x07 +#define REG_MT9P031_SHUTTER_WIDTH_U 0x08 +#define REG_MT9P031_SHUTTER_WIDTH_L 0x09 +#define REG_MT9P031_CLK_SPEED 0x0a +#define REG_MT9P031_RESTART 0x0b +#define REG_MT9P031_SHUTTER_DELAY 0x0c +#define REG_MT9P031_RESET 0x0d + +#define REG_MT9P031_PLL_CTRL 0x10 +#define REG_MT9P031_PLL_CONF1 0x11 +#define REG_MT9P031_PLL_CONF2 0x12 + +#define REG_MT9P031_READ_MODE1 0x1e +#define REG_MT9P031_READ_MODE2 0x20 +#define REG_MT9P031_ROW_ADDR_MODE 0x22 +#define REG_MT9P031_COL_ADDR_MODE 0x23 +#define REG_MT9P031_GREEN_1_GAIN 0x2b +#define REG_MT9P031_BLUE_GAIN 0x2c +#define REG_MT9P031_RED_GAIN 0x2d +#define REG_MT9P031_GREEN_2_GAIN 0x2e +#define REG_MT9P031_GLOBAL_GAIN 0x35 + +#define REG_MT9P031_BLC_SAMPLE_SIZE 0x5b +#define REG_MT9P031_BLC_TUNE1 0x5c +#define REG_MT9P031_BLC_DELTA_TRSHLD 0x5d +#define REG_MT9P031_BLC_TUNE2 0x5e +#define REG_MT9P031_BLC_TARGET_TRSHLD 0x5f +#define REG_MT9P031_GREEN_OFFS1 0x60 +#define REG_MT9P031_GREEN_OFFS2 0x61 +#define REG_MT9P031_BLACK_LEVEL_CALIB 0x62 +#define REG_MT9P031_RED_OFFS 0x63 +#define REG_MT9P031_BLUE_OFFS 0x64 +#define REG_MT9P031_SELF_TEST 0xa0 +#define REG_MT9P031_TEST_GREEN 0xa1 +#define REG_MT9P031_TEST_BLUE 0xa2 +#define REG_MT9P031_TEST_RED 0xa3 +#define REG_MT9P031_TEST_WIDTH 0xa4 + +#define MT9P031_NORMAL_OPERATION_MODE (0x1F82)//(0x0002)// //write +#define MT9P031_OUTPUT_CTRL_CHIP_UNSELECT (0x1F80) //write +#define MT9P031_OUTPUT_CTRL_HALT (0x1F83) +#define ADDRESS_MODE_MASK (0x0037) +#define MT9P031_SHUTTER_WIDTH_UPPER_SHIFT (16) +#define REG_MT9P031_BLK_DEF_OFFSET (0x4B) + +enum mt9p031_ctrl { + CTRL_R_GAIN, + CTRL_B_GAIN, + CTRL_G_1_GAIN, + CTRL_G_2_GAIN, + CTRL_R_OFFSET, + CTRL_B_OFFSET, + CTRL_G1_OFFSET, + CTRL_G2_OFFSET, + CTRL_CID_GAIN +}; + +struct mt9p031 +{ + int model; /* V4L2_IDENT_MT9P031* codes from v4l2-chip-ident.h */ +// struct mt9p031_regs regs; + struct v4l2_subdev sd; + struct v4l2_format fmt; + u16 global_gain, red_bal, blue_bal; + u16 exposure; + u16 global_gain_max, global_gain_min, exposure_max, exposure_min; + int is_aew, wbl_temperature; + int r_gain, b_gain ,g1_gain ,g2_gain; + int row_bin; + int width, height; + int column_size, row_size; +}; + +int hb_min[4][4] = { {450, 430, 0, 420}, + {796, 776, 0, 766}, + {0, 0, 0, 0}, + {1488,1468,0, 1458} }; + +int w_dc[4] = {80, 40, 0, 20 }; + +static struct v4l2_captureparm g_temp_capture_params = +{ + .capability = 0, +}; + +static inline struct mt9p031 *to_mt9p031(struct v4l2_subdev *sd) +{ + return container_of(sd, struct mt9p031, sd); +} + +static int reg_read(struct i2c_client *client, const u8 reg) +{ + s32 data = i2c_smbus_read_word_data(client, reg); + return data< 0 ? data : swab16(data); +} + +static int reg_write(struct i2c_client *client, const u8 reg, const u16 data) +{ + return i2c_smbus_write_word_data(client, reg, swab16(data)); +} + +static int reg_set(struct i2c_client *client, const u8 reg, const u16 data) +{ + int ret = reg_read(client, reg); + if (ret< 0) + return ret; + return reg_write(client, reg, ret | data); +} + +static int reg_clear(struct i2c_client *client, const u8 reg, + const u16 data) +{ + int ret = reg_read(client, reg); + if (ret< 0) + return ret; + return reg_write(client, reg, ret& ~data); +} + + +static const struct v4l2_fmtdesc mt9p031_formats[] = +{ + { + .index = 0, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .description = "Bayer (sRGB) 12 bit", + .pixelformat = V4L2_PIX_FMT_SBGGR16, + }, +}; + +static const unsigned int mt9p031_num_formats = ARRAY_SIZE(mt9p031_formats); + +static struct v4l2_queryctrl mt9p031_qctrl[] = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 0, + .maximum = (1<< 10) - 1, + .step = 1, + .default_value = 0x0020, + .flags = 0, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain", + .minimum = 0, + .maximum = (1<< 10) - 1, + .step = 1, + .default_value = 0x0020, + .flags = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red Balance", + .minimum = -1<< 9, + .maximum = (1<< 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue Balance", + .minimum = -1<< 9, + .maximum = (1<< 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, + { + .id = CTRL_R_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "red_gain", + .minimum = 0, + .maximum = (1<< 10) - 1, + .step = 1, + .default_value = 0x0020, + .flags = 0, + }, + { + .id = CTRL_B_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "blue_gain", + .minimum = 0, + .maximum = (1<< 10) - 1, + .step = 1, + .default_value = 0x0020, + .flags = 0, + }, + { + .id = CTRL_G_1_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green_1_gain", + .minimum = -1<< 9, + .maximum = (1<< 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, + { + .id = CTRL_G_2_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green_2_gain", + .minimum = -1<< 9, + .maximum = (1<< 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, + { + .id = CTRL_R_OFFSET, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "ctrl_r_offset", + .minimum = -1<< 9, + .maximum = (1<< 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, + { + .id = CTRL_B_OFFSET, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "ctrl_b_offset", + .minimum = -1<< 9, + .maximum = (1<< 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, + { + .id = CTRL_G1_OFFSET, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green_g1_gain", + .minimum = -1<< 9, + .maximum = (1<< 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + }, + { + .id = CTRL_G2_OFFSET, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "green_g2_gain", + .minimum = -1<< 9, + .maximum = (1<< 9) - 1, + .step = 1, + .default_value = 0, + .flags = 0, + } +}; + +static int mt9p031_init(struct v4l2_subdev *sd, u32 val) +{ + int ret; + struct i2c_client *client = v4l2_get_subdevdata(sd); + +#define PLL_MUL 88 +#define PLL_DIV_SCLK 4 +#define PLL_DIV_PCLK 8 + + ret = reg_write(client, REG_MT9P031_RESET, 0xffff); + if(ret< 0) + goto err; + mdelay(100); + ret = reg_write(client, REG_MT9P031_RESET, 0x0000); + if(ret< 0) + goto err; + mdelay(10); + ret = reg_write(client, REG_MT9P031_PLL_CTRL, 0x0051); + if(ret< 0) + goto err; + ret = reg_write(client, REG_MT9P031_PLL_CONF1, (PLL_MUL<< 8) | (PLL_DIV_SCLK - 1)); + if(ret< 0) + goto err; + ret = reg_write(client, REG_MT9P031_PLL_CONF2, PLL_DIV_PCLK - 1); + if(ret< 0) + goto err; + ret = reg_write(client, REG_MT9P031_PLL_CTRL, 0x0053); + if(ret< 0) + goto err; + ret = reg_write(client, REG_MT9P031_CLK_SPEED, 0x8000); + if(ret< 0) + goto err; + ret = reg_write(client, REG_MT9P031_HBLANK, 0); + if(ret< 0) + goto err; + ret = reg_write(client, REG_MT9P031_VBLANK, 8); + if(ret< 0) + goto err; + ret = reg_write(client, REG_MT9P031_READ_MODE1, 0x4006); + if(ret< 0) + goto err; + ret = reg_write(client, REG_MT9P031_SHUTTER_WIDTH_U, 0x0); + if(ret< 0) + goto err; + ret = reg_write(client, REG_MT9P031_SHUTTER_WIDTH_L, 100); + if(ret< 0) + goto err; + ret = reg_write(client, 0x29, 0x481); + ret |= reg_write(client, 0x3E, 0x87); + ret |= reg_write(client, 0x3F, 0x07); + ret |= reg_write(client, 0x41, 0x0003); + ret |= reg_write(client, 0x42, 0x0003); + ret |= reg_write(client, 0x43, 0x0003); + ret |= reg_write(client, 0x4F, 0x0014); + ret |= reg_write(client, 0x48, 0x18); + ret |= reg_write(client, 0x5F, 0x1C16); + ret |= reg_write(client, 0x57, 0x7); + ret |= reg_write(client, 0x70, 0x005C); + ret |= reg_write(client, 0x71, 0x5B00); + ret |= reg_write(client, 0x72, 0x5900); + ret |= reg_write(client, 0x73, 0x200); + ret |= reg_write(client, 0x74, 0x200); + ret |= reg_write(client, 0x75, 0x2800); + ret |= reg_write(client, 0x76, 0x3E29); + ret |= reg_write(client, 0x77, 0x3E29); + ret |= reg_write(client, 0x78, 0x583F); + ret |= reg_write(client, 0x79, 0x5B00); + ret |= reg_write(client, 0x7A, 0x5A00); + ret |= reg_write(client, 0x7B, 0x5900); + ret |= reg_write(client, 0x7C, 0x5900); + ret |= reg_write(client, 0x7E, 0x5900); + ret |= reg_write(client, 0x7F, 0x5900); + ret |= reg_write(client, REG_MT9P031_RESTART, 1); +err: + return ret>= 0 ? 0 : -EIO; +} + +static int mt9p031_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +{ + int i; + for (i = 0; i< ARRAY_SIZE(mt9p031_qctrl); i++) { + if (qc->id&& qc->id == mt9p031_qctrl[i].id) { + memcpy(qc,&(mt9p031_qctrl[i]), sizeof(*qc)); + return 0; + } + } + return -EINVAL; +} + +static int mt9p031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct mt9p031 *core = to_mt9p031(sd); + int ret = 0, shutter_width, so_p, pix_clk, sd_p, shutter_delay; + int sw_l ,sw_u ,W ,h_banking, t_row; + switch (ctrl->id) { + case CTRL_R_GAIN: + core->r_gain = ctrl->value; + ret = reg_write(client, REG_MT9P031_RED_GAIN, ctrl->value); + break; + case CTRL_B_GAIN: + core->b_gain = ctrl->value; + ret = reg_write(client, REG_MT9P031_BLUE_GAIN, ctrl->value); + break; + case CTRL_G_1_GAIN: + core->g1_gain = ctrl->value; + ret = reg_write(client, REG_MT9P031_GREEN_1_GAIN, ctrl->value); + break; + case CTRL_G_2_GAIN: + core->g2_gain = ctrl->value; + ret = reg_write(client, REG_MT9P031_GREEN_2_GAIN, ctrl->value); + break; + case CTRL_R_OFFSET: + ret = reg_write(client, REG_MT9P031_RED_OFFS, ctrl->value); + break; + case CTRL_B_OFFSET: + ret = reg_write(client, REG_MT9P031_BLUE_OFFS, ctrl->value); + break; + case CTRL_G1_OFFSET: + ret = reg_write(client, REG_MT9P031_GREEN_OFFS1, ctrl->value); + break; + case CTRL_G2_OFFSET: + ret = reg_write(client, REG_MT9P031_GREEN_OFFS2, ctrl->value); + break; + case CTRL_CID_GAIN: + ret = reg_write(client, REG_MT9P031_RED_GAIN, (ctrl->value& 0x0000007f)); + mdelay(1); + ret |= reg_write(client, REG_MT9P031_GREEN_1_GAIN, ((ctrl->value& 0x00007f00)>> 8)); + mdelay(1); + ret |= reg_write(client, REG_MT9P031_GREEN_2_GAIN, ((ctrl->value& 0x007f0000)>> 16)); + mdelay(1); + ret |= reg_write(client, REG_MT9P031_RED_GAIN, ((ctrl->value& 0x7f000000)>> 24)); + break; + case V4L2_CID_EXPOSURE: + shutter_delay = reg_read(client, REG_MT9P031_SHUTTER_DELAY); + sd_p = min(shutter_delay + 1, 1604); + so_p = 346 * (core->row_bin + 1) + 98 + sd_p + 166; + pix_clk = 41; + h_banking = reg_read(client, REG_MT9P031_HBLANK) + 1; + W = (core->width + 1) / (core->row_bin + 1); + t_row = 2 * pix_clk * max(W/2 + max(h_banking, hb_min[core->row_bin][core->row_bin]), + (41 + 346 * (core->row_bin + 1) + 99))/1000; + shutter_width = (ctrl->value + 2*so_p*pix_clk) / t_row; + if (shutter_width< 3) { + sd_p = 1315> shutter_delay ? 1315 : shutter_delay; + so_p = 346 * (core->row_bin + 1) + 98 + sd_p + 166; + shutter_width = (ctrl->value + 2*so_p*pix_clk) / t_row; + } + if (shutter_width< 1) + shutter_width = 1; + sw_l = shutter_width& 0xffff; + sw_u = (shutter_width)>> 16; + ret = reg_write(client, REG_MT9P031_SHUTTER_WIDTH_L,sw_l); + mdelay(1); + ret = reg_write(client, REG_MT9P031_SHUTTER_WIDTH_U,sw_u); + break; + default: + return -ERANGE; + } + return ret; +} + +static int mt9p031_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) +{ + struct v4l2_pix_format *pix =&f->fmt.pix; + if (pix->height< MT9P031_MIN_HEIGHT) + pix->height = MT9P031_MIN_HEIGHT; + else if (pix->height> MT9P031_MAX_HEIGHT) + pix->height = MT9P031_MAX_HEIGHT; + if (pix->width< MT9P031_MIN_WIDTH) + pix->width = MT9P031_MIN_WIDTH; + if (pix->width> MT9P031_MAX_WIDTH) + pix->width = MT9P031_MAX_WIDTH; + + pix->width&= ~0x01; /* has to be even */ + pix->height&= ~0x01; /* has to be even */ + pix->pixelformat = V4L2_PIX_FMT_SBGGR16; + return 0; +} +struct mt9p031_format_params { + int width; + int height; + int col_size; + int row_size; + int hblank; + int vblank; + int shutter_width; + int row_addr_mode; + int col_addr_mode; + int black_level; + int pixel_clk_control; + int row_start; + int col_start; + int read_mode_2_config; + int output_ctrl; + int pll_m; + int pll_n; + int pll_p1; +}; + +enum formats { + VGA_BIN_30FPS, + SVGA_30FPS, + XGA_30FPS, + SXGA_30FPS, + HD_READY_720P_30FPS, + FULL_5MP_7FPS, +}; + +const struct mt9p031_format_params mt9p031_supported_formats[] = + { + { 640, 480, 2575, 1951, 1470, 8, 496, 0x33, 0x33, 64, 0x8000, 32, 24, 32, 0x1F82, 0x12, 4, 2, }, // VGA_BIN_30FPS + { 800, 600, 1599, 1199, 0, 8, 599, 0x11, 0x11, 64, 0x8000, 0, 0, 64, 0x1F82, 0xFF, 29, 4, }, // SVGA_30FPS + {1024, 768, 2047, 1535, 0, 8, 767, 0x11, 0x11, 64, 0x8000, 0, 0, 64, 0x1F82, 0xFF, 29, 4, }, // XGA_30FPS + {1280,1024, 2575, 1951, 776,10, 744, 0x11, 0x11, 64, 0x8000, 32, 24, 32, 0x1F8E, 0x1C, 4, 2, }, // SXGA_30FPS + {1280, 720, 2583, 1491, 786, 0, 740, 0x11, 0x11, 64, 0x8000,272, 24, 32, 0x1F8E, 16, 3, 2, }, + {2592,1944, 2591, 1943, 450, 9,1942, 0x00, 0x00, 64, 0x8000, 66, 32, 64, 0x1F82, /*24*/ 12, 4, 2, }, // 5MP_7FPS + }; +static int mt9p031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + int ret; + struct v4l2_pix_format *pix =&fmt->fmt.pix; + struct mt9p031 *core = to_mt9p031(sd); + enum formats i; + struct i2c_client *client = v4l2_get_subdevdata(sd); + + memcpy(&(core->fmt), fmt, sizeof(struct v4l2_format)); + if (pix->width< 640) + return -EINVAL; + else if (pix->width< 800) { + if (pix->height>= 480) + i = VGA_BIN_30FPS; + else + return -EINVAL; + } + else if (pix->width< 1024) { + if (pix->height>= 600) + i = SVGA_30FPS; + else + return -EINVAL; + } + else if (pix->width< 1280) { + if (pix->height>= 768) + i = XGA_30FPS; + else + return -EINVAL; + } + else if (pix->width< 2592) { + if (pix->height< 768) { + i = HD_READY_720P_30FPS; // 1280*720 + } + else if (pix->height == 768) { + i = SXGA_30FPS; // 1280*768 + } + else { + return -EINVAL; + } + } + else { + if (pix->height == 1944) + i = FULL_5MP_7FPS; + else + return -EINVAL; + } + + core->width = mt9p031_supported_formats[i].width; + core->height = mt9p031_supported_formats[i].height; + ret = reg_write(client, REG_MT9P031_OUT_CTRL, MT9P031_OUTPUT_CTRL_HALT); + ret |= reg_write(client, REG_MT9P031_HEIGHT, mt9p031_supported_formats[i].row_size ); + ret |= reg_write(client, REG_MT9P031_WIDTH, mt9p031_supported_formats[i].col_size); + ret |= reg_clear(client, REG_MT9P031_ROW_ADDR_MODE, ADDRESS_MODE_MASK); + ret |= reg_set(client, REG_MT9P031_ROW_ADDR_MODE, mt9p031_supported_formats[i].row_addr_mode); + ret |= reg_clear(client, REG_MT9P031_COL_ADDR_MODE, ADDRESS_MODE_MASK); + ret |= reg_set(client, REG_MT9P031_COL_ADDR_MODE, mt9p031_supported_formats[i].col_addr_mode); + core->row_bin = mt9p031_supported_formats[i].row_addr_mode& 0x0F; + ret |= reg_write(client, REG_MT9P031_HBLANK, mt9p031_supported_formats[i].hblank); + ret |= reg_write(client, REG_MT9P031_VBLANK, mt9p031_supported_formats[i].vblank); + ret |= reg_write(client, REG_MT9P031_ROWSTART, mt9p031_supported_formats[i].row_start); + ret |= reg_write(client, REG_MT9P031_COLSTART, mt9p031_supported_formats[i].col_start); + + ret |= reg_write(client, REG_MT9P031_SHUTTER_WIDTH_U, + (unsigned short)(mt9p031_supported_formats[i].shutter_width>> MT9P031_SHUTTER_WIDTH_UPPER_SHIFT) ); + ret |= reg_write(client, REG_MT9P031_SHUTTER_WIDTH_L, (unsigned short)mt9p031_supported_formats[i].shutter_width); + + ret |= reg_write(client, REG_MT9P031_BLK_DEF_OFFSET, mt9p031_supported_formats[i].black_level); + ret |= reg_write(client, REG_MT9P031_CLK_SPEED, mt9p031_supported_formats[i].pixel_clk_control); + + // PLL setup + ret |= reg_write(client,REG_MT9P031_PLL_CTRL, 0x0051); + ret |= reg_write(client, REG_MT9P031_PLL_CONF1, + (mt9p031_supported_formats[i].pll_m<< 8) | (mt9p031_supported_formats[i].pll_n - 1)); + ret |= reg_write(client, REG_MT9P031_PLL_CONF2, mt9p031_supported_formats[i].pll_p1 - 1); + ret |= reg_write(client,REG_MT9P031_PLL_CTRL, 0x0053); + + ret |= reg_write(client, REG_MT9P031_OUT_CTRL, mt9p031_supported_formats[i].output_ctrl); + return ret; +} + +static int mt9p031_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) +{ + struct v4l2_pix_format *pix =&fmt->fmt.pix; + struct mt9p031 *core = to_mt9p031(sd); + pix->width = core->width; + pix->height = core->height; + pix->pixelformat = V4L2_PIX_FMT_SBGGR16; + pix->field = V4L2_FIELD_NONE; + pix->bytesperline = 2 * core->width; + pix->sizeimage = 2 * core->width * core->height; + pix->colorspace = V4L2_COLORSPACE_SRGB; + return 0; +} + +static int mt9p031_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) +{ + memcpy(parms,&g_temp_capture_params, sizeof(*parms)); + return 0; +} + +static int mt9p031_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) +{ + struct v4l2_captureparm *cp =&parms->parm.capture; + + if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (cp->extendedmode != 0) + return -EINVAL; + memcpy(&g_temp_capture_params, parms, sizeof(*parms)); + g_temp_capture_params.capability = V4L2_CAP_TIMEPERFRAME; + return 0; +} + +static int mt9p031_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret = 0; + if (enable) { + ret = reg_clear(client, REG_MT9P031_RESTART, 2); + if(ret< 0) + return ret; + mdelay(5); + ret = reg_write(client, REG_MT9P031_RESTART, 1); + }else { + ret = reg_set(client, REG_MT9P031_RESTART, 2); + if(ret< 0) + return ret; + mdelay(50); + ret = reg_set(client, REG_MT9P031_RESTART, 1); + } + return ret; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int mt9p031_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client,®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg->val = reg_read(client, reg->reg& 0xff); + reg->size = 2; + return 0; +} + +static int mt9p031_s_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (!v4l2_chip_match_i2c_client(client,®->match)) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reg_write(client, reg->reg& 0xff, reg->val& 0xffff); + return 0; +} +#endif + +static int mt9p031_g_chip_ident(struct v4l2_subdev *sd, + struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + u16 version = reg_read(client, REG_MT9P031_CHIP_VERSION); + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9P031, version); +} + +static const struct v4l2_subdev_core_ops mt9p031_core_ops = +{ + .g_chip_ident = mt9p031_g_chip_ident, + .init = mt9p031_init, + .queryctrl = mt9p031_queryctrl, + .s_ctrl = mt9p031_s_ctrl, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mt9p031_g_register, + .s_register = mt9p031_s_register, +#endif +}; + +static const struct v4l2_subdev_video_ops mt9p031_video_ops = { + .s_stream = mt9p031_s_stream, + .s_fmt = mt9p031_s_fmt, + .g_fmt = mt9p031_g_fmt, + .try_fmt = mt9p031_try_fmt, + .s_parm = mt9p031_s_parm, + .g_parm = mt9p031_g_parm, +}; + +static const struct v4l2_subdev_ops mt9p031_ops = { + .core =&mt9p031_core_ops, + .video =&mt9p031_video_ops, +}; + +static int mt9p031_detect(struct i2c_client *client, int *model) +{ + int ret, version; + dev_info(&client->dev, "entering %s\n", __FUNCTION__); + ret = reg_write(client, REG_MT9P031_OUT_CTRL, MT9P031_NORMAL_OPERATION_MODE); + if(ret< 0) + return ret; + mdelay(1); + version = reg_read(client, REG_MT9P031_CHIP_VERSION); + if (version != V4L2_IDENT_MT9P031) + return -EINVAL; + switch (version) { + case 6145: + *model = V4L2_IDENT_MT9P031; + break; + default: + dev_err(&client->dev,"No MT9P031 chip detected, register read %x\n", version); + return -ENODEV; + } + dev_info(&client->dev, "Detected a MT9P031 chip ID %x\n", version); + return 0; +} + + +static int mt9p031_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int ret; + struct mt9p031 *decoder; + struct v4l2_subdev *sd; + + dev_info(&client->dev, "entering %s\n", __FUNCTION__); + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) + return -EIO; + decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); + if (!decoder) + return -ENOMEM; + ret = mt9p031_detect(client,&decoder->model); + if (ret) + goto clean; + ret = reg_write(client, REG_MT9P031_HEIGHT, 240); + if (ret< 0) + goto clean; + ret = reg_write(client, REG_MT9P031_WIDTH, 320); + if (ret< 0) + goto clean; + + dev_info(&client->dev, "cont. %s\n", __FUNCTION__); + sd =&decoder->sd; + v4l2_i2c_subdev_init(sd, client,&mt9p031_ops); + ret = mt9p031_init(sd, 0); + + v4l2_info(sd, "%s decoder driver registered\n", sd->name); + return 0; +clean: + kfree(decoder); + return ret; +} + + +static int mt9p031_remove(struct i2c_client *client) +{ + int ret; + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct mt9p031 *decoder = to_mt9p031(sd); + ret = reg_write(client, REG_MT9P031_OUT_CTRL, MT9P031_NORMAL_OPERATION_MODE); + sd = i2c_get_clientdata(client); + ret |= reg_write(client, REG_MT9P031_OUT_CTRL, MT9P031_OUTPUT_CTRL_CHIP_UNSELECT); + v4l2_device_unregister_subdev(sd); + kfree(decoder); + return ret; +} + + +static const struct i2c_device_id mt9p031_id[] = +{ + {"mt9p031", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, mt9p031_id); + +static struct i2c_driver mt9p031_driver = +{ + .driver = { + .owner = THIS_MODULE, + .name = MT9P031_MODULE_NAME, + }, + .probe = mt9p031_probe, + .remove = mt9p031_remove, + .id_table = mt9p031_id, +}; + +static int __init mt9p031_module_init(void) +{ + return i2c_add_driver(&mt9p031_driver); +} + +static void __exit mt9p031_exit(void) +{ + i2c_del_driver(&mt9p031_driver); +} + +module_init(mt9p031_module_init); +module_exit(mt9p031_exit); + diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c index 3d4a861..341b685 100644 --- a/drivers/mfd/dm355evm_msp.c +++ b/drivers/mfd/dm355evm_msp.c @@ -56,7 +56,9 @@ #define msp_has_tvp() false #endif - +static int msp_use_soc_camera=1; +module_param(msp_use_soc_camera,bool, S_IRUGO); +MODULE_PARM_DESC(msp_use_soc_camera, "initially selects tvp541x(0) or a sensor(1)"); /*----------------------------------------------------------------------*/ /* REVISIT for paranoia's sake, retry reads/writes on error */ @@ -368,8 +370,8 @@ static int dm355evm_msp_probe(struct i2c_client *client, const struct i2c_device_id *id) { int status; - const char *video = msp_has_tvp() ? "TVP5146" : "imager"; - +// const char *video = msp_has_tvp() ? "TVP5146" : "imager"; + const char *video = msp_use_soc_camera == 0 ? "TVP5146" : "imager"; if (msp430) return -EBUSY; msp430 = client; @@ -382,7 +384,9 @@ dm355evm_msp_probe(struct i2c_client *client, const struct i2c_device_id *id) status, video); /* mux video input: either tvp5146 or some external imager */ - status = dm355evm_msp_write(msp_has_tvp() ? 0 : MSP_VIDEO_IMAGER, +// status = dm355evm_msp_write(msp_has_tvp() ? 0 : MSP_VIDEO_IMAGER, +// DM355EVM_MSP_VIDEO_IN); + status = dm355evm_msp_write(msp_use_soc_camera ? MSP_VIDEO_IMAGER : 0, DM355EVM_MSP_VIDEO_IN); if (status< 0) dev_warn(&client->dev, "error %d muxing %s as video-in\n", diff --git a/include/media/davinci/vpfe_capture.h b/include/media/davinci/vpfe_capture.h index 785157c..cdea6ac 100644 --- a/include/media/davinci/vpfe_capture.h +++ b/include/media/davinci/vpfe_capture.h @@ -68,6 +68,7 @@ enum vpfe_subdev_id { VPFE_SUBDEV_TVP5146 = 1, VPFE_SUBDEV_MT9T031 = 2, VPFE_SUBDEV_TVP7002 = 3, + VPFE_SUBDEV_MT9P031 = 4, }; struct vpfe_subdev_info { diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index 688b7ed..42ac2de 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -174,6 +174,9 @@ enum { /* module mt9v011, just ident 8243 */ V4L2_IDENT_MT9V011 = 8243, + /* module mt9p031, just ident 6145 */ + V4L2_IDENT_MT9P031 = 6145, + /* module tw9910: just ident 9910 */ V4L2_IDENT_TW9910 = 9910, -- 1.7.2.2 From michael.williamson at criticallink.com Mon Sep 13 18:45:25 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Mon, 13 Sep 2010 19:45:25 -0400 Subject: [PATCH v5 1/1] davinci: spi: replace existing driver In-Reply-To: References: <1280355490-11878-1-git-send-email-bniebuhr@efjohnson.com> <201008201406.33473.caglarakyuz@gmail.com> <201008231154.10411.caglarakyuz@gmail.com> Message-ID: <4C8EB795.1080607@criticallink.com> Hi Sekhar, On 08/23/2010 05:30 AM, Nori, Sekhar wrote: > On Mon, Aug 23, 2010 at 14:24:10, Caglar Akyuz wrote: >> On Monday 23 August 2010 07:28:48 am Nori, Sekhar wrote: >>> Hi Caglar, >>> >> >> Hi, >> >> [...] >> >>> I have been spending time on this (admittedly on and off) since I wrote >>> that email and have broken down the work into ~20 patches so far. Starting >>> to scratch the DMA related changes right now. So, I guess I am somewhere >>> midway. >>> >>> I pushed a branch containing the work so far here: >>> >>> http://arago-project.org/git/projects/?p=linux-davinci.git;a=shortlog;h=ref >>> s/heads/davinci-spi-rewrite >>> >> I've been trying to take a peek, but the arago site seems to be flakey lately, giving a lot of messages like the one below. Not sure if you are aware of this. Looking forward to seeing this... Thanks! -Mike (Arago Error Message). XML Parsing Error: undefined entity Location: http://arago-project.org/git/projects/?p=linux-davinci.git;a=summary Line Number 41, Column 20:
 
-------------------^ From nsekhar at ti.com Tue Sep 14 00:43:41 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Tue, 14 Sep 2010 11:13:41 +0530 Subject: [PATCH v5 1/1] davinci: spi: replace existing driver In-Reply-To: <4C8EB795.1080607@criticallink.com> References: <1280355490-11878-1-git-send-email-bniebuhr@efjohnson.com> <201008201406.33473.caglarakyuz@gmail.com> <201008231154.10411.caglarakyuz@gmail.com> <4C8EB795.1080607@criticallink.com> Message-ID: On Tue, Sep 14, 2010 at 05:15:25, Michael Williamson wrote: > Hi Sekhar, > > On 08/23/2010 05:30 AM, Nori, Sekhar wrote: > > On Mon, Aug 23, 2010 at 14:24:10, Caglar Akyuz wrote: > >> On Monday 23 August 2010 07:28:48 am Nori, Sekhar wrote: > >>> Hi Caglar, > >>> > >> > >> Hi, > >> > >> [...] > >> > >>> I have been spending time on this (admittedly on and off) since I wrote > >>> that email and have broken down the work into ~20 patches so far. Starting > >>> to scratch the DMA related changes right now. So, I guess I am somewhere > >>> midway. > >>> > >>> I pushed a branch containing the work so far here: > >>> > >>> http://arago-project.org/git/projects/?p=linux-davinci.git;a=shortlog;h=ref > >>> s/heads/davinci-spi-rewrite > >>> > >> > > I've been trying to take a peek, but the arago site seems to be flakey lately, > giving a lot of messages like the one below. Not sure if you are aware of this. Hmm, I have seen this kind of error in the past, but not lately. Accessed the site just now without issues. > Looking forward to seeing this... Thanks! Got side-tracked the last two weeks. The DMA changes are the major chunk left. Hopefully will have the final patch set ready with little more effort. Thanks, Sekhar From caglarakyuz at gmail.com Tue Sep 14 01:04:59 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Tue, 14 Sep 2010 09:04:59 +0300 Subject: [PATCH v5 1/1] davinci: spi: replace existing driver In-Reply-To: References: <1280355490-11878-1-git-send-email-bniebuhr@efjohnson.com> <4C8EB795.1080607@criticallink.com> Message-ID: <201009140904.59555.caglarakyuz@gmail.com> On Tuesday 14 September 2010 08:43:41 am Nori, Sekhar wrote: > On Tue, Sep 14, 2010 at 05:15:25, Michael Williamson wrote: > > Hi Sekhar, > > > > On 08/23/2010 05:30 AM, Nori, Sekhar wrote: > > > On Mon, Aug 23, 2010 at 14:24:10, Caglar Akyuz wrote: > > >> On Monday 23 August 2010 07:28:48 am Nori, Sekhar wrote: > > >>> Hi Caglar, > > >> > > >> Hi, > > >> > > >> [...] > > >> > > >>> I have been spending time on this (admittedly on and off) since I > > >>> wrote that email and have broken down the work into ~20 patches so > > >>> far. Starting to scratch the DMA related changes right now. So, I > > >>> guess I am somewhere midway. > > >>> > > >>> I pushed a branch containing the work so far here: > > >>> > > >>> http://arago-project.org/git/projects/?p=linux-davinci.git;a=shortlog > > >>>;h=ref s/heads/davinci-spi-rewrite > > > > I've been trying to take a peek, but the arago site seems to be flakey > > lately, giving a lot of messages like the one below. Not sure if you are > > aware of this. > > Hmm, I have seen this kind of error in the past, but not lately. Accessed > the site just now without issues. > > > Looking forward to seeing this... Thanks! > > Got side-tracked the last two weeks. The DMA changes are the major > chunk left. Hopefully will have the final patch set ready with > little more effort. > Yes, your patches seems ok and mostly complete. I'm waiting for hardware to test those, will let you know when I do some testing. Regards, Caglar > Thanks, > Sekhar > > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source at linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source > From nsekhar at ti.com Tue Sep 14 02:14:18 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Tue, 14 Sep 2010 12:44:18 +0530 Subject: [PATCH v5 1/1] davinci: spi: replace existing driver In-Reply-To: <201009140904.59555.caglarakyuz@gmail.com> References: <1280355490-11878-1-git-send-email-bniebuhr@efjohnson.com> <4C8EB795.1080607@criticallink.com> <201009140904.59555.caglarakyuz@gmail.com> Message-ID: On Tue, Sep 14, 2010 at 11:34:59, Caglar Akyuz wrote: > Yes, your patches seems ok and mostly complete. I'm waiting for hardware to > test those, will let you know when I do some testing. Thanks! To save time, I haven't tested these patches myself. I have only made sure individual patches don't break the build. Was planning to test after the complete series is ready. Regards, Sekhar From sugumar at ti.com Tue Sep 14 05:36:15 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Tue, 14 Sep 2010 16:06:15 +0530 Subject: [PATCH v5 1/2] davinci: Add generic PWM support for PWM control Message-ID: <1284460575-24746-1-git-send-email-sugumar@ti.com> This patch adds generic PWM support where it maintains the list of PWM control devices that can be added or removed. The interface provides a list of functions that can be accessed by the PWM control driver module and the generic PWM driver. The PWM control driver module such as eCAP uses the interface to register and add itself to the list as a PWM control device. The generic PWM driver uses the interface to search for a PWM control device and if present, uses the device for PWM control. Signed-off-by: Sugumar Natarajan --- Changes since v4: a) Conditional 'clk_enable' and 'clk_disable' has been added arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/davinci_pwm.c | 140 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 33 +++++ 3 files changed, 176 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/davinci_pwm.c create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index a7a70d1..90ca821 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_SUSPEND) += pm.o sleep.o + +# Generic PWM control support +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o diff --git a/arch/arm/mach-davinci/davinci_pwm.c b/arch/arm/mach-davinci/davinci_pwm.c new file mode 100644 index 0000000..5a5b332 --- /dev/null +++ b/arch/arm/mach-davinci/davinci_pwm.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + unsigned int clock_freq; + unsigned int period_cycles; + unsigned int duty_cycle; + int ret = 0; + + if (WARN_ON(!pwm)) + return -EINVAL; + + if (pwm->pwm_config_device) { + if (!period_ns || duty_ns > period_ns) + return -EINVAL; + + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; + ret = pwm->pwm_config_device(pwm, period_cycles, duty_cycle); + } + + return ret; +} +EXPORT_SYMBOL(pwm_config); + +int pwm_enable(struct pwm_device *pwm) +{ + int rc = 0; + + if (WARN_ON(!pwm)) + return -EINVAL; + + if (!pwm->clk_enabled) { + rc = clk_enable(pwm->clk); + if (!rc) + pwm->clk_enabled = 1; + } + return rc; +} +EXPORT_SYMBOL(pwm_enable); + +void pwm_disable(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + if (pwm->clk_enabled) { + clk_disable(pwm->clk); + pwm->clk_enabled = 0; + } +} +EXPORT_SYMBOL(pwm_disable); + +static DEFINE_MUTEX(pwm_lock); +static LIST_HEAD(pwm_list); + +struct pwm_device *pwm_request(int pwm_id, const char *label) +{ + struct pwm_device *pwm, *tmp_pwm = ERR_PTR(-ENOENT); + + mutex_lock(&pwm_lock); + + list_for_each_entry(pwm, &pwm_list, node) { + if (pwm->pwm_id == pwm_id) { + if (pwm->use_count == 0) { + pwm->use_count++; + pwm->label = label; + } else { + pwm = ERR_PTR(-EBUSY); + } + tmp_pwm = pwm; + break; + } + } + + mutex_unlock(&pwm_lock); + return tmp_pwm; +} +EXPORT_SYMBOL(pwm_request); + +void pwm_free(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + mutex_lock(&pwm_lock); + + if (pwm->use_count) { + pwm->use_count--; + pwm->label = NULL; + } else { + dev_warn(&pwm->pdev->dev, "PWM device already freed\n"); + } + + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_free); + +void pwm_add(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + mutex_lock(&pwm_lock); + list_add_tail(&pwm->node, &pwm_list); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_add); + +void pwm_remove(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + mutex_lock(&pwm_lock); + list_del(&pwm->node); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_remove); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h new file mode 100644 index 0000000..6dd8fb2 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __DAVINCI_PWM_H +#define __DAVINCI_PWM_H + +struct pwm_device { + struct list_head node; + struct platform_device *pdev; + int clk_enabled; + int (*pwm_config_device)(struct pwm_device *pwm, + unsigned int period, unsigned int dutycycle); + const char *label; + struct clk *clk; + unsigned int use_count; + unsigned int pwm_id; +}; + +void pwm_add(struct pwm_device *pwm); +void pwm_remove(struct pwm_device *pwm); + +#endif -- 1.5.6 From sugumar at ti.com Tue Sep 14 05:36:43 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Tue, 14 Sep 2010 16:06:43 +0530 Subject: [PATCH v5 2/2] davinci: da850: eCAP driver for PWM signal generation Message-ID: <1284460603-24792-1-git-send-email-sugumar@ti.com> OMAPL138/DA850 contains three instances of eCAP module. Each eCAP module has one dedicated pin that can be used either in capture mode(input) or in PWM mode. For more information on eCAP module operation, please refer to the following url. http://focus.ti.com/lit/ug/sprufl2a/sprufl2a.pdf This patch adds eCAP driver support for PWM signal generation. Signed-off-by: Sugumar Natarajan --- Changes since v4: a) clk_enable is added prior to configuring the registers. arch/arm/mach-davinci/Kconfig | 9 ++ arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/ecap.c | 160 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 1 + 4 files changed, 173 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/ecap.c diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 9aca60c..8192866 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -40,6 +40,7 @@ config ARCH_DAVINCI_DA850 select CP_INTC select ARCH_DAVINCI_DA8XX select ARCH_HAS_CPUFREQ + select HAVE_PWM config ARCH_DAVINCI_DA8XX select CPU_ARM926T @@ -230,6 +231,14 @@ config DAVINCI_RESET_CLOCKS probably do not want this option enabled until your device drivers work properly. +config DAVINCI_ECAP_PWM + bool "eCAP driver support for PWM control" + depends on ARCH_DAVINCI_DA8XX + depends on HAVE_PWM + default n + help + Say Y to select the eCAP module for PWM control. + endmenu endif diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 90ca821..90bd88e 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -42,3 +42,6 @@ obj-$(CONFIG_SUSPEND) += pm.o sleep.o # Generic PWM control support obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o + +# eCAP driver support for PWM +obj-$(CONFIG_DAVINCI_ECAP_PWM) += ecap.o diff --git a/arch/arm/mach-davinci/ecap.c b/arch/arm/mach-davinci/ecap.c new file mode 100644 index 0000000..066b489 --- /dev/null +++ b/arch/arm/mach-davinci/ecap.c @@ -0,0 +1,160 @@ +/* + * DA850/OMAP-L138 eCAP driver for PWM output generation + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CAPTURE_3_REG 0x10 +#define CAPTURE_4_REG 0x14 +#define CAPTURE_CTRL2_REG 0x2A + +#define ECAPCTRL2_MODESL_ECAP BIT(9) +#define ECAPCTRL2_SYNCOSEL_DISABLE (0x3 << 6) +#define ECAPCTRL2_TSCTRSTOP_FREERUN BIT(4) + +/* + * ecap_config_pwm - configures the eCAP Module for the PWM output with given + * period and duty cycle. + */ + +static int ecap_config_pwm(struct pwm_device *pwm, unsigned int period_cycles, + unsigned int duty_cycle) +{ + clk_enable(pwm->clk); + + __raw_writew(ECAPCTRL2_MODESL_ECAP | ECAPCTRL2_SYNCOSEL_DISABLE | + ECAPCTRL2_TSCTRSTOP_FREERUN, pwm->mmio_base + + CAPTURE_CTRL2_REG); + __raw_writel(period_cycles, pwm->mmio_base + CAPTURE_3_REG); + + /* + * 100% duty cycle is obtained when the duty cycle value is one + * greater than period ie duty cycle = period + 1 + */ + if (duty_cycle == period_cycles) + duty_cycle = duty_cycle + 1; + + __raw_writel(duty_cycle, pwm->mmio_base + CAPTURE_4_REG); + mdelay(10); + + clk_disable(pwm->clk); + return 0; +} + +static int __devinit ecap_probe(struct platform_device *pdev) +{ + struct pwm_device *pwm = NULL; + struct resource *r; + int ret = 0; + + pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); + if (!pwm) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + pwm->clk = clk_get(&pdev->dev, "ecap"); + if (IS_ERR(pwm->clk)) { + ret = PTR_ERR(pwm->clk); + goto err_free; + } + + pwm->pwm_id = pdev->id; + pwm->pdev = pdev; + pwm->pwm_config_device = ecap_config_pwm; + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "no memory resource defined\n"); + ret = -ENODEV; + goto err_free_clk; + } + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) { + dev_err(&pdev->dev, "failed to request memory resource\n"); + ret = -EBUSY; + goto err_free_clk; + } + + pwm->mmio_base = ioremap(r->start, resource_size(r)); + if (!pwm->mmio_base) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + ret = -ENODEV; + goto err_free_mem; + } + + pwm_add(pwm); + platform_set_drvdata(pdev, pwm); + return 0; + +err_free_mem: + release_mem_region(r->start, resource_size(r)); +err_free_clk: + clk_put(pwm->clk); +err_free: + kfree(pwm); + return ret; +} + +static int __devexit ecap_remove(struct platform_device *pdev) +{ + struct pwm_device *pwm; + struct resource *r; + + pwm = platform_get_drvdata(pdev); + if (!pwm) + return -ENODEV; + + pwm_remove(pwm); + iounmap(pwm->mmio_base); + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(r->start, resource_size(r)); + clk_put(pwm->clk); + kfree(pwm); + + return 0; +} + +static struct platform_driver ecap_driver = { + .driver = { + .name = "ecap", + .owner = THIS_MODULE, + }, + .probe = ecap_probe, + .remove = __devexit_p(ecap_remove), +}; + +static int __init ecap_init(void) +{ + return platform_driver_register(&ecap_driver); +} + +static void __exit ecap_exit(void) +{ + platform_driver_unregister(&ecap_driver); +} + +module_init(ecap_init); +module_exit(ecap_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h index 6dd8fb2..db84580 100644 --- a/arch/arm/mach-davinci/include/mach/davinci_pwm.h +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -23,6 +23,7 @@ struct pwm_device { unsigned int period, unsigned int dutycycle); const char *label; struct clk *clk; + void __iomem *mmio_base; unsigned int use_count; unsigned int pwm_id; }; -- 1.5.6 From michael.williamson at criticallink.com Tue Sep 14 08:10:56 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Tue, 14 Sep 2010 09:10:56 -0400 Subject: [PATCH v5 1/1] davinci: spi: replace existing driver In-Reply-To: References: <1280355490-11878-1-git-send-email-bniebuhr@efjohnson.com> <4C8EB795.1080607@criticallink.com> <201009140904.59555.caglarakyuz@gmail.com> Message-ID: <4C8F7460.6050006@criticallink.com> On 9/14/2010 3:14 AM, Nori, Sekhar wrote: > On Tue, Sep 14, 2010 at 11:34:59, Caglar Akyuz wrote: > >> Yes, your patches seems ok and mostly complete. I'm waiting for hardware to >> test those, will let you know when I do some testing. > > Thanks! To save time, I haven't tested these patches myself. I have only made > sure individual patches don't break the build. Was planning to test after > the complete series is ready. > If it would help, If there are portions of the patch set that can be tested with DMA disabled or something, I'd be willing to kick the tires. I have da850 hardware available. -Mike From nsekhar at ti.com Tue Sep 14 08:26:30 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Tue, 14 Sep 2010 18:56:30 +0530 Subject: [PATCH v5 1/1] davinci: spi: replace existing driver In-Reply-To: <4C8F7460.6050006@criticallink.com> References: <1280355490-11878-1-git-send-email-bniebuhr@efjohnson.com> <4C8EB795.1080607@criticallink.com> <201009140904.59555.caglarakyuz@gmail.com> <4C8F7460.6050006@criticallink.com> Message-ID: Hi Mike, On Tue, Sep 14, 2010 at 18:40:56, Michael Williamson wrote: > On 9/14/2010 3:14 AM, Nori, Sekhar wrote: > > > On Tue, Sep 14, 2010 at 11:34:59, Caglar Akyuz wrote: > > > >> Yes, your patches seems ok and mostly complete. I'm waiting for hardware to > >> test those, will let you know when I do some testing. > > > > Thanks! To save time, I haven't tested these patches myself. I have only made > > sure individual patches don't break the build. Was planning to test after > > the complete series is ready. > > > > > If it would help, If there are portions of the patch set that can be tested > with DMA disabled or something, I'd be willing to kick the tires. I have > da850 hardware available. Thanks for being brave and offering to help! Yes, interrupt and polled mode can be tried. Since a lot of testing has already happened on the original patch, I was planning to test the series only after it is complete. Any issues found can be narrowed down to the differences (which I hope will be justifiable). Thanks, Sekhar From Michael.Rondeau at andrew.com Tue Sep 14 08:31:15 2010 From: Michael.Rondeau at andrew.com (Rondeau, Michael) Date: Tue, 14 Sep 2010 08:31:15 -0500 Subject: Prefered web server fo Davinci Message-ID: <55D474137AF1C541A021F8D73F85CF5D4207993934@ACDCE7MB3.commscope.com> We have been using the Apache web server that came with the Montivista Pro 4 development software on our product using the Davinci 6446. I have been working for three days now to cross compile the latest Apache release. Apparently the cross compile has been broken for many years. I finally got it to cross compile but cannot run it yet because I need to update or get new libraries. The size of the executable has doubled from 78 KB to 1.5 MB. We are looking to update the web server to get the latest security fixes as well as SSH. Could someone please tell me if there is a better, smaller, easier to cross compile, and secure web server that you would recommend? Thanks Michael Rondeau -------------- next part -------------- An HTML attachment was scrubbed... URL: From albertbu at gmail.com Tue Sep 14 08:51:13 2010 From: albertbu at gmail.com (Albert Burbea) Date: Tue, 14 Sep 2010 15:51:13 +0200 Subject: voice codec driver In-Reply-To: References: <4C8E26F9.1020205@mvista.com> Message-ID: Thanks folks can you please tell me if there is a usage example ? Albert On Mon, Sep 13, 2010 at 4:06 PM, Raffaele Recalcati wrote: > On Mon, Sep 13, 2010 at 3:28 PM, Sergei Shtylyov > wrote: > > Hello. > > > > Albert Burbea wrote: > > > >> Hi everybody > >> are there any plans/schedule to add the DM365 internal voice codec to > the > >> linux tree? > > > > The DM365 voice codec support has been merged back in March already. > > And I have checked it in 2.6.32 arago kernel. > Some fixes are needed. > Look at the following for more info: > http://e2e.ti.com/support/embedded/f/354/p/56231/226155.aspx#226155 > -- Albert Burbea Harishonim 8 Ramat Gan 52502, Israel Tel/Fax + 972-3-7526016 Mobile: +972-52-3541842 -------------- next part -------------- An HTML attachment was scrubbed... URL: From khilman at deeprootsystems.com Tue Sep 14 13:50:39 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Tue, 14 Sep 2010 11:50:39 -0700 Subject: [PATCH 0/9] post cpdma/mdio refactoring fixes In-Reply-To: <1284401251-8846-1-git-send-email-cyril@ti.com> (Cyril Chemparathy's message of "Mon, 13 Sep 2010 14:07:22 -0400") References: <1284401251-8846-1-git-send-email-cyril@ti.com> Message-ID: <87hbhsnoqo.fsf@deeprootsystems.com> Cyril Chemparathy writes: > This series consists of fixes for issues found during broader testing of the > davinci cpdma/mdio separation series. > > The fixes included here are: > > 1. Ability to force 100/full rather than auto-detect phy. This is necessary > for the external switch on the da830 evm platform > > 2. Fix end-of-queue requeue to include checks at submission time (in > addition to pre-existing completion time checks). > > 3. Cleanups to rx path error handling. This prevents unnecessary stack > dumps for perfectly legal situations. > > 4. Work around for emac-soft-reset tie-up to mdio controller. This affects > all da8xx family devices (and possibly am35xx as well). > > 5. Reworked hard-coded scan-time estimate to use a more accurate calculated > number instead. > > 6. Code to generate cpdma register dumps, useful during debug. > > > Many thanks to Mike and Caglar for patiently working with me through these > issues Thanks for working with them to resolve these issues. > I've taken the liberty of adding their sign offs. A sign-off is only for those on the delivery path of the patch. Can you update changing those to Tested-By tags? If you prefer, you can respin the original series with these fixes included instead of creating a separate series. I will then just drop the original, and queue the new one. Thanks, Kevin > Cyril Chemparathy (9): > net: davinci_emac: allow forced 100/full via phy_id > davinci: specify phy_id rather than auto-detect > net: davinci_cpdma: requeue on early end-of-queue > net: davinci_emac: fix rx error handling > net: davinci_mdio: separate out controller reset > net: davinci_mdio: use calculated bus access times > net: davinci_mdio: work around emac soft-reset during i/o > net: davinci_cpdma: add register dump routines > net: davinci_emac: extended register dumps on tx timeout > > arch/arm/mach-davinci/board-da830-evm.c | 2 + > arch/arm/mach-davinci/board-da850-evm.c | 3 + > arch/arm/mach-davinci/board-dm365-evm.c | 4 + > arch/arm/mach-davinci/board-dm644x-evm.c | 3 + > arch/arm/mach-davinci/board-dm646x-evm.c | 5 + > arch/arm/mach-davinci/board-mityomapl138.c | 3 + > arch/arm/mach-davinci/board-neuros-osd2.c | 4 + > arch/arm/mach-davinci/board-sffsdr.c | 4 + > drivers/net/davinci_cpdma.c | 132 ++++++++++++++++++- > drivers/net/davinci_cpdma.h | 3 + > drivers/net/davinci_emac.c | 31 ++++- > drivers/net/davinci_mdio.c | 195 ++++++++++++++++++++-------- > include/linux/davinci_emac.h | 7 + > 13 files changed, 334 insertions(+), 62 deletions(-) > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo at vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html From cyril at ti.com Tue Sep 14 16:10:04 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 14 Sep 2010 17:10:04 -0400 Subject: [PATCH v4 02/10] davinci: add mdio platform devices In-Reply-To: <1284498612-25294-1-git-send-email-cyril@ti.com> References: <1284498612-25294-1-git-send-email-cyril@ti.com> Message-ID: <1284498612-25294-3-git-send-email-cyril@ti.com> This patch adds mdio platform devices on SoCs that have the necessary hardware. Clock lookup entries (aliases) have also been added, so that the MDIO and EMAC drivers can independently enable/disable a shared underlying clock. Further, the EMAC MMR region has been split down into separate MDIO and EMAC regions. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- arch/arm/mach-davinci/devices-da8xx.c | 29 +++++++++++++++++++++++++- arch/arm/mach-davinci/dm365.c | 22 +++++++++++++++++++- arch/arm/mach-davinci/dm644x.c | 22 +++++++++++++++++++- arch/arm/mach-davinci/dm646x.c | 21 ++++++++++++++++++- arch/arm/mach-davinci/include/mach/dm365.h | 1 + arch/arm/mach-davinci/include/mach/dm644x.h | 1 + arch/arm/mach-davinci/include/mach/dm646x.h | 1 + 7 files changed, 92 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index caeb7f4..9039221 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -352,7 +352,7 @@ int __init da8xx_register_watchdog(void) static struct resource da8xx_emac_resources[] = { { .start = DA8XX_EMAC_CPPI_PORT_BASE, - .end = DA8XX_EMAC_CPPI_PORT_BASE + 0x5000 - 1, + .end = DA8XX_EMAC_CPPI_PORT_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -396,9 +396,34 @@ static struct platform_device da8xx_emac_device = { .resource = da8xx_emac_resources, }; +static struct resource da8xx_mdio_resources[] = { + { + .start = DA8XX_EMAC_MDIO_BASE, + .end = DA8XX_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device da8xx_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(da8xx_mdio_resources), + .resource = da8xx_mdio_resources, +}; + int __init da8xx_register_emac(void) { - return platform_device_register(&da8xx_emac_device); + int ret; + + ret = platform_device_register(&da8xx_mdio_device); + if (ret < 0) + return ret; + ret = platform_device_register(&da8xx_emac_device); + if (ret < 0) + return ret; + ret = clk_add_alias(NULL, dev_name(&da8xx_mdio_device.dev), + NULL, &da8xx_emac_device.dev); + return ret; } static struct resource da830_mcasp1_resources[] = { diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 6b6f4c6..71f0f9d 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -699,7 +699,7 @@ static struct emac_platform_data dm365_emac_pdata = { static struct resource dm365_emac_resources[] = { { .start = DM365_EMAC_BASE, - .end = DM365_EMAC_BASE + 0x47ff, + .end = DM365_EMAC_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -734,6 +734,21 @@ static struct platform_device dm365_emac_device = { .resource = dm365_emac_resources, }; +static struct resource dm365_mdio_resources[] = { + { + .start = DM365_EMAC_MDIO_BASE, + .end = DM365_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device dm365_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(dm365_mdio_resources), + .resource = dm365_mdio_resources, +}; + static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = { [IRQ_VDINT0] = 2, [IRQ_VDINT1] = 6, @@ -1220,7 +1235,12 @@ static int __init dm365_init_devices(void) davinci_cfg_reg(DM365_INT_EDMA_CC); platform_device_register(&dm365_edma_device); + + platform_device_register(&dm365_mdio_device); platform_device_register(&dm365_emac_device); + clk_add_alias(NULL, dev_name(&dm365_mdio_device.dev), + NULL, &dm365_emac_device.dev); + /* Add isif clock alias */ clk_add_alias("master", dm365_isif_dev.name, "vpss_master", NULL); platform_device_register(&dm365_vpss_device); diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 40fec31..c103b2c 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -330,7 +330,7 @@ static struct emac_platform_data dm644x_emac_pdata = { static struct resource dm644x_emac_resources[] = { { .start = DM644X_EMAC_BASE, - .end = DM644X_EMAC_BASE + 0x47ff, + .end = DM644X_EMAC_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -350,6 +350,21 @@ static struct platform_device dm644x_emac_device = { .resource = dm644x_emac_resources, }; +static struct resource dm644x_mdio_resources[] = { + { + .start = DM644X_EMAC_MDIO_BASE, + .end = DM644X_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device dm644x_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(dm644x_mdio_resources), + .resource = dm644x_mdio_resources, +}; + /* * Device specific mux setup * @@ -777,7 +792,12 @@ static int __init dm644x_init_devices(void) clk_add_alias("master", dm644x_ccdc_dev.name, "vpss_master", NULL); clk_add_alias("slave", dm644x_ccdc_dev.name, "vpss_slave", NULL); platform_device_register(&dm644x_edma_device); + + platform_device_register(&dm644x_mdio_device); platform_device_register(&dm644x_emac_device); + clk_add_alias(NULL, dev_name(&dm644x_mdio_device.dev), + NULL, &dm644x_emac_device.dev); + platform_device_register(&dm644x_vpss_device); platform_device_register(&dm644x_ccdc_dev); platform_device_register(&vpfe_capture_dev); diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index e4a3df1..8da886b 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -366,7 +366,7 @@ static struct emac_platform_data dm646x_emac_pdata = { static struct resource dm646x_emac_resources[] = { { .start = DM646X_EMAC_BASE, - .end = DM646X_EMAC_BASE + 0x47ff, + .end = DM646X_EMAC_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -401,6 +401,21 @@ static struct platform_device dm646x_emac_device = { .resource = dm646x_emac_resources, }; +static struct resource dm646x_mdio_resources[] = { + { + .start = DM646X_EMAC_MDIO_BASE, + .end = DM646X_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device dm646x_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(dm646x_mdio_resources), + .resource = dm646x_mdio_resources, +}; + /* * Device specific mux setup * @@ -897,7 +912,11 @@ static int __init dm646x_init_devices(void) if (!cpu_is_davinci_dm646x()) return 0; + platform_device_register(&dm646x_mdio_device); platform_device_register(&dm646x_emac_device); + clk_add_alias(NULL, dev_name(&dm646x_mdio_device.dev), + NULL, &dm646x_emac_device.dev); + return 0; } postcore_initcall(dm646x_init_devices); diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h index ea5df3b..dbb5052 100644 --- a/arch/arm/mach-davinci/include/mach/dm365.h +++ b/arch/arm/mach-davinci/include/mach/dm365.h @@ -21,6 +21,7 @@ #include #define DM365_EMAC_BASE (0x01D07000) +#define DM365_EMAC_MDIO_BASE (DM365_EMAC_BASE + 0x4000) #define DM365_EMAC_CNTRL_OFFSET (0x0000) #define DM365_EMAC_CNTRL_MOD_OFFSET (0x3000) #define DM365_EMAC_CNTRL_RAM_OFFSET (0x1000) diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h index 6fca568..5159117 100644 --- a/arch/arm/mach-davinci/include/mach/dm644x.h +++ b/arch/arm/mach-davinci/include/mach/dm644x.h @@ -28,6 +28,7 @@ #include #define DM644X_EMAC_BASE (0x01C80000) +#define DM644X_EMAC_MDIO_BASE (DM644X_EMAC_BASE + 0x4000) #define DM644X_EMAC_CNTRL_OFFSET (0x0000) #define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000) diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h index 0a27ee9..1c4dca9 100644 --- a/arch/arm/mach-davinci/include/mach/dm646x.h +++ b/arch/arm/mach-davinci/include/mach/dm646x.h @@ -19,6 +19,7 @@ #include #define DM646X_EMAC_BASE (0x01C80000) +#define DM646X_EMAC_MDIO_BASE (DM646X_EMAC_BASE + 0x4000) #define DM646X_EMAC_CNTRL_OFFSET (0x0000) #define DM646X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM646X_EMAC_CNTRL_RAM_OFFSET (0x2000) -- 1.7.0.4 From cyril at ti.com Tue Sep 14 16:10:02 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 14 Sep 2010 17:10:02 -0400 Subject: [PATCH v4 00/10] split out emac cpdma and mdio for reuse Message-ID: <1284498612-25294-1-git-send-email-cyril@ti.com> Davinci's EMAC device has an in-built MDIO controller and a CPDMA engine. These hardware modules are not restricted to EMAC device alone. For example, CPSW3G (3-port gigabit ethernet switch) hardware uses these very same modules internally. This patch series separates out EMAC's MDIO and CPDMA functionality, allowing these individual pieces to be reused across TI hardware. This patch series has been broadly organized as follows: MDIO: - Add new functionality netdev: separate out davinci mdio controller code - Hookup new functionality davinci: add mdio platform devices omap: add mdio platform devices netdev: switch davinci emac to new mdio driver - Cleanup left over cruft davinci: cleanup unused davinci mdio arch code omap: cleanup unused davinci mdio arch code netdev: cleanup unused davinci mdio emac code CPDMA: - Add new functionality netdev: separate out davinci cpdma controller code - Hookup new functionality netdev: switch davinci emac to new cpdma layer - Cleanup left over cruft netdev: cleanup unused davinci emac cpdma code This series has been tested on dm365 and tnetv107x (with additional cpsw patches) hardware. Although am3517 (omap) board support code has been updated as needed, emac does not work on this platform. Changes from v1: 1. Fixed memory leak in cpdma_chan_create() failure case 2. Included new omap patches for am3517, avoids build breakage Changes from v2: 1. Updated series to include mityomapl138 board 2. Minor white-space fixes Changes from v3 (rolled in "post cpdma/mdio refactoring fixes" series): 1. allow forced 100/full mode instead of phy auto-detect 2. specify phy_id on boards that had a phy_mask defined earlier 3. requeue cpdma descriptors when EOQ at submit 4. use calculated mdio bus access times instead of hardcoded delays 5. work around emac soft-reset impact on mdio controller state 6. extend register dumps to include cpdma registers Cyril Chemparathy (10): net: davinci_emac: separate out davinci mdio davinci: add mdio platform devices omap: add mdio platform devices net: davinci_emac: switch to new mdio davinci: cleanup mdio arch code and switch to phy_id omap: cleanup unused davinci mdio arch code net: davinci_emac: cleanup unused mdio emac code net: davinci_emac: separate out cpdma code net: davinci_emac: switch to new cpdma layer net: davinci_emac: cleanup unused cpdma code arch/arm/mach-davinci/board-da830-evm.c | 7 +- arch/arm/mach-davinci/board-da850-evm.c | 7 +- arch/arm/mach-davinci/board-dm365-evm.c | 7 +- arch/arm/mach-davinci/board-dm644x-evm.c | 8 +- arch/arm/mach-davinci/board-dm646x-evm.c | 7 +- arch/arm/mach-davinci/board-mityomapl138.c | 8 +- arch/arm/mach-davinci/board-neuros-osd2.c | 7 +- arch/arm/mach-davinci/board-sffsdr.c | 7 +- arch/arm/mach-davinci/devices-da8xx.c | 31 +- arch/arm/mach-davinci/dm365.c | 23 +- arch/arm/mach-davinci/dm644x.c | 23 +- arch/arm/mach-davinci/dm646x.c | 22 +- arch/arm/mach-davinci/include/mach/dm365.h | 2 +- arch/arm/mach-davinci/include/mach/dm644x.h | 2 +- arch/arm/mach-davinci/include/mach/dm646x.h | 2 +- arch/arm/mach-omap2/board-am3517evm.c | 31 +- drivers/net/Kconfig | 21 + drivers/net/Makefile | 2 + drivers/net/davinci_cpdma.c | 965 +++++++++++++++++++ drivers/net/davinci_cpdma.h | 108 +++ drivers/net/davinci_emac.c | 1338 ++++----------------------- drivers/net/davinci_mdio.c | 475 ++++++++++ include/linux/davinci_emac.h | 16 +- 23 files changed, 1894 insertions(+), 1225 deletions(-) create mode 100644 drivers/net/davinci_cpdma.c create mode 100644 drivers/net/davinci_cpdma.h create mode 100644 drivers/net/davinci_mdio.c From cyril at ti.com Tue Sep 14 16:10:05 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 14 Sep 2010 17:10:05 -0400 Subject: [PATCH v4 03/10] omap: add mdio platform devices In-Reply-To: <1284498612-25294-1-git-send-email-cyril@ti.com> References: <1284498612-25294-1-git-send-email-cyril@ti.com> Message-ID: <1284498612-25294-4-git-send-email-cyril@ti.com> This patch adds mdio platform devices on SoCs that have the necessary hardware. Clock lookup entries (aliases) have also been added, so that the MDIO and EMAC drivers can independently enable/disable a shared underlying clock. Further, the EMAC MMR region has been split down into separate MDIO and EMAC regions. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- arch/arm/mach-omap2/board-am3517evm.c | 27 ++++++++++++++++++++++++++- 1 files changed, 26 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 4d0f585..5dd1b73 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,27 @@ #define AM35XX_EVM_PHY_MASK (0xF) #define AM35XX_EVM_MDIO_FREQUENCY (1000000) +static struct mdio_platform_data am3517_evm_mdio_pdata = { + .bus_freq = AM35XX_EVM_MDIO_FREQUENCY, +}; + +static struct resource am3517_mdio_resources[] = { + { + .start = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET, + .end = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET + + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device am3517_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(am3517_mdio_resources), + .resource = am3517_mdio_resources, + .dev.platform_data = &am3517_evm_mdio_pdata, +}; + static struct emac_platform_data am3517_evm_emac_pdata = { .phy_mask = AM35XX_EVM_PHY_MASK, .mdio_max_freq = AM35XX_EVM_MDIO_FREQUENCY, @@ -50,7 +72,7 @@ static struct emac_platform_data am3517_evm_emac_pdata = { static struct resource am3517_emac_resources[] = { { .start = AM35XX_IPSS_EMAC_BASE, - .end = AM35XX_IPSS_EMAC_BASE + 0x3FFFF, + .end = AM35XX_IPSS_EMAC_BASE + 0x2FFFF, .flags = IORESOURCE_MEM, }, { @@ -121,6 +143,9 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata) pdata->interrupt_disable = am3517_disable_ethernet_int; am3517_emac_device.dev.platform_data = pdata; platform_device_register(&am3517_emac_device); + platform_device_register(&am3517_mdio_device); + clk_add_alias(NULL, dev_name(&am3517_mdio_device.dev), + NULL, &am3517_emac_device.dev); regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); regval = regval & (~(AM35XX_CPGMACSS_SW_RST)); -- 1.7.0.4 From cyril at ti.com Tue Sep 14 16:10:08 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 14 Sep 2010 17:10:08 -0400 Subject: [PATCH v4 06/10] omap: cleanup unused davinci mdio arch code In-Reply-To: <1284498612-25294-1-git-send-email-cyril@ti.com> References: <1284498612-25294-1-git-send-email-cyril@ti.com> Message-ID: <1284498612-25294-7-git-send-email-cyril@ti.com> This patch removes davinci architecture code that has now been rendered useless by the previous patches in the MDIO separation series. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- arch/arm/mach-omap2/board-am3517evm.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 5dd1b73..5225df6 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -39,7 +39,6 @@ #include "mux.h" -#define AM35XX_EVM_PHY_MASK (0xF) #define AM35XX_EVM_MDIO_FREQUENCY (1000000) static struct mdio_platform_data am3517_evm_mdio_pdata = { @@ -64,8 +63,6 @@ static struct platform_device am3517_mdio_device = { }; static struct emac_platform_data am3517_evm_emac_pdata = { - .phy_mask = AM35XX_EVM_PHY_MASK, - .mdio_max_freq = AM35XX_EVM_MDIO_FREQUENCY, .rmii_en = 1, }; @@ -135,7 +132,6 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata) pdata->ctrl_reg_offset = AM35XX_EMAC_CNTRL_OFFSET; pdata->ctrl_mod_reg_offset = AM35XX_EMAC_CNTRL_MOD_OFFSET; pdata->ctrl_ram_offset = AM35XX_EMAC_CNTRL_RAM_OFFSET; - pdata->mdio_reg_offset = AM35XX_EMAC_MDIO_OFFSET; pdata->ctrl_ram_size = AM35XX_EMAC_CNTRL_RAM_SIZE; pdata->version = EMAC_VERSION_2; pdata->hw_ram_addr = AM35XX_EMAC_HW_RAM_ADDR; -- 1.7.0.4 From cyril at ti.com Tue Sep 14 16:10:06 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 14 Sep 2010 17:10:06 -0400 Subject: [PATCH v4 04/10] net: davinci_emac: switch to new mdio In-Reply-To: <1284498612-25294-1-git-send-email-cyril@ti.com> References: <1284498612-25294-1-git-send-email-cyril@ti.com> Message-ID: <1284498612-25294-5-git-send-email-cyril@ti.com> This patch switches the emac implementation over to the newly separated MDIO driver. With this, the mdio bus frequency defaults to a safe 2.2MHz. Boards may optionally specify a bus frequency via platform data. The phy identification scheme has been modified to use a phy bus id instead of a mask. This largely serves to eliminate the "phy search" code in emac init. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- drivers/net/Kconfig | 1 + drivers/net/davinci_emac.c | 88 ++++++++++++++--------------------------- include/linux/davinci_emac.h | 9 ++++ 3 files changed, 40 insertions(+), 58 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c5c86e0..911e7f1 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -951,6 +951,7 @@ config NET_NETX config TI_DAVINCI_EMAC tristate "TI DaVinci EMAC Support" depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + select TI_DAVINCI_MDIO select PHYLIB help This driver supports TI's DaVinci Ethernet . diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 7fbd052..997f599 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -500,6 +500,7 @@ struct emac_priv { u32 phy_mask; /* mii_bus,phy members */ struct mii_bus *mii_bus; + const char *phy_id; struct phy_device *phydev; spinlock_t lock; /*platform specific members*/ @@ -686,7 +687,7 @@ static int emac_get_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) { struct emac_priv *priv = netdev_priv(ndev); - if (priv->phy_mask) + if (priv->phydev) return phy_ethtool_gset(priv->phydev, ecmd); else return -EOPNOTSUPP; @@ -704,7 +705,7 @@ static int emac_get_settings(struct net_device *ndev, static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) { struct emac_priv *priv = netdev_priv(ndev); - if (priv->phy_mask) + if (priv->phydev) return phy_ethtool_sset(priv->phydev, ecmd); else return -EOPNOTSUPP; @@ -841,7 +842,7 @@ static void emac_update_phystatus(struct emac_priv *priv) mac_control = emac_read(EMAC_MACCONTROL); cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ? DUPLEX_FULL : DUPLEX_HALF; - if (priv->phy_mask) + if (priv->phydev) new_duplex = priv->phydev->duplex; else new_duplex = DUPLEX_FULL; @@ -2485,6 +2486,11 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) return -EOPNOTSUPP; } +static int match_first_device(struct device *dev, void *data) +{ + return 1; +} + /** * emac_dev_open: EMAC device open * @ndev: The DaVinci EMAC network adapter @@ -2499,7 +2505,6 @@ static int emac_dev_open(struct net_device *ndev) { struct device *emac_dev = &ndev->dev; u32 rc, cnt, ch; - int phy_addr; struct resource *res; int q, m; int i = 0; @@ -2560,28 +2565,26 @@ static int emac_dev_open(struct net_device *ndev) emac_set_coalesce(ndev, &coal); } - /* find the first phy */ priv->phydev = NULL; - if (priv->phy_mask) { - emac_mii_reset(priv->mii_bus); - for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { - if (priv->mii_bus->phy_map[phy_addr]) { - priv->phydev = priv->mii_bus->phy_map[phy_addr]; - break; - } - } + /* use the first phy on the bus if pdata did not give us a phy id */ + if (!priv->phy_id) { + struct device *phy; - if (!priv->phydev) { - printk(KERN_ERR "%s: no PHY found\n", ndev->name); - return -1; - } + phy = bus_find_device(&mdio_bus_type, NULL, NULL, + match_first_device); + if (phy) + priv->phy_id = dev_name(phy); + } - priv->phydev = phy_connect(ndev, dev_name(&priv->phydev->dev), - &emac_adjust_link, 0, PHY_INTERFACE_MODE_MII); + if (priv->phy_id && *priv->phy_id) { + priv->phydev = phy_connect(ndev, priv->phy_id, + &emac_adjust_link, 0, + PHY_INTERFACE_MODE_MII); if (IS_ERR(priv->phydev)) { - printk(KERN_ERR "%s: Could not attach to PHY\n", - ndev->name); + dev_err(emac_dev, "could not connect to phy %s\n", + priv->phy_id); + priv->phydev = NULL; return PTR_ERR(priv->phydev); } @@ -2589,12 +2592,13 @@ static int emac_dev_open(struct net_device *ndev) priv->speed = 0; priv->duplex = ~0; - printk(KERN_INFO "%s: attached PHY driver [%s] " - "(mii_bus:phy_addr=%s, id=%x)\n", ndev->name, + dev_info(emac_dev, "attached PHY driver [%s] " + "(mii_bus:phy_addr=%s, id=%x)\n", priv->phydev->drv->name, dev_name(&priv->phydev->dev), priv->phydev->phy_id); - } else{ + } else { /* No PHY , fix the link, speed and duplex settings */ + dev_notice(emac_dev, "no phy, defaulting to 100/full\n"); priv->link = 1; priv->speed = SPEED_100; priv->duplex = DUPLEX_FULL; @@ -2607,7 +2611,7 @@ static int emac_dev_open(struct net_device *ndev) if (netif_msg_drv(priv)) dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name); - if (priv->phy_mask) + if (priv->phydev) phy_start(priv->phydev); return 0; @@ -2794,7 +2798,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) /* MAC addr and PHY mask , RMII enable info from platform_data */ memcpy(priv->mac_addr, pdata->mac_addr, 6); - priv->phy_mask = pdata->phy_mask; + priv->phy_id = pdata->phy_id; priv->rmii_en = pdata->rmii_en; priv->version = pdata->version; priv->int_enable = pdata->interrupt_enable; @@ -2871,32 +2875,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) } - /* MII/Phy intialisation, mdio bus registration */ - emac_mii = mdiobus_alloc(); - if (emac_mii == NULL) { - dev_err(emac_dev, "DaVinci EMAC: Error allocating mii_bus\n"); - rc = -ENOMEM; - goto mdio_alloc_err; - } - - priv->mii_bus = emac_mii; - emac_mii->name = "emac-mii", - emac_mii->read = emac_mii_read, - emac_mii->write = emac_mii_write, - emac_mii->reset = emac_mii_reset, - emac_mii->irq = mii_irqs, - emac_mii->phy_mask = ~(priv->phy_mask); - emac_mii->parent = &pdev->dev; - emac_mii->priv = priv->remap_addr + pdata->mdio_reg_offset; - snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", priv->pdev->id); - mdio_max_freq = pdata->mdio_max_freq; - emac_mii->reset(emac_mii); - - /* Register the MII bus */ - rc = mdiobus_register(emac_mii); - if (rc) - goto mdiobus_quit; - if (netif_msg_probe(priv)) { dev_notice(emac_dev, "DaVinci EMAC Probe found device "\ "(regs: %p, irq: %d)\n", @@ -2904,11 +2882,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) } return 0; -mdiobus_quit: - mdiobus_free(emac_mii); - netdev_reg_err: -mdio_alloc_err: clk_disable(emac_clk); no_irq_res: res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -2938,8 +2912,6 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mdiobus_unregister(priv->mii_bus); - mdiobus_free(priv->mii_bus); release_mem_region(res->start, res->end - res->start + 1); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index a04fd8c..46a759f 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -28,6 +28,15 @@ struct emac_platform_data { u32 ctrl_ram_size; u32 phy_mask; u32 mdio_max_freq; + + /* + * phy_id can be one of the following: + * - NULL : use the first phy on the bus, + * - "" : force to 100/full, no mdio control + * - ":" : use the specified bus and phy + */ + const char *phy_id; + u8 rmii_en; u8 version; void (*interrupt_enable) (void); -- 1.7.0.4 From cyril at ti.com Tue Sep 14 16:10:03 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 14 Sep 2010 17:10:03 -0400 Subject: [PATCH v4 01/10] net: davinci_emac: separate out davinci mdio In-Reply-To: <1284498612-25294-1-git-send-email-cyril@ti.com> References: <1284498612-25294-1-git-send-email-cyril@ti.com> Message-ID: <1284498612-25294-2-git-send-email-cyril@ti.com> Davinci's MDIO controller is present on other TI devices, without an accompanying EMAC. For example, on tnetv107x, the same MDIO module is used in conjunction with a 3-port switch hardware. By separating the MDIO controller code into its own platform driver, this patch allows common logic to be reused on such platforms. Signed-off-by: Cyril Chemparathy Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- drivers/net/Kconfig | 10 + drivers/net/Makefile | 1 + drivers/net/davinci_mdio.c | 475 ++++++++++++++++++++++++++++++++++++++++++ include/linux/davinci_emac.h | 4 + 4 files changed, 490 insertions(+), 0 deletions(-) create mode 100644 drivers/net/davinci_mdio.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2cc81a5..c5c86e0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -958,6 +958,16 @@ config TI_DAVINCI_EMAC To compile this driver as a module, choose M here: the module will be called davinci_emac_driver. This is recommended. +config TI_DAVINCI_MDIO + tristate "TI DaVinci MDIO Support" + depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + select PHYLIB + help + This driver supports TI's DaVinci MDIO module. + + To compile this driver as a module, choose M here: the module + will be called davinci_mdio. This is recommended. + config DM9000 tristate "DM9000 support" depends on ARM || BLACKFIN || MIPS diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 3e8f150..d38a7ab 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_MDIO) += mdio.o obj-$(CONFIG_PHYLIB) += phy/ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o +obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_E1000E) += e1000e/ diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c new file mode 100644 index 0000000..7615040 --- /dev/null +++ b/drivers/net/davinci_mdio.c @@ -0,0 +1,475 @@ +/* + * DaVinci MDIO Module driver + * + * Copyright (C) 2010 Texas Instruments. + * + * Shamelessly ripped out of davinci_emac.c, original copyrights follow: + * + * Copyright (C) 2009 Texas Instruments. + * + * --------------------------------------------------------------------------- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * --------------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This timeout definition is a worst-case ultra defensive measure against + * unexpected controller lock ups. Ideally, we should never ever hit this + * scenario in practice. + */ +#define MDIO_TIMEOUT 100 /* msecs */ + +#define PHY_REG_MASK 0x1f +#define PHY_ID_MASK 0x1f + +#define DEF_OUT_FREQ 2200000 /* 2.2 MHz */ + +struct davinci_mdio_regs { + u32 version; + u32 control; +#define CONTROL_IDLE BIT(31) +#define CONTROL_ENABLE BIT(30) +#define CONTROL_MAX_DIV (0xff) + + u32 alive; + u32 link; + u32 linkintraw; + u32 linkintmasked; + u32 __reserved_0[2]; + u32 userintraw; + u32 userintmasked; + u32 userintmaskset; + u32 userintmaskclr; + u32 __reserved_1[20]; + + struct { + u32 access; +#define USERACCESS_GO BIT(31) +#define USERACCESS_WRITE BIT(30) +#define USERACCESS_ACK BIT(29) +#define USERACCESS_READ (0) +#define USERACCESS_DATA (0xffff) + + u32 physel; + } user[0]; +}; + +struct mdio_platform_data default_pdata = { + .bus_freq = DEF_OUT_FREQ, +}; + +struct davinci_mdio_data { + struct mdio_platform_data pdata; + struct davinci_mdio_regs __iomem *regs; + spinlock_t lock; + struct clk *clk; + struct device *dev; + struct mii_bus *bus; + bool suspended; + unsigned long access_time; /* jiffies */ +}; + +static void __davinci_mdio_reset(struct davinci_mdio_data *data) +{ + u32 mdio_in, div, mdio_out_khz, access_time; + + mdio_in = clk_get_rate(data->clk); + div = (mdio_in / data->pdata.bus_freq) - 1; + if (div > CONTROL_MAX_DIV) + div = CONTROL_MAX_DIV; + + /* set enable and clock divider */ + __raw_writel(div | CONTROL_ENABLE, &data->regs->control); + + /* + * One mdio transaction consists of: + * 32 bits of preamble + * 32 bits of transferred data + * 24 bits of bus yield (not needed unless shared?) + */ + mdio_out_khz = mdio_in / (1000 * (div + 1)); + access_time = (88 * 1000) / mdio_out_khz; + + /* + * In the worst case, we could be kicking off a user-access immediately + * after the mdio bus scan state-machine triggered its own read. If + * so, our request could get deferred by one access cycle. We + * defensively allow for 4 access cycles. + */ + data->access_time = usecs_to_jiffies(access_time * 4); + if (!data->access_time) + data->access_time = 1; +} + +static int davinci_mdio_reset(struct mii_bus *bus) +{ + struct davinci_mdio_data *data = bus->priv; + u32 phy_mask, ver; + + __davinci_mdio_reset(data); + + /* wait for scan logic to settle */ + msleep(PHY_MAX_ADDR * data->access_time); + + /* dump hardware version info */ + ver = __raw_readl(&data->regs->version); + dev_info(data->dev, "davinci mdio revision %d.%d\n", + (ver >> 8) & 0xff, ver & 0xff); + + /* get phy mask from the alive register */ + phy_mask = __raw_readl(&data->regs->alive); + if (phy_mask) { + /* restrict mdio bus to live phys only */ + dev_info(data->dev, "detected phy mask %x\n", ~phy_mask); + phy_mask = ~phy_mask; + } else { + /* desperately scan all phys */ + dev_warn(data->dev, "no live phy, scanning all\n"); + phy_mask = 0; + } + data->bus->phy_mask = phy_mask; + + return 0; +} + +/* wait until hardware is ready for another user access */ +static inline int wait_for_user_access(struct davinci_mdio_data *data) +{ + struct davinci_mdio_regs __iomem *regs = data->regs; + unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT); + u32 reg; + + while (time_after(timeout, jiffies)) { + reg = __raw_readl(®s->user[0].access); + if ((reg & USERACCESS_GO) == 0) + return 0; + + reg = __raw_readl(®s->control); + if ((reg & CONTROL_IDLE) == 0) + continue; + + /* + * An emac soft_reset may have clobbered the mdio controller's + * state machine. We need to reset and retry the current + * operation + */ + dev_warn(data->dev, "resetting idled controller\n"); + __davinci_mdio_reset(data); + return -EAGAIN; + } + dev_err(data->dev, "timed out waiting for user access\n"); + return -ETIMEDOUT; +} + +/* wait until hardware state machine is idle */ +static inline int wait_for_idle(struct davinci_mdio_data *data) +{ + struct davinci_mdio_regs __iomem *regs = data->regs; + unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT); + + while (time_after(timeout, jiffies)) { + if (__raw_readl(®s->control) & CONTROL_IDLE) + return 0; + } + dev_err(data->dev, "timed out waiting for idle\n"); + return -ETIMEDOUT; +} + +static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg) +{ + struct davinci_mdio_data *data = bus->priv; + u32 reg; + int ret; + + if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) + return -EINVAL; + + spin_lock(&data->lock); + + if (data->suspended) { + spin_unlock(&data->lock); + return -ENODEV; + } + + reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) | + (phy_id << 16)); + + while (1) { + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + if (ret < 0) + break; + + __raw_writel(reg, &data->regs->user[0].access); + + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + if (ret < 0) + break; + + reg = __raw_readl(&data->regs->user[0].access); + ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO; + break; + } + + spin_unlock(&data->lock); + + return ret; +} + +static int davinci_mdio_write(struct mii_bus *bus, int phy_id, + int phy_reg, u16 phy_data) +{ + struct davinci_mdio_data *data = bus->priv; + u32 reg; + int ret; + + if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) + return -EINVAL; + + spin_lock(&data->lock); + + if (data->suspended) { + spin_unlock(&data->lock); + return -ENODEV; + } + + reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) | + (phy_id << 16) | (phy_data & USERACCESS_DATA)); + + while (1) { + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + if (ret < 0) + break; + + __raw_writel(reg, &data->regs->user[0].access); + + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + break; + } + + spin_unlock(&data->lock); + + return 0; +} + +static int __devinit davinci_mdio_probe(struct platform_device *pdev) +{ + struct mdio_platform_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct davinci_mdio_data *data; + struct resource *res; + struct phy_device *phy; + int ret, addr; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + dev_err(dev, "failed to alloc device data\n"); + return -ENOMEM; + } + + data->pdata = pdata ? (*pdata) : default_pdata; + + data->bus = mdiobus_alloc(); + if (!data->bus) { + dev_err(dev, "failed to alloc mii bus\n"); + ret = -ENOMEM; + goto bail_out; + } + + data->bus->name = dev_name(dev); + data->bus->read = davinci_mdio_read, + data->bus->write = davinci_mdio_write, + data->bus->reset = davinci_mdio_reset, + data->bus->parent = dev; + data->bus->priv = data; + snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); + + data->clk = clk_get(dev, NULL); + if (IS_ERR(data->clk)) { + data->clk = NULL; + dev_err(dev, "failed to get device clock\n"); + ret = PTR_ERR(data->clk); + goto bail_out; + } + + clk_enable(data->clk); + + dev_set_drvdata(dev, data); + data->dev = dev; + spin_lock_init(&data->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "could not find register map resource\n"); + ret = -ENOENT; + goto bail_out; + } + + res = devm_request_mem_region(dev, res->start, resource_size(res), + dev_name(dev)); + if (!res) { + dev_err(dev, "could not allocate register map resource\n"); + ret = -ENXIO; + goto bail_out; + } + + data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); + if (!data->regs) { + dev_err(dev, "could not map mdio registers\n"); + ret = -ENOMEM; + goto bail_out; + } + + /* register the mii bus */ + ret = mdiobus_register(data->bus); + if (ret) + goto bail_out; + + /* scan and dump the bus */ + for (addr = 0; addr < PHY_MAX_ADDR; addr++) { + phy = data->bus->phy_map[addr]; + if (phy) { + dev_info(dev, "phy[%d]: device %s, driver %s\n", + phy->addr, dev_name(&phy->dev), + phy->drv ? phy->drv->name : "unknown"); + } + } + + return 0; + +bail_out: + if (data->bus) + mdiobus_free(data->bus); + + if (data->clk) { + clk_disable(data->clk); + clk_put(data->clk); + } + + kfree(data); + + return ret; +} + +static int __devexit davinci_mdio_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct davinci_mdio_data *data = dev_get_drvdata(dev); + + if (data->bus) + mdiobus_free(data->bus); + + if (data->clk) { + clk_disable(data->clk); + clk_put(data->clk); + } + + dev_set_drvdata(dev, NULL); + + kfree(data); + + return 0; +} + +static int davinci_mdio_suspend(struct device *dev) +{ + struct davinci_mdio_data *data = dev_get_drvdata(dev); + u32 ctrl; + + spin_lock(&data->lock); + + /* shutdown the scan state machine */ + ctrl = __raw_readl(&data->regs->control); + ctrl &= ~CONTROL_ENABLE; + __raw_writel(ctrl, &data->regs->control); + wait_for_idle(data); + + if (data->clk) + clk_disable(data->clk); + + data->suspended = true; + spin_unlock(&data->lock); + + return 0; +} + +static int davinci_mdio_resume(struct device *dev) +{ + struct davinci_mdio_data *data = dev_get_drvdata(dev); + u32 ctrl; + + spin_lock(&data->lock); + if (data->clk) + clk_enable(data->clk); + + /* restart the scan state machine */ + ctrl = __raw_readl(&data->regs->control); + ctrl |= CONTROL_ENABLE; + __raw_writel(ctrl, &data->regs->control); + + data->suspended = false; + spin_unlock(&data->lock); + + return 0; +} + +static const struct dev_pm_ops davinci_mdio_pm_ops = { + .suspend = davinci_mdio_suspend, + .resume = davinci_mdio_resume, +}; + +static struct platform_driver davinci_mdio_driver = { + .driver = { + .name = "davinci_mdio", + .owner = THIS_MODULE, + .pm = &davinci_mdio_pm_ops, + }, + .probe = davinci_mdio_probe, + .remove = __devexit_p(davinci_mdio_remove), +}; + +static int __init davinci_mdio_init(void) +{ + return platform_driver_register(&davinci_mdio_driver); +} +device_initcall(davinci_mdio_init); + +static void __exit davinci_mdio_exit(void) +{ + platform_driver_unregister(&davinci_mdio_driver); +} +module_exit(davinci_mdio_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("DaVinci MDIO driver"); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index 7c930db..a04fd8c 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -14,6 +14,10 @@ #include #include +struct mdio_platform_data { + unsigned long bus_freq; +}; + struct emac_platform_data { char mac_addr[ETH_ALEN]; u32 ctrl_reg_offset; -- 1.7.0.4 From cyril at ti.com Tue Sep 14 16:10:09 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 14 Sep 2010 17:10:09 -0400 Subject: [PATCH v4 07/10] net: davinci_emac: cleanup unused mdio emac code In-Reply-To: <1284498612-25294-1-git-send-email-cyril@ti.com> References: <1284498612-25294-1-git-send-email-cyril@ti.com> Message-ID: <1284498612-25294-8-git-send-email-cyril@ti.com> This patch removes code that has been rendered useless by the previous patches in this series. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- drivers/net/davinci_emac.c | 107 ------------------------------------------ include/linux/davinci_emac.h | 3 - 2 files changed, 0 insertions(+), 110 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 997f599..d4298cb 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -113,7 +113,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_FRAME_SIZE (1500 + 14 + 4 + 4) #define EMAC_DEF_TX_CH (0) /* Default 0th channel */ #define EMAC_DEF_RX_CH (0) /* Default 0th channel */ -#define EMAC_DEF_MDIO_TICK_MS (10) /* typically 1 tick=1 ms) */ #define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */ #define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */ #define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */ @@ -303,25 +302,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DM644X_INTMIN_INTVL 0x1 #define EMAC_DM644X_INTMAX_INTVL (EMAC_DM644X_EWINTCNT_MASK) -/* EMAC MDIO related */ -/* Mask & Control defines */ -#define MDIO_CONTROL_CLKDIV (0xFF) -#define MDIO_CONTROL_ENABLE BIT(30) -#define MDIO_USERACCESS_GO BIT(31) -#define MDIO_USERACCESS_WRITE BIT(30) -#define MDIO_USERACCESS_READ (0) -#define MDIO_USERACCESS_REGADR (0x1F << 21) -#define MDIO_USERACCESS_PHYADR (0x1F << 16) -#define MDIO_USERACCESS_DATA (0xFFFF) -#define MDIO_USERPHYSEL_LINKSEL BIT(7) -#define MDIO_VER_MODID (0xFFFF << 16) -#define MDIO_VER_REVMAJ (0xFF << 8) -#define MDIO_VER_REVMIN (0xFF) - -#define MDIO_USERACCESS(inst) (0x80 + (inst * 8)) -#define MDIO_USERPHYSEL(inst) (0x84 + (inst * 8)) -#define MDIO_CONTROL (0x04) - /* EMAC DM646X control module registers */ #define EMAC_DM646X_CMINTCTRL 0x0C #define EMAC_DM646X_CMRXINTEN 0x14 @@ -493,13 +473,6 @@ struct emac_priv { u32 mac_hash2; u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS]; u32 rx_addr_type; - /* periodic timer required for MDIO polling */ - struct timer_list periodic_timer; - u32 periodic_ticks; - u32 timer_active; - u32 phy_mask; - /* mii_bus,phy members */ - struct mii_bus *mii_bus; const char *phy_id; struct phy_device *phydev; spinlock_t lock; @@ -511,7 +484,6 @@ struct emac_priv { /* clock frequency for EMAC */ static struct clk *emac_clk; static unsigned long emac_bus_frequency; -static unsigned long mdio_max_freq; #define emac_virt_to_phys(addr, priv) \ (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \ @@ -549,9 +521,6 @@ static char *emac_rxhost_errcodes[16] = { #define emac_ctrl_read(reg) ioread32((priv->ctrl_base + (reg))) #define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg))) -#define emac_mdio_read(reg) ioread32(bus->priv + (reg)) -#define emac_mdio_write(reg, val) iowrite32(val, (bus->priv + (reg))) - /** * emac_dump_regs: Dump important EMAC registers to debug terminal * @priv: The DaVinci EMAC private adapter structure @@ -657,9 +626,6 @@ static void emac_dump_regs(struct emac_priv *priv) emac_read(EMAC_RXDMAOVERRUNS)); } -/************************************************************************* - * EMAC MDIO/Phy Functionality - *************************************************************************/ /** * emac_get_drvinfo: Get EMAC driver information * @ndev: The DaVinci EMAC network adapter @@ -2349,79 +2315,6 @@ void emac_poll_controller(struct net_device *ndev) } #endif -/* PHY/MII bus related */ - -/* Wait until mdio is ready for next command */ -#define MDIO_WAIT_FOR_USER_ACCESS\ - while ((emac_mdio_read((MDIO_USERACCESS(0))) &\ - MDIO_USERACCESS_GO) != 0) - -static int emac_mii_read(struct mii_bus *bus, int phy_id, int phy_reg) -{ - unsigned int phy_data = 0; - unsigned int phy_control; - - /* Wait until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - phy_control = (MDIO_USERACCESS_GO | - MDIO_USERACCESS_READ | - ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | - ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | - (phy_data & MDIO_USERACCESS_DATA)); - emac_mdio_write(MDIO_USERACCESS(0), phy_control); - - /* Wait until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - return emac_mdio_read(MDIO_USERACCESS(0)) & MDIO_USERACCESS_DATA; - -} - -static int emac_mii_write(struct mii_bus *bus, int phy_id, - int phy_reg, u16 phy_data) -{ - - unsigned int control; - - /* until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - control = (MDIO_USERACCESS_GO | - MDIO_USERACCESS_WRITE | - ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | - ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | - (phy_data & MDIO_USERACCESS_DATA)); - emac_mdio_write(MDIO_USERACCESS(0), control); - - return 0; -} - -static int emac_mii_reset(struct mii_bus *bus) -{ - unsigned int clk_div; - int mdio_bus_freq = emac_bus_frequency; - - if (mdio_max_freq && mdio_bus_freq) - clk_div = ((mdio_bus_freq / mdio_max_freq) - 1); - else - clk_div = 0xFF; - - clk_div &= MDIO_CONTROL_CLKDIV; - - /* Set enable and clock divider in MDIOControl */ - emac_mdio_write(MDIO_CONTROL, (clk_div | MDIO_CONTROL_ENABLE)); - - return 0; - -} - -static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, PHY_POLL }; - -/* emac_driver: EMAC MII bus structure */ - -static struct mii_bus *emac_mii; - static void emac_adjust_link(struct net_device *ndev) { struct emac_priv *priv = netdev_priv(ndev); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index 46a759f..5dd4285 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -24,10 +24,7 @@ struct emac_platform_data { u32 ctrl_mod_reg_offset; u32 ctrl_ram_offset; u32 hw_ram_addr; - u32 mdio_reg_offset; u32 ctrl_ram_size; - u32 phy_mask; - u32 mdio_max_freq; /* * phy_id can be one of the following: -- 1.7.0.4 From cyril at ti.com Tue Sep 14 16:10:07 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 14 Sep 2010 17:10:07 -0400 Subject: [PATCH v4 05/10] davinci: cleanup mdio arch code and switch to phy_id In-Reply-To: <1284498612-25294-1-git-send-email-cyril@ti.com> References: <1284498612-25294-1-git-send-email-cyril@ti.com> Message-ID: <1284498612-25294-6-git-send-email-cyril@ti.com> This patch removes davinci architecture code that has now been rendered useless by the previous patches in the MDIO separation series. In addition, the earlier phy_mask definitions have been replaced with corresponding phy_id definitions. Signed-off-by: Cyril Chemparathy Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- arch/arm/mach-davinci/board-da830-evm.c | 7 ++----- arch/arm/mach-davinci/board-da850-evm.c | 7 ++----- arch/arm/mach-davinci/board-dm365-evm.c | 7 ++----- arch/arm/mach-davinci/board-dm644x-evm.c | 8 ++------ arch/arm/mach-davinci/board-dm646x-evm.c | 7 ++----- arch/arm/mach-davinci/board-mityomapl138.c | 8 ++------ arch/arm/mach-davinci/board-neuros-osd2.c | 7 ++----- arch/arm/mach-davinci/board-sffsdr.c | 7 ++----- arch/arm/mach-davinci/devices-da8xx.c | 2 -- arch/arm/mach-davinci/dm365.c | 1 - arch/arm/mach-davinci/dm644x.c | 1 - arch/arm/mach-davinci/dm646x.c | 1 - arch/arm/mach-davinci/include/mach/dm365.h | 1 - arch/arm/mach-davinci/include/mach/dm644x.h | 1 - arch/arm/mach-davinci/include/mach/dm646x.h | 1 - 15 files changed, 16 insertions(+), 50 deletions(-) diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index ef1ab0b..1bb89d3 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -31,9 +31,7 @@ #include #include -#define DA830_EVM_PHY_MASK 0x0 -#define DA830_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ - +#define DA830_EVM_PHY_ID "" /* * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4]. */ @@ -558,9 +556,8 @@ static __init void da830_evm_init(void) da830_evm_usb_init(); - soc_info->emac_pdata->phy_mask = DA830_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DA830_EVM_MDIO_FREQUENCY; soc_info->emac_pdata->rmii_en = 1; + soc_info->emac_pdata->phy_id = DA830_EVM_PHY_ID; ret = davinci_cfg_reg_list(da830_cpgmac_pins); if (ret) diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index ac2297c..5e435b0 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -38,9 +38,7 @@ #include #include -#define DA850_EVM_PHY_MASK 0x1 -#define DA850_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ - +#define DA850_EVM_PHY_ID "0:00" #define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8) #define DA850_LCD_BL_PIN GPIO_TO_PIN(2, 15) @@ -678,8 +676,7 @@ static int __init da850_evm_config_emac(void) /* Enable/Disable MII MDIO clock */ gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en); - soc_info->emac_pdata->phy_mask = DA850_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DA850_EVM_MDIO_FREQUENCY; + soc_info->emac_pdata->phy_id = DA850_EVM_PHY_ID; ret = da8xx_register_emac(); if (ret) diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index bdea2da..a06b84c 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -54,9 +54,7 @@ static inline int have_tvp7002(void) return 0; } -#define DM365_EVM_PHY_MASK (0x2) -#define DM365_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - +#define DM365_EVM_PHY_ID "0:01" /* * A MAX-II CPLD is used for various board control functions. */ @@ -535,8 +533,7 @@ fail: /* ... and ENET ... */ dm365evm_emac_configure(); - soc_info->emac_pdata->phy_mask = DM365_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DM365_EVM_MDIO_FREQUENCY; + soc_info->emac_pdata->phy_id = DM365_EVM_PHY_ID; resets &= ~BIT(3); /* ... and AIC33 */ diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 65bb940..44a2f0a 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -39,9 +39,7 @@ #include #include -#define DM644X_EVM_PHY_MASK (0x2) -#define DM644X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - +#define DM644X_EVM_PHY_ID "0:01" #define LXT971_PHY_ID (0x001378e2) #define LXT971_PHY_MASK (0xfffffff0) @@ -707,9 +705,7 @@ static __init void davinci_evm_init(void) davinci_serial_init(&uart_config); dm644x_init_asp(&dm644x_evm_snd_data); - soc_info->emac_pdata->phy_mask = DM644X_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DM644X_EVM_MDIO_FREQUENCY; - + soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID; /* Register the fixup for PHY on DaVinci */ phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK, davinci_phy_fixup); diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 5a29955..67669bb 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -729,9 +729,7 @@ static struct davinci_uart_config uart_config __initdata = { .enabled_uarts = (1 << 0), }; -#define DM646X_EVM_PHY_MASK (0x2) -#define DM646X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - +#define DM646X_EVM_PHY_ID "0:01" /* * The following EDMA channels/slots are not being used by drivers (for * example: Timer, GPIO, UART events etc) on dm646x, hence they are being @@ -784,8 +782,7 @@ static __init void evm_init(void) if (HAS_ATA) davinci_init_ide(); - soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY; + soc_info->emac_pdata->phy_id = DM646X_EVM_PHY_ID; } #define DM646X_EVM_REF_FREQ 27000000 diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index 84d5aff..6f12a18 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -24,9 +24,7 @@ #include #include -#define MITYOMAPL138_PHY_MASK 0x08 /* hardcoded for now */ -#define MITYOMAPL138_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - +#define MITYOMAPL138_PHY_ID "0:03" static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = { .bus_freq = 100, /* kHz */ .bus_delay = 0, /* usec */ @@ -273,9 +271,7 @@ static void __init mityomapl138_config_emac(void) /* configure the CFGCHIP3 register for RMII or MII */ __raw_writel(val, cfg_chip3_base); - soc_info->emac_pdata->phy_mask = MITYOMAPL138_PHY_MASK; - pr_debug("setting phy_mask to %x\n", soc_info->emac_pdata->phy_mask); - soc_info->emac_pdata->mdio_max_freq = MITYOMAPL138_MDIO_FREQUENCY; + soc_info->emac_pdata->phy_id = MITYOMAPL138_PHY_ID; ret = da8xx_register_emac(); if (ret) diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index 4c30e92..04a8d16 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -39,9 +39,7 @@ #include #include -#define NEUROS_OSD2_PHY_MASK 0x2 -#define NEUROS_OSD2_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ - +#define NEUROS_OSD2_PHY_ID "0:01" #define LXT971_PHY_ID 0x001378e2 #define LXT971_PHY_MASK 0xfffffff0 @@ -252,8 +250,7 @@ static __init void davinci_ntosd2_init(void) davinci_serial_init(&uart_config); dm644x_init_asp(&dm644x_ntosd2_snd_data); - soc_info->emac_pdata->phy_mask = NEUROS_OSD2_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = NEUROS_OSD2_MDIO_FREQUENCY; + soc_info->emac_pdata->phy_id = NEUROS_OSD2_PHY_ID; davinci_setup_usb(1000, 8); /* diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 23e664a..ab4292d 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -42,9 +42,7 @@ #include #include -#define SFFSDR_PHY_MASK (0x2) -#define SFFSDR_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - +#define SFFSDR_PHY_ID "0:01" static struct mtd_partition davinci_sffsdr_nandflash_partition[] = { /* U-Boot Environment: Block 0 * UBL: Block 1 @@ -143,8 +141,7 @@ static __init void davinci_sffsdr_init(void) ARRAY_SIZE(davinci_sffsdr_devices)); sffsdr_init_i2c(); davinci_serial_init(&uart_config); - soc_info->emac_pdata->phy_mask = SFFSDR_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = SFFSDR_MDIO_FREQUENCY; + soc_info->emac_pdata->phy_id = SFFSDR_PHY_ID; davinci_setup_usb(0, 0); /* We support only peripheral mode. */ /* mux VLYNQ pins */ diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 9039221..9eec630 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -42,7 +42,6 @@ #define DA8XX_EMAC_CTRL_REG_OFFSET 0x3000 #define DA8XX_EMAC_MOD_REG_OFFSET 0x2000 #define DA8XX_EMAC_RAM_OFFSET 0x0000 -#define DA8XX_MDIO_REG_OFFSET 0x4000 #define DA8XX_EMAC_CTRL_RAM_SIZE SZ_8K void __iomem *da8xx_syscfg0_base; @@ -381,7 +380,6 @@ struct emac_platform_data da8xx_emac_pdata = { .ctrl_reg_offset = DA8XX_EMAC_CTRL_REG_OFFSET, .ctrl_mod_reg_offset = DA8XX_EMAC_MOD_REG_OFFSET, .ctrl_ram_offset = DA8XX_EMAC_RAM_OFFSET, - .mdio_reg_offset = DA8XX_MDIO_REG_OFFSET, .ctrl_ram_size = DA8XX_EMAC_CTRL_RAM_SIZE, .version = EMAC_VERSION_2, }; diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 71f0f9d..240f392 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -691,7 +691,6 @@ static struct emac_platform_data dm365_emac_pdata = { .ctrl_reg_offset = DM365_EMAC_CNTRL_OFFSET, .ctrl_mod_reg_offset = DM365_EMAC_CNTRL_MOD_OFFSET, .ctrl_ram_offset = DM365_EMAC_CNTRL_RAM_OFFSET, - .mdio_reg_offset = DM365_EMAC_MDIO_OFFSET, .ctrl_ram_size = DM365_EMAC_CNTRL_RAM_SIZE, .version = EMAC_VERSION_2, }; diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index c103b2c..41b7a95 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -322,7 +322,6 @@ static struct emac_platform_data dm644x_emac_pdata = { .ctrl_reg_offset = DM644X_EMAC_CNTRL_OFFSET, .ctrl_mod_reg_offset = DM644X_EMAC_CNTRL_MOD_OFFSET, .ctrl_ram_offset = DM644X_EMAC_CNTRL_RAM_OFFSET, - .mdio_reg_offset = DM644X_EMAC_MDIO_OFFSET, .ctrl_ram_size = DM644X_EMAC_CNTRL_RAM_SIZE, .version = EMAC_VERSION_1, }; diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 8da886b..08db90f 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -358,7 +358,6 @@ static struct emac_platform_data dm646x_emac_pdata = { .ctrl_reg_offset = DM646X_EMAC_CNTRL_OFFSET, .ctrl_mod_reg_offset = DM646X_EMAC_CNTRL_MOD_OFFSET, .ctrl_ram_offset = DM646X_EMAC_CNTRL_RAM_OFFSET, - .mdio_reg_offset = DM646X_EMAC_MDIO_OFFSET, .ctrl_ram_size = DM646X_EMAC_CNTRL_RAM_SIZE, .version = EMAC_VERSION_2, }; diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h index dbb5052..2563bf4 100644 --- a/arch/arm/mach-davinci/include/mach/dm365.h +++ b/arch/arm/mach-davinci/include/mach/dm365.h @@ -25,7 +25,6 @@ #define DM365_EMAC_CNTRL_OFFSET (0x0000) #define DM365_EMAC_CNTRL_MOD_OFFSET (0x3000) #define DM365_EMAC_CNTRL_RAM_OFFSET (0x1000) -#define DM365_EMAC_MDIO_OFFSET (0x4000) #define DM365_EMAC_CNTRL_RAM_SIZE (0x2000) /* Base of key scan register bank */ diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h index 5159117..5a1b26d 100644 --- a/arch/arm/mach-davinci/include/mach/dm644x.h +++ b/arch/arm/mach-davinci/include/mach/dm644x.h @@ -32,7 +32,6 @@ #define DM644X_EMAC_CNTRL_OFFSET (0x0000) #define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000) -#define DM644X_EMAC_MDIO_OFFSET (0x4000) #define DM644X_EMAC_CNTRL_RAM_SIZE (0x2000) #define DM644X_ASYNC_EMIF_CONTROL_BASE 0x01E00000 diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h index 1c4dca9..7a27f3f 100644 --- a/arch/arm/mach-davinci/include/mach/dm646x.h +++ b/arch/arm/mach-davinci/include/mach/dm646x.h @@ -23,7 +23,6 @@ #define DM646X_EMAC_CNTRL_OFFSET (0x0000) #define DM646X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM646X_EMAC_CNTRL_RAM_OFFSET (0x2000) -#define DM646X_EMAC_MDIO_OFFSET (0x4000) #define DM646X_EMAC_CNTRL_RAM_SIZE (0x2000) #define DM646X_ASYNC_EMIF_CONTROL_BASE 0x20008000 -- 1.7.0.4 From cyril at ti.com Tue Sep 14 16:10:11 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 14 Sep 2010 17:10:11 -0400 Subject: [PATCH v4 09/10] net: davinci_emac: switch to new cpdma layer In-Reply-To: <1284498612-25294-1-git-send-email-cyril@ti.com> References: <1284498612-25294-1-git-send-email-cyril@ti.com> Message-ID: <1284498612-25294-10-git-send-email-cyril@ti.com> This patch hooks up the emac driver with the newly separated cpdma driver. Key differences introduced here: - The old buffer list scheme is no longer required - The original code maintained mac address per rx channel, even if only one rx channel was being used. With this change, mac address is maintained device wide. If support for multiple rx channels is added in future, this will need to be reworked a bit. - The new CPDMA code handles short packets better than before. The earlier code was adjusting the length up, without ensuring that the tail end of the padding was cleared - a possible security issue. This has been fixed to use skb_padto(). Signed-off-by: Cyril Chemparathy Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- drivers/net/davinci_emac.c | 249 +++++++++++++++++++++++++++++--------------- 1 files changed, 164 insertions(+), 85 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index d4298cb..67dbcfb 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -63,6 +63,8 @@ #include #include +#include "davinci_cpdma.h" + static int debug_level; module_param(debug_level, int, 0); MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)"); @@ -113,6 +115,7 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_FRAME_SIZE (1500 + 14 + 4 + 4) #define EMAC_DEF_TX_CH (0) /* Default 0th channel */ #define EMAC_DEF_RX_CH (0) /* Default 0th channel */ +#define EMAC_DEF_RX_NUM_DESC (128) #define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */ #define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */ #define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */ @@ -460,6 +463,9 @@ struct emac_priv { u32 hw_ram_addr; struct emac_txch *txch[EMAC_DEF_MAX_TX_CH]; struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH]; + struct cpdma_ctlr *dma; + struct cpdma_chan *txchan; + struct cpdma_chan *rxchan; u32 link; /* 1=link on, 0=link off */ u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */ u32 duplex; /* Link duplex: 0=Half, 1=Full */ @@ -624,6 +630,8 @@ static void emac_dump_regs(struct emac_priv *priv) emac_read(EMAC_RXMOFOVERRUNS)); dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n", emac_read(EMAC_RXDMAOVERRUNS)); + + cpdma_ctlr_dump(priv->dma); } /** @@ -1151,6 +1159,70 @@ static irqreturn_t emac_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static struct sk_buff *emac_rx_alloc(struct emac_priv *priv) +{ + struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size); + if (WARN_ON(!skb)) + return NULL; + skb->dev = priv->ndev; + skb_reserve(skb, NET_IP_ALIGN); + return skb; +} + +static void emac_rx_handler(void *token, int len, int status) +{ + struct sk_buff *skb = token; + struct net_device *ndev = skb->dev; + struct emac_priv *priv = netdev_priv(ndev); + struct device *emac_dev = &ndev->dev; + int ret; + + /* free and bail if we are shutting down */ + if (unlikely(!netif_running(ndev))) { + dev_kfree_skb_any(skb); + return; + } + + /* recycle on recieve error */ + if (status < 0) { + ndev->stats.rx_errors++; + goto recycle; + } + + /* feed received packet up the stack */ + skb_put(skb, len); + skb->protocol = eth_type_trans(skb, ndev); + netif_receive_skb(skb); + ndev->stats.rx_bytes += len; + ndev->stats.rx_packets++; + + /* alloc a new packet for receive */ + skb = emac_rx_alloc(priv); + if (!skb) { + if (netif_msg_rx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "failed rx buffer alloc\n"); + return; + } + +recycle: + ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, + skb_tailroom(skb), GFP_KERNEL); + if (WARN_ON(ret < 0)) + dev_kfree_skb_any(skb); +} + +static void emac_tx_handler(void *token, int len, int status) +{ + struct sk_buff *skb = token; + struct net_device *ndev = skb->dev; + + if (unlikely(netif_queue_stopped(ndev))) + netif_start_queue(ndev); + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += len; + dev_kfree_skb_any(skb); +} + /** EMAC on-chip buffer descriptor memory * * WARNING: Please note that the on chip memory is used for both TX and RX @@ -1532,42 +1604,36 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) { struct device *emac_dev = &ndev->dev; int ret_code; - struct emac_netbufobj tx_buf; /* buffer obj-only single frame support */ - struct emac_netpktobj tx_packet; /* packet object */ struct emac_priv *priv = netdev_priv(ndev); /* If no link, return */ if (unlikely(!priv->link)) { if (netif_msg_tx_err(priv) && net_ratelimit()) dev_err(emac_dev, "DaVinci EMAC: No link to transmit"); - return NETDEV_TX_BUSY; + goto fail_tx; } - /* Build the buffer and packet objects - Since only single fragment is - * supported, need not set length and token in both packet & object. - * Doing so for completeness sake & to show that this needs to be done - * in multifragment case - */ - tx_packet.buf_list = &tx_buf; - tx_packet.num_bufs = 1; /* only single fragment supported */ - tx_packet.pkt_length = skb->len; - tx_packet.pkt_token = (void *)skb; - tx_buf.length = skb->len; - tx_buf.buf_token = (void *)skb; - tx_buf.data_ptr = skb->data; - ret_code = emac_send(priv, &tx_packet, EMAC_DEF_TX_CH); + ret_code = skb_padto(skb, EMAC_DEF_MIN_ETHPKTSIZE); + if (unlikely(ret_code < 0)) { + if (netif_msg_tx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "DaVinci EMAC: packet pad failed"); + goto fail_tx; + } + + ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len, + GFP_KERNEL); if (unlikely(ret_code != 0)) { - if (ret_code == EMAC_ERR_TX_OUT_OF_BD) { - if (netif_msg_tx_err(priv) && net_ratelimit()) - dev_err(emac_dev, "DaVinci EMAC: xmit() fatal"\ - " err. Out of TX BD's"); - netif_stop_queue(priv->ndev); - } - ndev->stats.tx_dropped++; - return NETDEV_TX_BUSY; + if (netif_msg_tx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "DaVinci EMAC: desc submit failed"); + goto fail_tx; } return NETDEV_TX_OK; + +fail_tx: + ndev->stats.tx_dropped++; + netif_stop_queue(ndev); + return NETDEV_TX_BUSY; } /** @@ -1588,13 +1654,12 @@ static void emac_dev_tx_timeout(struct net_device *ndev) if (netif_msg_tx_err(priv)) dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX"); + emac_dump_regs(priv); + ndev->stats.tx_errors++; emac_int_disable(priv); - emac_stop_txch(priv, EMAC_DEF_TX_CH); - emac_cleanup_txch(priv, EMAC_DEF_TX_CH); - emac_init_txch(priv, EMAC_DEF_TX_CH); - emac_write(EMAC_TXHDP(0), 0); - emac_write(EMAC_TXINTMASKSET, BIT(EMAC_DEF_TX_CH)); + cpdma_chan_stop(priv->txchan); + cpdma_chan_start(priv->txchan); emac_int_enable(priv); } @@ -1915,7 +1980,6 @@ static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr) static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) { struct emac_priv *priv = netdev_priv(ndev); - struct emac_rxch *rxch = priv->rxch[EMAC_DEF_RX_CH]; struct device *emac_dev = &priv->ndev->dev; struct sockaddr *sa = addr; @@ -1926,11 +1990,10 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); - /* If the interface is down - rxch is NULL. */ /* MAC address is configured only after the interface is enabled. */ if (netif_running(ndev)) { - memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); - emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); + memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); + emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); } if (netif_msg_drv(priv)) @@ -2139,7 +2202,7 @@ end_emac_rx_bdproc: */ static int emac_hw_enable(struct emac_priv *priv) { - u32 ch, val, mbp_enable, mac_control; + u32 val, mbp_enable, mac_control; /* Soft reset */ emac_write(EMAC_SOFTRESET, 1); @@ -2182,26 +2245,9 @@ static int emac_hw_enable(struct emac_priv *priv) emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL); priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF; - val = emac_read(EMAC_TXCONTROL); - val |= EMAC_TX_CONTROL_TX_ENABLE_VAL; - emac_write(EMAC_TXCONTROL, val); - val = emac_read(EMAC_RXCONTROL); - val |= EMAC_RX_CONTROL_RX_ENABLE_VAL; - emac_write(EMAC_RXCONTROL, val); emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL); - for (ch = 0; ch < EMAC_DEF_MAX_TX_CH; ch++) { - emac_write(EMAC_TXHDP(ch), 0); - emac_write(EMAC_TXINTMASKSET, BIT(ch)); - } - for (ch = 0; ch < EMAC_DEF_MAX_RX_CH; ch++) { - struct emac_rxch *rxch = priv->rxch[ch]; - emac_setmac(priv, ch, rxch->mac_addr); - emac_write(EMAC_RXINTMASKSET, BIT(ch)); - rxch->queue_active = 1; - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(rxch->active_queue_head, priv)); - } + emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); /* Enable MII */ val = emac_read(EMAC_MACCONTROL); @@ -2246,8 +2292,8 @@ static int emac_poll(struct napi_struct *napi, int budget) mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC; if (status & mask) { - num_tx_pkts = emac_tx_bdproc(priv, EMAC_DEF_TX_CH, - EMAC_DEF_TX_MAX_SERVICE); + num_tx_pkts = cpdma_chan_process(priv->txchan, + EMAC_DEF_TX_MAX_SERVICE); } /* TX processing */ mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC; @@ -2256,7 +2302,7 @@ static int emac_poll(struct napi_struct *napi, int budget) mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC; if (status & mask) { - num_rx_pkts = emac_rx_bdproc(priv, EMAC_DEF_RX_CH, budget); + num_rx_pkts = cpdma_chan_process(priv->rxchan, budget); } /* RX processing */ mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT; @@ -2397,9 +2443,9 @@ static int match_first_device(struct device *dev, void *data) static int emac_dev_open(struct net_device *ndev) { struct device *emac_dev = &ndev->dev; - u32 rc, cnt, ch; + u32 cnt; struct resource *res; - int q, m; + int q, m, ret; int i = 0; int k = 0; struct emac_priv *priv = netdev_priv(ndev); @@ -2411,29 +2457,21 @@ static int emac_dev_open(struct net_device *ndev) /* Configuration items */ priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN; - /* Clear basic hardware */ - for (ch = 0; ch < EMAC_MAX_TXRX_CHANNELS; ch++) { - emac_write(EMAC_TXHDP(ch), 0); - emac_write(EMAC_RXHDP(ch), 0); - emac_write(EMAC_RXHDP(ch), 0); - emac_write(EMAC_RXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); - emac_write(EMAC_TXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); - } priv->mac_hash1 = 0; priv->mac_hash2 = 0; emac_write(EMAC_MACHASH1, 0); emac_write(EMAC_MACHASH2, 0); - /* multi ch not supported - open 1 TX, 1RX ch by default */ - rc = emac_init_txch(priv, EMAC_DEF_TX_CH); - if (0 != rc) { - dev_err(emac_dev, "DaVinci EMAC: emac_init_txch() failed"); - return rc; - } - rc = emac_init_rxch(priv, EMAC_DEF_RX_CH, priv->mac_addr); - if (0 != rc) { - dev_err(emac_dev, "DaVinci EMAC: emac_init_rxch() failed"); - return rc; + for (i = 0; i < EMAC_DEF_RX_NUM_DESC; i++) { + struct sk_buff *skb = emac_rx_alloc(priv); + + if (!skb) + break; + + ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, + skb_tailroom(skb), GFP_KERNEL); + if (WARN_ON(ret < 0)) + break; } /* Request IRQ */ @@ -2458,6 +2496,8 @@ static int emac_dev_open(struct net_device *ndev) emac_set_coalesce(ndev, &coal); } + cpdma_ctlr_start(priv->dma); + priv->phydev = NULL; /* use the first phy on the bus if pdata did not give us a phy id */ if (!priv->phy_id) { @@ -2545,10 +2585,7 @@ static int emac_dev_stop(struct net_device *ndev) netif_carrier_off(ndev); emac_int_disable(priv); - emac_stop_txch(priv, EMAC_DEF_TX_CH); - emac_stop_rxch(priv, EMAC_DEF_RX_CH); - emac_cleanup_txch(priv, EMAC_DEF_TX_CH); - emac_cleanup_rxch(priv, EMAC_DEF_RX_CH); + cpdma_ctlr_stop(priv->dma); emac_write(EMAC_SOFTRESET, 1); if (priv->phydev) @@ -2653,9 +2690,10 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) struct resource *res; struct net_device *ndev; struct emac_priv *priv; - unsigned long size; + unsigned long size, hw_ram_addr; struct emac_platform_data *pdata; struct device *emac_dev; + struct cpdma_params dma_params; /* obtain emac clock from kernel */ emac_clk = clk_get(&pdev->dev, NULL); @@ -2731,11 +2769,40 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->ctrl_ram_size = pdata->ctrl_ram_size; priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset; - if (pdata->hw_ram_addr) - priv->hw_ram_addr = pdata->hw_ram_addr; - else - priv->hw_ram_addr = (u32 __force)res->start + - pdata->ctrl_ram_offset; + hw_ram_addr = pdata->hw_ram_addr; + if (!hw_ram_addr) + hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset; + + memset(&dma_params, 0, sizeof(dma_params)); + dma_params.dev = emac_dev; + dma_params.dmaregs = priv->emac_base; + dma_params.rxthresh = priv->emac_base + 0x120; + dma_params.rxfree = priv->emac_base + 0x140; + dma_params.txhdp = priv->emac_base + 0x600; + dma_params.rxhdp = priv->emac_base + 0x620; + dma_params.txcp = priv->emac_base + 0x640; + dma_params.rxcp = priv->emac_base + 0x660; + dma_params.num_chan = EMAC_MAX_TXRX_CHANNELS; + dma_params.min_packet_size = EMAC_DEF_MIN_ETHPKTSIZE; + dma_params.desc_mem_phys = hw_ram_addr; + dma_params.desc_mem_size = pdata->ctrl_ram_size; + dma_params.desc_align = 16; + + priv->dma = cpdma_ctlr_create(&dma_params); + if (!priv->dma) { + dev_err(emac_dev, "DaVinci EMAC: Error initializing DMA\n"); + rc = -ENOMEM; + goto no_dma; + } + + priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH), + emac_tx_handler); + priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH), + emac_rx_handler); + if (WARN_ON(!priv->txchan || !priv->rxchan)) { + rc = -ENOMEM; + goto no_irq_res; + } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { @@ -2778,6 +2845,12 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) netdev_reg_err: clk_disable(emac_clk); no_irq_res: + if (priv->txchan) + cpdma_chan_destroy(priv->txchan); + if (priv->rxchan) + cpdma_chan_destroy(priv->rxchan); + cpdma_ctlr_destroy(priv->dma); +no_dma: res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, res->end - res->start + 1); iounmap(priv->remap_addr); @@ -2806,6 +2879,12 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (priv->txchan) + cpdma_chan_destroy(priv->txchan); + if (priv->rxchan) + cpdma_chan_destroy(priv->rxchan); + cpdma_ctlr_destroy(priv->dma); + release_mem_region(res->start, res->end - res->start + 1); unregister_netdev(ndev); -- 1.7.0.4 From cyril at ti.com Tue Sep 14 16:10:12 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 14 Sep 2010 17:10:12 -0400 Subject: [PATCH v4 10/10] net: davinci_emac: cleanup unused cpdma code In-Reply-To: <1284498612-25294-1-git-send-email-cyril@ti.com> References: <1284498612-25294-1-git-send-email-cyril@ti.com> Message-ID: <1284498612-25294-11-git-send-email-cyril@ti.com> Having switched over to the newly introduced cpdma layer, this patch now removes a whole bunch of code that is now unused. This patch has been maintained separate strictly for reasons of readability. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- drivers/net/davinci_emac.c | 930 -------------------------------------------- 1 files changed, 0 insertions(+), 930 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 67dbcfb..2a628d1 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -127,7 +127,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; /* EMAC register related defines */ #define EMAC_ALL_MULTI_REG_VALUE (0xFFFFFFFF) #define EMAC_NUM_MULTICAST_BITS (64) -#define EMAC_TEARDOWN_VALUE (0xFFFFFFFC) #define EMAC_TX_CONTROL_TX_ENABLE_VAL (0x1) #define EMAC_RX_CONTROL_RX_ENABLE_VAL (0x1) #define EMAC_MAC_HOST_ERR_INTMASK_VAL (0x2) @@ -214,24 +213,10 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */ /* EMAC Peripheral Device Register Memory Layout structure */ -#define EMAC_TXIDVER 0x0 -#define EMAC_TXCONTROL 0x4 -#define EMAC_TXTEARDOWN 0x8 -#define EMAC_RXIDVER 0x10 -#define EMAC_RXCONTROL 0x14 -#define EMAC_RXTEARDOWN 0x18 -#define EMAC_TXINTSTATRAW 0x80 -#define EMAC_TXINTSTATMASKED 0x84 -#define EMAC_TXINTMASKSET 0x88 -#define EMAC_TXINTMASKCLEAR 0x8C #define EMAC_MACINVECTOR 0x90 #define EMAC_DM646X_MACEOIVECTOR 0x94 -#define EMAC_RXINTSTATRAW 0xA0 -#define EMAC_RXINTSTATMASKED 0xA4 -#define EMAC_RXINTMASKSET 0xA8 -#define EMAC_RXINTMASKCLEAR 0xAC #define EMAC_MACINTSTATRAW 0xB0 #define EMAC_MACINTSTATMASKED 0xB4 #define EMAC_MACINTMASKSET 0xB8 @@ -258,12 +243,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_MACADDRHI 0x504 #define EMAC_MACINDEX 0x508 -/* EMAC HDP and Completion registors */ -#define EMAC_TXHDP(ch) (0x600 + (ch * 4)) -#define EMAC_RXHDP(ch) (0x620 + (ch * 4)) -#define EMAC_TXCP(ch) (0x640 + (ch * 4)) -#define EMAC_RXCP(ch) (0x660 + (ch * 4)) - /* EMAC statistics registers */ #define EMAC_RXGOODFRAMES 0x200 #define EMAC_RXBCASTFRAMES 0x204 @@ -328,120 +307,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; /* EMAC Stats Clear Mask */ #define EMAC_STATS_CLR_MASK (0xFFFFFFFF) -/** net_buf_obj: EMAC network bufferdata structure - * - * EMAC network buffer data structure - */ -struct emac_netbufobj { - void *buf_token; - char *data_ptr; - int length; -}; - -/** net_pkt_obj: EMAC network packet data structure - * - * EMAC network packet data structure - supports buffer list (for future) - */ -struct emac_netpktobj { - void *pkt_token; /* data token may hold tx/rx chan id */ - struct emac_netbufobj *buf_list; /* array of network buffer objects */ - int num_bufs; - int pkt_length; -}; - -/** emac_tx_bd: EMAC TX Buffer descriptor data structure - * - * EMAC TX Buffer descriptor data structure - */ -struct emac_tx_bd { - int h_next; - int buff_ptr; - int off_b_len; - int mode; /* SOP, EOP, ownership, EOQ, teardown,Qstarv, length */ - struct emac_tx_bd __iomem *next; - void *buf_token; -}; - -/** emac_txch: EMAC TX Channel data structure - * - * EMAC TX Channel data structure - */ -struct emac_txch { - /* Config related */ - u32 num_bd; - u32 service_max; - - /* CPPI specific */ - u32 alloc_size; - void __iomem *bd_mem; - struct emac_tx_bd __iomem *bd_pool_head; - struct emac_tx_bd __iomem *active_queue_head; - struct emac_tx_bd __iomem *active_queue_tail; - struct emac_tx_bd __iomem *last_hw_bdprocessed; - u32 queue_active; - u32 teardown_pending; - u32 *tx_complete; - - /** statistics */ - u32 proc_count; /* TX: # of times emac_tx_bdproc is called */ - u32 mis_queued_packets; - u32 queue_reinit; - u32 end_of_queue_add; - u32 out_of_tx_bd; - u32 no_active_pkts; /* IRQ when there were no packets to process */ - u32 active_queue_count; -}; - -/** emac_rx_bd: EMAC RX Buffer descriptor data structure - * - * EMAC RX Buffer descriptor data structure - */ -struct emac_rx_bd { - int h_next; - int buff_ptr; - int off_b_len; - int mode; - struct emac_rx_bd __iomem *next; - void *data_ptr; - void *buf_token; -}; - -/** emac_rxch: EMAC RX Channel data structure - * - * EMAC RX Channel data structure - */ -struct emac_rxch { - /* configuration info */ - u32 num_bd; - u32 service_max; - u32 buf_size; - char mac_addr[6]; - - /** CPPI specific */ - u32 alloc_size; - void __iomem *bd_mem; - struct emac_rx_bd __iomem *bd_pool_head; - struct emac_rx_bd __iomem *active_queue_head; - struct emac_rx_bd __iomem *active_queue_tail; - u32 queue_active; - u32 teardown_pending; - - /* packet and buffer objects */ - struct emac_netpktobj pkt_queue; - struct emac_netbufobj buf_queue; - - /** statistics */ - u32 proc_count; /* number of times emac_rx_bdproc is called */ - u32 processed_bd; - u32 recycled_bd; - u32 out_of_rx_bd; - u32 out_of_rx_buffers; - u32 queue_reinit; - u32 end_of_queue_add; - u32 end_of_queue; - u32 mis_queued_packets; -}; - /* emac_priv: EMAC private data structure * * EMAC adapter private data structure @@ -452,17 +317,10 @@ struct emac_priv { struct platform_device *pdev; struct napi_struct napi; char mac_addr[6]; - spinlock_t tx_lock; - spinlock_t rx_lock; void __iomem *remap_addr; u32 emac_base_phys; void __iomem *emac_base; void __iomem *ctrl_base; - void __iomem *emac_ctrl_ram; - u32 ctrl_ram_size; - u32 hw_ram_addr; - struct emac_txch *txch[EMAC_DEF_MAX_TX_CH]; - struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH]; struct cpdma_ctlr *dma; struct cpdma_chan *txchan; struct cpdma_chan *rxchan; @@ -491,18 +349,6 @@ struct emac_priv { static struct clk *emac_clk; static unsigned long emac_bus_frequency; -#define emac_virt_to_phys(addr, priv) \ - (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \ - + priv->hw_ram_addr) - -/* Cache macros - Packet buffers would be from skb pool which is cached */ -#define EMAC_VIRT_NOCACHE(addr) (addr) - -/* DM644x does not have BD's in cached memory - so no cache functions */ -#define BD_CACHE_INVALIDATE(addr, size) -#define BD_CACHE_WRITEBACK(addr, size) -#define BD_CACHE_WRITEBACK_INVALIDATE(addr, size) - /* EMAC TX Host Error description strings */ static char *emac_txhost_errcodes[16] = { "No error", "SOP error", "Ownership bit not set in SOP buffer", @@ -545,20 +391,6 @@ static void emac_dump_regs(struct emac_priv *priv) emac_ctrl_read(EMAC_CTRL_EWCTL), emac_ctrl_read(EMAC_CTRL_EWINTTCNT)); } - dev_info(emac_dev, "EMAC: TXID: %08X %s, RXID: %08X %s\n", - emac_read(EMAC_TXIDVER), - ((emac_read(EMAC_TXCONTROL)) ? "enabled" : "disabled"), - emac_read(EMAC_RXIDVER), - ((emac_read(EMAC_RXCONTROL)) ? "enabled" : "disabled")); - dev_info(emac_dev, "EMAC: TXIntRaw:%08X, TxIntMasked: %08X, "\ - "TxIntMasSet: %08X\n", emac_read(EMAC_TXINTSTATRAW), - emac_read(EMAC_TXINTSTATMASKED), emac_read(EMAC_TXINTMASKSET)); - dev_info(emac_dev, "EMAC: RXIntRaw:%08X, RxIntMasked: %08X, "\ - "RxIntMasSet: %08X\n", emac_read(EMAC_RXINTSTATRAW), - emac_read(EMAC_RXINTSTATMASKED), emac_read(EMAC_RXINTMASKSET)); - dev_info(emac_dev, "EMAC: MacIntRaw:%08X, MacIntMasked: %08X, "\ - "MacInVector=%08X\n", emac_read(EMAC_MACINTSTATRAW), - emac_read(EMAC_MACINTSTATMASKED), emac_read(EMAC_MACINVECTOR)); dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n", emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL)); dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\ @@ -567,8 +399,6 @@ static void emac_dump_regs(struct emac_priv *priv) dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\ "MacConfig=%08X\n", emac_read(EMAC_MACCONTROL), emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG)); - dev_info(emac_dev, "EMAC: TXHDP[0]:%08X, RXHDP[0]: %08X\n", - emac_read(EMAC_TXHDP(0)), emac_read(EMAC_RXHDP(0))); dev_info(emac_dev, "EMAC Statistics\n"); dev_info(emac_dev, "EMAC: rx_good_frames:%d\n", emac_read(EMAC_RXGOODFRAMES)); @@ -1223,373 +1053,6 @@ static void emac_tx_handler(void *token, int len, int status) dev_kfree_skb_any(skb); } -/** EMAC on-chip buffer descriptor memory - * - * WARNING: Please note that the on chip memory is used for both TX and RX - * buffer descriptor queues and is equally divided between TX and RX desc's - * If the number of TX or RX descriptors change this memory pointers need - * to be adjusted. If external memory is allocated then these pointers can - * pointer to the memory - * - */ -#define EMAC_TX_BD_MEM(priv) ((priv)->emac_ctrl_ram) -#define EMAC_RX_BD_MEM(priv) ((priv)->emac_ctrl_ram + \ - (((priv)->ctrl_ram_size) >> 1)) - -/** - * emac_init_txch: TX channel initialization - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device init to setup a TX channel (allocate buffer desc - * create free pool and keep ready for transmission - * - * Returns success(0) or mem alloc failures error code - */ -static int emac_init_txch(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 cnt, bd_size; - void __iomem *mem; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch = NULL; - - txch = kzalloc(sizeof(struct emac_txch), GFP_KERNEL); - if (NULL == txch) { - dev_err(emac_dev, "DaVinci EMAC: TX Ch mem alloc failed"); - return -ENOMEM; - } - priv->txch[ch] = txch; - txch->service_max = EMAC_DEF_TX_MAX_SERVICE; - txch->active_queue_head = NULL; - txch->active_queue_tail = NULL; - txch->queue_active = 0; - txch->teardown_pending = 0; - - /* allocate memory for TX CPPI channel on a 4 byte boundry */ - txch->tx_complete = kzalloc(txch->service_max * sizeof(u32), - GFP_KERNEL); - if (NULL == txch->tx_complete) { - dev_err(emac_dev, "DaVinci EMAC: Tx service mem alloc failed"); - kfree(txch); - return -ENOMEM; - } - - /* allocate buffer descriptor pool align every BD on four word - * boundry for future requirements */ - bd_size = (sizeof(struct emac_tx_bd) + 0xF) & ~0xF; - txch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; - txch->alloc_size = (((bd_size * txch->num_bd) + 0xF) & ~0xF); - - /* alloc TX BD memory */ - txch->bd_mem = EMAC_TX_BD_MEM(priv); - __memzero((void __force *)txch->bd_mem, txch->alloc_size); - - /* initialize the BD linked list */ - mem = (void __force __iomem *) - (((u32 __force) txch->bd_mem + 0xF) & ~0xF); - txch->bd_pool_head = NULL; - for (cnt = 0; cnt < txch->num_bd; cnt++) { - curr_bd = mem + (cnt * bd_size); - curr_bd->next = txch->bd_pool_head; - txch->bd_pool_head = curr_bd; - } - - /* reset statistics counters */ - txch->out_of_tx_bd = 0; - txch->no_active_pkts = 0; - txch->active_queue_count = 0; - - return 0; -} - -/** - * emac_cleanup_txch: Book-keep function to clean TX channel resources - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to clean up TX channel resources - * - */ -static void emac_cleanup_txch(struct emac_priv *priv, u32 ch) -{ - struct emac_txch *txch = priv->txch[ch]; - - if (txch) { - if (txch->bd_mem) - txch->bd_mem = NULL; - kfree(txch->tx_complete); - kfree(txch); - priv->txch[ch] = NULL; - } -} - -/** - * emac_net_tx_complete: TX packet completion function - * @priv: The DaVinci EMAC private adapter structure - * @net_data_tokens: packet token - skb pointer - * @num_tokens: number of skb's to free - * @ch: TX channel number - * - * Frees the skb once packet is transmitted - * - */ -static int emac_net_tx_complete(struct emac_priv *priv, - void **net_data_tokens, - int num_tokens, u32 ch) -{ - struct net_device *ndev = priv->ndev; - u32 cnt; - - if (unlikely(num_tokens && netif_queue_stopped(ndev))) - netif_start_queue(ndev); - for (cnt = 0; cnt < num_tokens; cnt++) { - struct sk_buff *skb = (struct sk_buff *)net_data_tokens[cnt]; - if (skb == NULL) - continue; - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += skb->len; - dev_kfree_skb_any(skb); - } - return 0; -} - -/** - * emac_txch_teardown: TX channel teardown - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to teardown TX channel - * - */ -static void emac_txch_teardown(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ - struct emac_txch *txch = priv->txch[ch]; - struct emac_tx_bd __iomem *curr_bd; - - while ((emac_read(EMAC_TXCP(ch)) & EMAC_TEARDOWN_VALUE) != - EMAC_TEARDOWN_VALUE) { - /* wait till tx teardown complete */ - cpu_relax(); /* TODO: check if this helps ... */ - --teardown_cnt; - if (0 == teardown_cnt) { - dev_err(emac_dev, "EMAC: TX teardown aborted\n"); - break; - } - } - emac_write(EMAC_TXCP(ch), EMAC_TEARDOWN_VALUE); - - /* process sent packets and return skb's to upper layer */ - if (1 == txch->queue_active) { - curr_bd = txch->active_queue_head; - while (curr_bd != NULL) { - dma_unmap_single(emac_dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_TO_DEVICE); - - emac_net_tx_complete(priv, (void __force *) - &curr_bd->buf_token, 1, ch); - if (curr_bd != txch->active_queue_tail) - curr_bd = curr_bd->next; - else - break; - } - txch->bd_pool_head = txch->active_queue_head; - txch->active_queue_head = - txch->active_queue_tail = NULL; - } -} - -/** - * emac_stop_txch: Stop TX channel operation - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to stop TX channel operation - * - */ -static void emac_stop_txch(struct emac_priv *priv, u32 ch) -{ - struct emac_txch *txch = priv->txch[ch]; - - if (txch) { - txch->teardown_pending = 1; - emac_write(EMAC_TXTEARDOWN, 0); - emac_txch_teardown(priv, ch); - txch->teardown_pending = 0; - emac_write(EMAC_TXINTMASKCLEAR, BIT(ch)); - } -} - -/** - * emac_tx_bdproc: TX buffer descriptor (packet) processing - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number to process buffer descriptors for - * @budget: number of packets allowed to process - * @pending: indication to caller that packets are pending to process - * - * Processes TX buffer descriptors after packets are transmitted - checks - * ownership bit on the TX * descriptor and requeues it to free pool & frees - * the SKB buffer. Only "budget" number of packets are processed and - * indication of pending packets provided to the caller - * - * Returns number of packets processed - */ -static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) -{ - struct device *emac_dev = &priv->ndev->dev; - unsigned long flags; - u32 frame_status; - u32 pkts_processed = 0; - u32 tx_complete_cnt = 0; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch = priv->txch[ch]; - u32 *tx_complete_ptr = txch->tx_complete; - - if (unlikely(1 == txch->teardown_pending)) { - if (netif_msg_tx_err(priv) && net_ratelimit()) { - dev_err(emac_dev, "DaVinci EMAC:emac_tx_bdproc: "\ - "teardown pending\n"); - } - return 0; /* dont handle any pkt completions */ - } - - ++txch->proc_count; - spin_lock_irqsave(&priv->tx_lock, flags); - curr_bd = txch->active_queue_head; - if (NULL == curr_bd) { - emac_write(EMAC_TXCP(ch), - emac_virt_to_phys(txch->last_hw_bdprocessed, priv)); - txch->no_active_pkts++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return 0; - } - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - while ((curr_bd) && - ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && - (pkts_processed < budget)) { - emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd, priv)); - txch->active_queue_head = curr_bd->next; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - if (curr_bd->next) { /* misqueued packet */ - emac_write(EMAC_TXHDP(ch), curr_bd->h_next); - ++txch->mis_queued_packets; - } else { - txch->queue_active = 0; /* end of queue */ - } - } - - dma_unmap_single(emac_dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_TO_DEVICE); - - *tx_complete_ptr = (u32) curr_bd->buf_token; - ++tx_complete_ptr; - ++tx_complete_cnt; - curr_bd->next = txch->bd_pool_head; - txch->bd_pool_head = curr_bd; - --txch->active_queue_count; - pkts_processed++; - txch->last_hw_bdprocessed = curr_bd; - curr_bd = txch->active_queue_head; - if (curr_bd) { - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - } - } /* end of pkt processing loop */ - - emac_net_tx_complete(priv, - (void *)&txch->tx_complete[0], - tx_complete_cnt, ch); - spin_unlock_irqrestore(&priv->tx_lock, flags); - return pkts_processed; -} - -#define EMAC_ERR_TX_OUT_OF_BD -1 - -/** - * emac_send: EMAC Transmit function (internal) - * @priv: The DaVinci EMAC private adapter structure - * @pkt: packet pointer (contains skb ptr) - * @ch: TX channel number - * - * Called by the transmit function to queue the packet in EMAC hardware queue - * - * Returns success(0) or error code (typically out of desc's) - */ -static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch) -{ - unsigned long flags; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch; - struct emac_netbufobj *buf_list; - - txch = priv->txch[ch]; - buf_list = pkt->buf_list; /* get handle to the buffer array */ - - /* check packet size and pad if short */ - if (pkt->pkt_length < EMAC_DEF_MIN_ETHPKTSIZE) { - buf_list->length += (EMAC_DEF_MIN_ETHPKTSIZE - pkt->pkt_length); - pkt->pkt_length = EMAC_DEF_MIN_ETHPKTSIZE; - } - - spin_lock_irqsave(&priv->tx_lock, flags); - curr_bd = txch->bd_pool_head; - if (curr_bd == NULL) { - txch->out_of_tx_bd++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return EMAC_ERR_TX_OUT_OF_BD; - } - - txch->bd_pool_head = curr_bd->next; - curr_bd->buf_token = buf_list->buf_token; - curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buf_list->data_ptr, - buf_list->length, DMA_TO_DEVICE); - curr_bd->off_b_len = buf_list->length; - curr_bd->h_next = 0; - curr_bd->next = NULL; - curr_bd->mode = (EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT | - EMAC_CPPI_EOP_BIT | pkt->pkt_length); - - /* flush the packet from cache if write back cache is present */ - BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - - /* send the packet */ - if (txch->active_queue_head == NULL) { - txch->active_queue_head = curr_bd; - txch->active_queue_tail = curr_bd; - if (1 != txch->queue_active) { - emac_write(EMAC_TXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - txch->queue_active = 1; - } - ++txch->queue_reinit; - } else { - register struct emac_tx_bd __iomem *tail_bd; - register u32 frame_status; - - tail_bd = txch->active_queue_tail; - tail_bd->next = curr_bd; - txch->active_queue_tail = curr_bd; - tail_bd = EMAC_VIRT_NOCACHE(tail_bd); - tail_bd->h_next = (int)emac_virt_to_phys(curr_bd, priv); - frame_status = tail_bd->mode; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - emac_write(EMAC_TXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - frame_status &= ~(EMAC_CPPI_EOQ_BIT); - tail_bd->mode = frame_status; - ++txch->end_of_queue_add; - } - } - txch->active_queue_count++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return 0; -} - /** * emac_dev_xmit: EMAC Transmit function * @skb: SKB pointer @@ -1664,207 +1127,6 @@ static void emac_dev_tx_timeout(struct net_device *ndev) } /** - * emac_net_alloc_rx_buf: Allocate a skb for RX - * @priv: The DaVinci EMAC private adapter structure - * @buf_size: size of SKB data buffer to allocate - * @data_token: data token returned (skb handle for storing in buffer desc) - * @ch: RX channel number - * - * Called during RX channel setup - allocates skb buffer of required size - * and provides the skb handle and allocated buffer data pointer to caller - * - * Returns skb data pointer or 0 on failure to alloc skb - */ -static void *emac_net_alloc_rx_buf(struct emac_priv *priv, int buf_size, - void **data_token, u32 ch) -{ - struct net_device *ndev = priv->ndev; - struct device *emac_dev = &ndev->dev; - struct sk_buff *p_skb; - - p_skb = dev_alloc_skb(buf_size); - if (unlikely(NULL == p_skb)) { - if (netif_msg_rx_err(priv) && net_ratelimit()) - dev_err(emac_dev, "DaVinci EMAC: failed to alloc skb"); - return NULL; - } - - /* set device pointer in skb and reserve space for extra bytes */ - p_skb->dev = ndev; - skb_reserve(p_skb, NET_IP_ALIGN); - *data_token = (void *) p_skb; - return p_skb->data; -} - -/** - * emac_init_rxch: RX channel initialization - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * @param: mac address for RX channel - * - * Called during device init to setup a RX channel (allocate buffers and - * buffer descriptors, create queue and keep ready for reception - * - * Returns success(0) or mem alloc failures error code - */ -static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 cnt, bd_size; - void __iomem *mem; - struct emac_rx_bd __iomem *curr_bd; - struct emac_rxch *rxch = NULL; - - rxch = kzalloc(sizeof(struct emac_rxch), GFP_KERNEL); - if (NULL == rxch) { - dev_err(emac_dev, "DaVinci EMAC: RX Ch mem alloc failed"); - return -ENOMEM; - } - priv->rxch[ch] = rxch; - rxch->buf_size = priv->rx_buf_size; - rxch->service_max = EMAC_DEF_RX_MAX_SERVICE; - rxch->queue_active = 0; - rxch->teardown_pending = 0; - - /* save mac address */ - for (cnt = 0; cnt < 6; cnt++) - rxch->mac_addr[cnt] = param[cnt]; - - /* allocate buffer descriptor pool align every BD on four word - * boundry for future requirements */ - bd_size = (sizeof(struct emac_rx_bd) + 0xF) & ~0xF; - rxch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; - rxch->alloc_size = (((bd_size * rxch->num_bd) + 0xF) & ~0xF); - rxch->bd_mem = EMAC_RX_BD_MEM(priv); - __memzero((void __force *)rxch->bd_mem, rxch->alloc_size); - rxch->pkt_queue.buf_list = &rxch->buf_queue; - - /* allocate RX buffer and initialize the BD linked list */ - mem = (void __force __iomem *) - (((u32 __force) rxch->bd_mem + 0xF) & ~0xF); - rxch->active_queue_head = NULL; - rxch->active_queue_tail = mem; - for (cnt = 0; cnt < rxch->num_bd; cnt++) { - curr_bd = mem + (cnt * bd_size); - /* for future use the last parameter contains the BD ptr */ - curr_bd->data_ptr = emac_net_alloc_rx_buf(priv, - rxch->buf_size, - (void __force **)&curr_bd->buf_token, - EMAC_DEF_RX_CH); - if (curr_bd->data_ptr == NULL) { - dev_err(emac_dev, "DaVinci EMAC: RX buf mem alloc " \ - "failed for ch %d\n", ch); - kfree(rxch); - return -ENOMEM; - } - - /* populate the hardware descriptor */ - curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head, - priv); - curr_bd->buff_ptr = dma_map_single(emac_dev, curr_bd->data_ptr, - rxch->buf_size, DMA_FROM_DEVICE); - curr_bd->off_b_len = rxch->buf_size; - curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; - - /* write back to hardware memory */ - BD_CACHE_WRITEBACK_INVALIDATE((u32) curr_bd, - EMAC_BD_LENGTH_FOR_CACHE); - curr_bd->next = rxch->active_queue_head; - rxch->active_queue_head = curr_bd; - } - - /* At this point rxCppi->activeQueueHead points to the first - RX BD ready to be given to RX HDP and rxch->active_queue_tail - points to the last RX BD - */ - return 0; -} - -/** - * emac_rxch_teardown: RX channel teardown - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to teardown RX channel - * - */ -static void emac_rxch_teardown(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ - - while ((emac_read(EMAC_RXCP(ch)) & EMAC_TEARDOWN_VALUE) != - EMAC_TEARDOWN_VALUE) { - /* wait till tx teardown complete */ - cpu_relax(); /* TODO: check if this helps ... */ - --teardown_cnt; - if (0 == teardown_cnt) { - dev_err(emac_dev, "EMAC: RX teardown aborted\n"); - break; - } - } - emac_write(EMAC_RXCP(ch), EMAC_TEARDOWN_VALUE); -} - -/** - * emac_stop_rxch: Stop RX channel operation - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to stop RX channel operation - * - */ -static void emac_stop_rxch(struct emac_priv *priv, u32 ch) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - - if (rxch) { - rxch->teardown_pending = 1; - emac_write(EMAC_RXTEARDOWN, ch); - /* wait for teardown complete */ - emac_rxch_teardown(priv, ch); - rxch->teardown_pending = 0; - emac_write(EMAC_RXINTMASKCLEAR, BIT(ch)); - } -} - -/** - * emac_cleanup_rxch: Book-keep function to clean RX channel resources - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to clean up RX channel resources - * - */ -static void emac_cleanup_rxch(struct emac_priv *priv, u32 ch) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - struct emac_rx_bd __iomem *curr_bd; - - if (rxch) { - /* free the receive buffers previously allocated */ - curr_bd = rxch->active_queue_head; - while (curr_bd) { - if (curr_bd->buf_token) { - dma_unmap_single(&priv->ndev->dev, - curr_bd->buff_ptr, - curr_bd->off_b_len - & EMAC_RX_BD_BUF_SIZE, - DMA_FROM_DEVICE); - - dev_kfree_skb_any((struct sk_buff *)\ - curr_bd->buf_token); - } - curr_bd = curr_bd->next; - } - if (rxch->bd_mem) - rxch->bd_mem = NULL; - kfree(rxch); - priv->rxch[ch] = NULL; - } -} - -/** * emac_set_type0addr: Set EMAC Type0 mac address * @priv: The DaVinci EMAC private adapter structure * @ch: RX channel number @@ -2004,194 +1266,6 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) } /** - * emac_addbd_to_rx_queue: Recycle RX buffer descriptor - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number to process buffer descriptors for - * @curr_bd: current buffer descriptor - * @buffer: buffer pointer for descriptor - * @buf_token: buffer token (stores skb information) - * - * Prepares the recycled buffer descriptor and addes it to hardware - * receive queue - if queue empty this descriptor becomes the head - * else addes the descriptor to end of queue - * - */ -static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch, - struct emac_rx_bd __iomem *curr_bd, - char *buffer, void *buf_token) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - - /* populate the hardware descriptor */ - curr_bd->h_next = 0; - curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buffer, - rxch->buf_size, DMA_FROM_DEVICE); - curr_bd->off_b_len = rxch->buf_size; - curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; - curr_bd->next = NULL; - curr_bd->data_ptr = buffer; - curr_bd->buf_token = buf_token; - - /* write back */ - BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - if (rxch->active_queue_head == NULL) { - rxch->active_queue_head = curr_bd; - rxch->active_queue_tail = curr_bd; - if (0 != rxch->queue_active) { - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(rxch->active_queue_head, priv)); - rxch->queue_active = 1; - } - } else { - struct emac_rx_bd __iomem *tail_bd; - u32 frame_status; - - tail_bd = rxch->active_queue_tail; - rxch->active_queue_tail = curr_bd; - tail_bd->next = curr_bd; - tail_bd = EMAC_VIRT_NOCACHE(tail_bd); - tail_bd->h_next = emac_virt_to_phys(curr_bd, priv); - frame_status = tail_bd->mode; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - frame_status &= ~(EMAC_CPPI_EOQ_BIT); - tail_bd->mode = frame_status; - ++rxch->end_of_queue_add; - } - } - ++rxch->recycled_bd; -} - -/** - * emac_net_rx_cb: Prepares packet and sends to upper layer - * @priv: The DaVinci EMAC private adapter structure - * @net_pkt_list: Network packet list (received packets) - * - * Invalidates packet buffer memory and sends the received packet to upper - * layer - * - * Returns success or appropriate error code (none as of now) - */ -static int emac_net_rx_cb(struct emac_priv *priv, - struct emac_netpktobj *net_pkt_list) -{ - struct net_device *ndev = priv->ndev; - struct sk_buff *p_skb = net_pkt_list->pkt_token; - /* set length of packet */ - skb_put(p_skb, net_pkt_list->pkt_length); - p_skb->protocol = eth_type_trans(p_skb, priv->ndev); - netif_receive_skb(p_skb); - ndev->stats.rx_bytes += net_pkt_list->pkt_length; - ndev->stats.rx_packets++; - return 0; -} - -/** - * emac_rx_bdproc: RX buffer descriptor (packet) processing - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number to process buffer descriptors for - * @budget: number of packets allowed to process - * @pending: indication to caller that packets are pending to process - * - * Processes RX buffer descriptors - checks ownership bit on the RX buffer - * descriptor, sends the receive packet to upper layer, allocates a new SKB - * and recycles the buffer descriptor (requeues it in hardware RX queue). - * Only "budget" number of packets are processed and indication of pending - * packets provided to the caller. - * - * Returns number of packets processed (and indication of pending packets) - */ -static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) -{ - unsigned long flags; - u32 frame_status; - u32 pkts_processed = 0; - char *new_buffer; - struct emac_rx_bd __iomem *curr_bd; - struct emac_rx_bd __iomem *last_bd; - struct emac_netpktobj *curr_pkt, pkt_obj; - struct emac_netbufobj buf_obj; - struct emac_netbufobj *rx_buf_obj; - void *new_buf_token; - struct emac_rxch *rxch = priv->rxch[ch]; - - if (unlikely(1 == rxch->teardown_pending)) - return 0; - ++rxch->proc_count; - spin_lock_irqsave(&priv->rx_lock, flags); - pkt_obj.buf_list = &buf_obj; - curr_pkt = &pkt_obj; - curr_bd = rxch->active_queue_head; - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - - while ((curr_bd) && - ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && - (pkts_processed < budget)) { - - new_buffer = emac_net_alloc_rx_buf(priv, rxch->buf_size, - &new_buf_token, EMAC_DEF_RX_CH); - if (unlikely(NULL == new_buffer)) { - ++rxch->out_of_rx_buffers; - goto end_emac_rx_bdproc; - } - - /* populate received packet data structure */ - rx_buf_obj = &curr_pkt->buf_list[0]; - rx_buf_obj->data_ptr = (char *)curr_bd->data_ptr; - rx_buf_obj->length = curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE; - rx_buf_obj->buf_token = curr_bd->buf_token; - - dma_unmap_single(&priv->ndev->dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_FROM_DEVICE); - - curr_pkt->pkt_token = curr_pkt->buf_list->buf_token; - curr_pkt->num_bufs = 1; - curr_pkt->pkt_length = - (frame_status & EMAC_RX_BD_PKT_LENGTH_MASK); - emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd, priv)); - ++rxch->processed_bd; - last_bd = curr_bd; - curr_bd = last_bd->next; - rxch->active_queue_head = curr_bd; - - /* check if end of RX queue ? */ - if (frame_status & EMAC_CPPI_EOQ_BIT) { - if (curr_bd) { - ++rxch->mis_queued_packets; - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - } else { - ++rxch->end_of_queue; - rxch->queue_active = 0; - } - } - - /* recycle BD */ - emac_addbd_to_rx_queue(priv, ch, last_bd, new_buffer, - new_buf_token); - - /* return the packet to the user - BD ptr passed in - * last parameter for potential *future* use */ - spin_unlock_irqrestore(&priv->rx_lock, flags); - emac_net_rx_cb(priv, curr_pkt); - spin_lock_irqsave(&priv->rx_lock, flags); - curr_bd = rxch->active_queue_head; - if (curr_bd) { - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - } - ++pkts_processed; - } - -end_emac_rx_bdproc: - spin_unlock_irqrestore(&priv->rx_lock, flags); - return pkts_processed; -} - -/** * emac_hw_enable: Enable EMAC hardware for packet transmission/reception * @priv: The DaVinci EMAC private adapter structure * @@ -2717,8 +1791,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->ndev = ndev; priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG); - spin_lock_init(&priv->tx_lock); - spin_lock_init(&priv->rx_lock); spin_lock_init(&priv->lock); pdata = pdev->dev.platform_data; @@ -2766,8 +1838,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) ndev->base_addr = (unsigned long)priv->remap_addr; priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset; - priv->ctrl_ram_size = pdata->ctrl_ram_size; - priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset; hw_ram_addr = pdata->hw_ram_addr; if (!hw_ram_addr) -- 1.7.0.4 From cyril at ti.com Tue Sep 14 16:10:10 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Tue, 14 Sep 2010 17:10:10 -0400 Subject: [PATCH v4 08/10] net: davinci_emac: separate out cpdma code In-Reply-To: <1284498612-25294-1-git-send-email-cyril@ti.com> References: <1284498612-25294-1-git-send-email-cyril@ti.com> Message-ID: <1284498612-25294-9-git-send-email-cyril@ti.com> In addition to being embedded into the EMAC controller, the CPDMA hardware block is used in TI's CPSW switch controller. Fortunately, the programming interface to this hardware block remains pretty nicely consistent across these devices. This patch adds a new CPDMA services layer, which can then be reused across EMAC and CPSW drivers. Signed-off-by: Cyril Chemparathy Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- drivers/net/Kconfig | 10 + drivers/net/Makefile | 1 + drivers/net/davinci_cpdma.c | 965 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/davinci_cpdma.h | 108 +++++ 4 files changed, 1084 insertions(+), 0 deletions(-) create mode 100644 drivers/net/davinci_cpdma.c create mode 100644 drivers/net/davinci_cpdma.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 911e7f1..775fd87 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -952,6 +952,7 @@ config TI_DAVINCI_EMAC tristate "TI DaVinci EMAC Support" depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) select TI_DAVINCI_MDIO + select TI_DAVINCI_CPDMA select PHYLIB help This driver supports TI's DaVinci Ethernet . @@ -969,6 +970,15 @@ config TI_DAVINCI_MDIO To compile this driver as a module, choose M here: the module will be called davinci_mdio. This is recommended. +config TI_DAVINCI_CPDMA + tristate "TI DaVinci CPDMA Support" + depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + help + This driver supports TI's DaVinci CPDMA dma engine. + + To compile this driver as a module, choose M here: the module + will be called davinci_cpdma. This is recommended. + config DM9000 tristate "DM9000 support" depends on ARM || BLACKFIN || MIPS diff --git a/drivers/net/Makefile b/drivers/net/Makefile index d38a7ab..65da885 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_PHYLIB) += phy/ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o +obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_E1000E) += e1000e/ diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c new file mode 100644 index 0000000..e92b2b6 --- /dev/null +++ b/drivers/net/davinci_cpdma.c @@ -0,0 +1,965 @@ +/* + * Texas Instruments CPDMA Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "davinci_cpdma.h" + +/* DMA Registers */ +#define CPDMA_TXIDVER 0x00 +#define CPDMA_TXCONTROL 0x04 +#define CPDMA_TXTEARDOWN 0x08 +#define CPDMA_RXIDVER 0x10 +#define CPDMA_RXCONTROL 0x14 +#define CPDMA_SOFTRESET 0x1c +#define CPDMA_RXTEARDOWN 0x18 +#define CPDMA_TXINTSTATRAW 0x80 +#define CPDMA_TXINTSTATMASKED 0x84 +#define CPDMA_TXINTMASKSET 0x88 +#define CPDMA_TXINTMASKCLEAR 0x8c +#define CPDMA_MACINVECTOR 0x90 +#define CPDMA_MACEOIVECTOR 0x94 +#define CPDMA_RXINTSTATRAW 0xa0 +#define CPDMA_RXINTSTATMASKED 0xa4 +#define CPDMA_RXINTMASKSET 0xa8 +#define CPDMA_RXINTMASKCLEAR 0xac +#define CPDMA_DMAINTSTATRAW 0xb0 +#define CPDMA_DMAINTSTATMASKED 0xb4 +#define CPDMA_DMAINTMASKSET 0xb8 +#define CPDMA_DMAINTMASKCLEAR 0xbc +#define CPDMA_DMAINT_HOSTERR BIT(1) + +/* the following exist only if has_ext_regs is set */ +#define CPDMA_DMACONTROL 0x20 +#define CPDMA_DMASTATUS 0x24 +#define CPDMA_RXBUFFOFS 0x28 +#define CPDMA_EM_CONTROL 0x2c + +/* Descriptor mode bits */ +#define CPDMA_DESC_SOP BIT(31) +#define CPDMA_DESC_EOP BIT(30) +#define CPDMA_DESC_OWNER BIT(29) +#define CPDMA_DESC_EOQ BIT(28) +#define CPDMA_DESC_TD_COMPLETE BIT(27) +#define CPDMA_DESC_PASS_CRC BIT(26) + +#define CPDMA_TEARDOWN_VALUE 0xfffffffc + +struct cpdma_desc { + /* hardware fields */ + u32 hw_next; + u32 hw_buffer; + u32 hw_len; + u32 hw_mode; + /* software fields */ + void *sw_token; + u32 sw_buffer; + u32 sw_len; +}; + +struct cpdma_desc_pool { + u32 phys; + void __iomem *iomap; /* ioremap map */ + void *cpumap; /* dma_alloc map */ + int desc_size, mem_size; + int num_desc, used_desc; + unsigned long *bitmap; + struct device *dev; + spinlock_t lock; +}; + +enum cpdma_state { + CPDMA_STATE_IDLE, + CPDMA_STATE_ACTIVE, + CPDMA_STATE_TEARDOWN, +}; + +const char *cpdma_state_str[] = { "idle", "active", "teardown" }; + +struct cpdma_ctlr { + enum cpdma_state state; + struct cpdma_params params; + struct device *dev; + struct cpdma_desc_pool *pool; + spinlock_t lock; + struct cpdma_chan *channels[2 * CPDMA_MAX_CHANNELS]; +}; + +struct cpdma_chan { + enum cpdma_state state; + struct cpdma_ctlr *ctlr; + int chan_num; + spinlock_t lock; + struct cpdma_desc __iomem *head, *tail; + int count; + void __iomem *hdp, *cp, *rxfree; + u32 mask; + cpdma_handler_fn handler; + enum dma_data_direction dir; + struct cpdma_chan_stats stats; + /* offsets into dmaregs */ + int int_set, int_clear, td; +}; + +/* The following make access to common cpdma_ctlr params more readable */ +#define dmaregs params.dmaregs +#define num_chan params.num_chan + +/* various accessors */ +#define dma_reg_read(ctlr, ofs) __raw_readl((ctlr)->dmaregs + (ofs)) +#define chan_read(chan, fld) __raw_readl((chan)->fld) +#define desc_read(desc, fld) __raw_readl(&(desc)->fld) +#define dma_reg_write(ctlr, ofs, v) __raw_writel(v, (ctlr)->dmaregs + (ofs)) +#define chan_write(chan, fld, v) __raw_writel(v, (chan)->fld) +#define desc_write(desc, fld, v) __raw_writel((u32)(v), &(desc)->fld) + +/* + * Utility constructs for a cpdma descriptor pool. Some devices (e.g. davinci + * emac) have dedicated on-chip memory for these descriptors. Some other + * devices (e.g. cpsw switches) use plain old memory. Descriptor pools + * abstract out these details + */ +static struct cpdma_desc_pool * +cpdma_desc_pool_create(struct device *dev, u32 phys, int size, int align) +{ + int bitmap_size; + struct cpdma_desc_pool *pool; + + pool = kzalloc(sizeof(*pool), GFP_KERNEL); + if (!pool) + return NULL; + + spin_lock_init(&pool->lock); + + pool->dev = dev; + pool->mem_size = size; + pool->desc_size = ALIGN(sizeof(struct cpdma_desc), align); + pool->num_desc = size / pool->desc_size; + + bitmap_size = (pool->num_desc / BITS_PER_LONG) * sizeof(long); + pool->bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!pool->bitmap) + goto fail; + + if (phys) { + pool->phys = phys; + pool->iomap = ioremap(phys, size); + } else { + pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys, + GFP_KERNEL); + pool->iomap = (void __force __iomem *)pool->cpumap; + } + + if (pool->iomap) + return pool; + +fail: + kfree(pool->bitmap); + kfree(pool); + return NULL; +} + +static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool) +{ + unsigned long flags; + + if (!pool) + return; + + spin_lock_irqsave(&pool->lock, flags); + WARN_ON(pool->used_desc); + kfree(pool->bitmap); + if (pool->cpumap) { + dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap, + pool->phys); + } else { + iounmap(pool->iomap); + } + spin_unlock_irqrestore(&pool->lock, flags); + kfree(pool); +} + +static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool, + struct cpdma_desc __iomem *desc) +{ + if (!desc) + return 0; + return pool->phys + (__force dma_addr_t)desc - + (__force dma_addr_t)pool->iomap; +} + +static inline struct cpdma_desc __iomem * +desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma) +{ + return dma ? pool->iomap + dma - pool->phys : NULL; +} + +static struct cpdma_desc __iomem * +cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc) +{ + unsigned long flags; + int index; + struct cpdma_desc __iomem *desc = NULL; + + spin_lock_irqsave(&pool->lock, flags); + + index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0, + num_desc, 0); + if (index < pool->num_desc) { + bitmap_set(pool->bitmap, index, num_desc); + desc = pool->iomap + pool->desc_size * index; + pool->used_desc++; + } + + spin_unlock_irqrestore(&pool->lock, flags); + return desc; +} + +static void cpdma_desc_free(struct cpdma_desc_pool *pool, + struct cpdma_desc __iomem *desc, int num_desc) +{ + unsigned long flags, index; + + index = ((unsigned long)desc - (unsigned long)pool->iomap) / + pool->desc_size; + spin_lock_irqsave(&pool->lock, flags); + bitmap_clear(pool->bitmap, index, num_desc); + pool->used_desc--; + spin_unlock_irqrestore(&pool->lock, flags); +} + +struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params) +{ + struct cpdma_ctlr *ctlr; + + ctlr = kzalloc(sizeof(*ctlr), GFP_KERNEL); + if (!ctlr) + return NULL; + + ctlr->state = CPDMA_STATE_IDLE; + ctlr->params = *params; + ctlr->dev = params->dev; + spin_lock_init(&ctlr->lock); + + ctlr->pool = cpdma_desc_pool_create(ctlr->dev, + ctlr->params.desc_mem_phys, + ctlr->params.desc_mem_size, + ctlr->params.desc_align); + if (!ctlr->pool) { + kfree(ctlr); + return NULL; + } + + if (WARN_ON(ctlr->num_chan > CPDMA_MAX_CHANNELS)) + ctlr->num_chan = CPDMA_MAX_CHANNELS; + return ctlr; +} + +int cpdma_ctlr_start(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_IDLE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EBUSY; + } + + if (ctlr->params.has_soft_reset) { + unsigned long timeout = jiffies + HZ/10; + + dma_reg_write(ctlr, CPDMA_SOFTRESET, 1); + while (time_before(jiffies, timeout)) { + if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0) + break; + } + WARN_ON(!time_before(jiffies, timeout)); + } + + for (i = 0; i < ctlr->num_chan; i++) { + __raw_writel(0, ctlr->params.txhdp + 4 * i); + __raw_writel(0, ctlr->params.rxhdp + 4 * i); + __raw_writel(0, ctlr->params.txcp + 4 * i); + __raw_writel(0, ctlr->params.rxcp + 4 * i); + } + + dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); + dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); + + dma_reg_write(ctlr, CPDMA_TXCONTROL, 1); + dma_reg_write(ctlr, CPDMA_RXCONTROL, 1); + + ctlr->state = CPDMA_STATE_ACTIVE; + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_start(ctlr->channels[i]); + } + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EINVAL; + } + + ctlr->state = CPDMA_STATE_TEARDOWN; + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_stop(ctlr->channels[i]); + } + + dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); + dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); + + dma_reg_write(ctlr, CPDMA_TXCONTROL, 0); + dma_reg_write(ctlr, CPDMA_RXCONTROL, 0); + + ctlr->state = CPDMA_STATE_IDLE; + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr) +{ + struct device *dev = ctlr->dev; + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + + dev_info(dev, "CPDMA: state: %s", cpdma_state_str[ctlr->state]); + + dev_info(dev, "CPDMA: txidver: %x", + dma_reg_read(ctlr, CPDMA_TXIDVER)); + dev_info(dev, "CPDMA: txcontrol: %x", + dma_reg_read(ctlr, CPDMA_TXCONTROL)); + dev_info(dev, "CPDMA: txteardown: %x", + dma_reg_read(ctlr, CPDMA_TXTEARDOWN)); + dev_info(dev, "CPDMA: rxidver: %x", + dma_reg_read(ctlr, CPDMA_RXIDVER)); + dev_info(dev, "CPDMA: rxcontrol: %x", + dma_reg_read(ctlr, CPDMA_RXCONTROL)); + dev_info(dev, "CPDMA: softreset: %x", + dma_reg_read(ctlr, CPDMA_SOFTRESET)); + dev_info(dev, "CPDMA: rxteardown: %x", + dma_reg_read(ctlr, CPDMA_RXTEARDOWN)); + dev_info(dev, "CPDMA: txintstatraw: %x", + dma_reg_read(ctlr, CPDMA_TXINTSTATRAW)); + dev_info(dev, "CPDMA: txintstatmasked: %x", + dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED)); + dev_info(dev, "CPDMA: txintmaskset: %x", + dma_reg_read(ctlr, CPDMA_TXINTMASKSET)); + dev_info(dev, "CPDMA: txintmaskclear: %x", + dma_reg_read(ctlr, CPDMA_TXINTMASKCLEAR)); + dev_info(dev, "CPDMA: macinvector: %x", + dma_reg_read(ctlr, CPDMA_MACINVECTOR)); + dev_info(dev, "CPDMA: maceoivector: %x", + dma_reg_read(ctlr, CPDMA_MACEOIVECTOR)); + dev_info(dev, "CPDMA: rxintstatraw: %x", + dma_reg_read(ctlr, CPDMA_RXINTSTATRAW)); + dev_info(dev, "CPDMA: rxintstatmasked: %x", + dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED)); + dev_info(dev, "CPDMA: rxintmaskset: %x", + dma_reg_read(ctlr, CPDMA_RXINTMASKSET)); + dev_info(dev, "CPDMA: rxintmaskclear: %x", + dma_reg_read(ctlr, CPDMA_RXINTMASKCLEAR)); + dev_info(dev, "CPDMA: dmaintstatraw: %x", + dma_reg_read(ctlr, CPDMA_DMAINTSTATRAW)); + dev_info(dev, "CPDMA: dmaintstatmasked: %x", + dma_reg_read(ctlr, CPDMA_DMAINTSTATMASKED)); + dev_info(dev, "CPDMA: dmaintmaskset: %x", + dma_reg_read(ctlr, CPDMA_DMAINTMASKSET)); + dev_info(dev, "CPDMA: dmaintmaskclear: %x", + dma_reg_read(ctlr, CPDMA_DMAINTMASKCLEAR)); + + if (!ctlr->params.has_ext_regs) { + dev_info(dev, "CPDMA: dmacontrol: %x", + dma_reg_read(ctlr, CPDMA_DMACONTROL)); + dev_info(dev, "CPDMA: dmastatus: %x", + dma_reg_read(ctlr, CPDMA_DMASTATUS)); + dev_info(dev, "CPDMA: rxbuffofs: %x", + dma_reg_read(ctlr, CPDMA_RXBUFFOFS)); + } + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) + if (ctlr->channels[i]) + cpdma_chan_dump(ctlr->channels[i]); + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int ret = 0, i; + + if (!ctlr) + return -EINVAL; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_IDLE) + cpdma_ctlr_stop(ctlr); + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_destroy(ctlr->channels[i]); + } + + cpdma_desc_pool_destroy(ctlr->pool); + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(ctlr); + return ret; +} + +int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable) +{ + unsigned long flags; + int i, reg; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EINVAL; + } + + reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR; + dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR); + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_int_ctrl(ctlr->channels[i], enable); + } + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr) +{ + dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0); +} + +struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, + cpdma_handler_fn handler) +{ + struct cpdma_chan *chan; + int ret, offset = (chan_num % CPDMA_MAX_CHANNELS) * 4; + unsigned long flags; + + if (__chan_linear(chan_num) >= ctlr->num_chan) + return NULL; + + ret = -ENOMEM; + chan = kzalloc(sizeof(*chan), GFP_KERNEL); + if (!chan) + goto err_chan_alloc; + + spin_lock_irqsave(&ctlr->lock, flags); + ret = -EBUSY; + if (ctlr->channels[chan_num]) + goto err_chan_busy; + + chan->ctlr = ctlr; + chan->state = CPDMA_STATE_IDLE; + chan->chan_num = chan_num; + chan->handler = handler; + + if (is_rx_chan(chan)) { + chan->hdp = ctlr->params.rxhdp + offset; + chan->cp = ctlr->params.rxcp + offset; + chan->rxfree = ctlr->params.rxfree + offset; + chan->int_set = CPDMA_RXINTMASKSET; + chan->int_clear = CPDMA_RXINTMASKCLEAR; + chan->td = CPDMA_RXTEARDOWN; + chan->dir = DMA_FROM_DEVICE; + } else { + chan->hdp = ctlr->params.txhdp + offset; + chan->cp = ctlr->params.txcp + offset; + chan->int_set = CPDMA_TXINTMASKSET; + chan->int_clear = CPDMA_TXINTMASKCLEAR; + chan->td = CPDMA_TXTEARDOWN; + chan->dir = DMA_TO_DEVICE; + } + chan->mask = BIT(chan_linear(chan)); + + spin_lock_init(&chan->lock); + + ctlr->channels[chan_num] = chan; + spin_unlock_irqrestore(&ctlr->lock, flags); + return chan; + +err_chan_busy: + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(chan); +err_chan_alloc: + return ERR_PTR(ret); +} + +int cpdma_chan_destroy(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + unsigned long flags; + + if (!chan) + return -EINVAL; + + spin_lock_irqsave(&ctlr->lock, flags); + if (chan->state != CPDMA_STATE_IDLE) + cpdma_chan_stop(chan); + ctlr->channels[chan->chan_num] = NULL; + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(chan); + return 0; +} + +int cpdma_chan_get_stats(struct cpdma_chan *chan, + struct cpdma_chan_stats *stats) +{ + unsigned long flags; + if (!chan) + return -EINVAL; + spin_lock_irqsave(&chan->lock, flags); + memcpy(stats, &chan->stats, sizeof(*stats)); + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +int cpdma_chan_dump(struct cpdma_chan *chan) +{ + unsigned long flags; + struct device *dev = chan->ctlr->dev; + + spin_lock_irqsave(&chan->lock, flags); + + dev_info(dev, "channel %d (%s %d) state %s", + chan->chan_num, is_rx_chan(chan) ? "rx" : "tx", + chan_linear(chan), cpdma_state_str[chan->state]); + dev_info(dev, "\thdp: %x\n", chan_read(chan, hdp)); + dev_info(dev, "\tcp: %x\n", chan_read(chan, cp)); + if (chan->rxfree) { + dev_info(dev, "\trxfree: %x\n", + chan_read(chan, rxfree)); + } + + dev_info(dev, "\tstats head_enqueue: %d\n", + chan->stats.head_enqueue); + dev_info(dev, "\tstats tail_enqueue: %d\n", + chan->stats.tail_enqueue); + dev_info(dev, "\tstats pad_enqueue: %d\n", + chan->stats.pad_enqueue); + dev_info(dev, "\tstats misqueued: %d\n", + chan->stats.misqueued); + dev_info(dev, "\tstats desc_alloc_fail: %d\n", + chan->stats.desc_alloc_fail); + dev_info(dev, "\tstats pad_alloc_fail: %d\n", + chan->stats.pad_alloc_fail); + dev_info(dev, "\tstats runt_receive_buff: %d\n", + chan->stats.runt_receive_buff); + dev_info(dev, "\tstats runt_transmit_buff: %d\n", + chan->stats.runt_transmit_buff); + dev_info(dev, "\tstats empty_dequeue: %d\n", + chan->stats.empty_dequeue); + dev_info(dev, "\tstats busy_dequeue: %d\n", + chan->stats.busy_dequeue); + dev_info(dev, "\tstats good_dequeue: %d\n", + chan->stats.good_dequeue); + dev_info(dev, "\tstats requeue: %d\n", + chan->stats.requeue); + dev_info(dev, "\tstats teardown_dequeue: %d\n", + chan->stats.teardown_dequeue); + + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +static void __cpdma_chan_submit(struct cpdma_chan *chan, + struct cpdma_desc __iomem *desc) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *prev = chan->tail; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t desc_dma; + u32 mode; + + desc_dma = desc_phys(pool, desc); + + /* simple case - idle channel */ + if (!chan->head) { + chan->stats.head_enqueue++; + chan->head = desc; + chan->tail = desc; + if (chan->state == CPDMA_STATE_ACTIVE) + chan_write(chan, hdp, desc_dma); + return; + } + + /* first chain the descriptor at the tail of the list */ + desc_write(prev, hw_next, desc_dma); + chan->tail = desc; + chan->stats.tail_enqueue++; + + /* next check if EOQ has been triggered already */ + mode = desc_read(prev, hw_mode); + if (((mode & (CPDMA_DESC_EOQ | CPDMA_DESC_OWNER)) == CPDMA_DESC_EOQ) && + (chan->state == CPDMA_STATE_ACTIVE)) { + desc_write(prev, hw_mode, mode & ~CPDMA_DESC_EOQ); + chan_write(chan, hdp, desc_dma); + chan->stats.misqueued++; + } +} + +int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, + int len, gfp_t gfp_mask) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *desc; + dma_addr_t buffer; + unsigned long flags; + u32 mode; + int ret = 0; + + spin_lock_irqsave(&chan->lock, flags); + + if (chan->state == CPDMA_STATE_TEARDOWN) { + ret = -EINVAL; + goto unlock_ret; + } + + desc = cpdma_desc_alloc(ctlr->pool, 1); + if (!desc) { + chan->stats.desc_alloc_fail++; + ret = -ENOMEM; + goto unlock_ret; + } + + if (len < ctlr->params.min_packet_size) { + len = ctlr->params.min_packet_size; + chan->stats.runt_transmit_buff++; + } + + buffer = dma_map_single(ctlr->dev, data, len, chan->dir); + mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP; + + desc_write(desc, hw_next, 0); + desc_write(desc, hw_buffer, buffer); + desc_write(desc, hw_len, len); + desc_write(desc, hw_mode, mode | len); + desc_write(desc, sw_token, token); + desc_write(desc, sw_buffer, buffer); + desc_write(desc, sw_len, len); + + __cpdma_chan_submit(chan, desc); + + if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree) + chan_write(chan, rxfree, 1); + + chan->count++; + +unlock_ret: + spin_unlock_irqrestore(&chan->lock, flags); + return ret; +} + +static void __cpdma_chan_free(struct cpdma_chan *chan, + struct cpdma_desc __iomem *desc, + int outlen, int status) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t buff_dma; + int origlen; + void *token; + + token = (void *)desc_read(desc, sw_token); + buff_dma = desc_read(desc, sw_buffer); + origlen = desc_read(desc, sw_len); + + dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir); + cpdma_desc_free(pool, desc, 1); + (*chan->handler)(token, outlen, status); +} + +static int __cpdma_chan_process(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *desc; + int status, outlen; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t desc_dma; + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + + desc = chan->head; + if (!desc) { + chan->stats.empty_dequeue++; + status = -ENOENT; + goto unlock_ret; + } + desc_dma = desc_phys(pool, desc); + + status = __raw_readl(&desc->hw_mode); + outlen = status & 0x7ff; + if (status & CPDMA_DESC_OWNER) { + chan->stats.busy_dequeue++; + status = -EBUSY; + goto unlock_ret; + } + status = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE); + + chan->head = desc_from_phys(pool, desc_read(desc, hw_next)); + chan_write(chan, cp, desc_dma); + chan->count--; + chan->stats.good_dequeue++; + + if (status & CPDMA_DESC_EOQ) { + chan->stats.requeue++; + chan_write(chan, hdp, desc_phys(pool, chan->head)); + } + + spin_unlock_irqrestore(&chan->lock, flags); + + __cpdma_chan_free(chan, desc, outlen, status); + return status; + +unlock_ret: + spin_unlock_irqrestore(&chan->lock, flags); + return status; +} + +int cpdma_chan_process(struct cpdma_chan *chan, int quota) +{ + int used = 0, ret = 0; + + if (chan->state != CPDMA_STATE_ACTIVE) + return -EINVAL; + + while (used < quota) { + ret = __cpdma_chan_process(chan); + if (ret < 0) + break; + used++; + } + return used; +} + +int cpdma_chan_start(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_IDLE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EBUSY; + } + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + dma_reg_write(ctlr, chan->int_set, chan->mask); + chan->state = CPDMA_STATE_ACTIVE; + if (chan->head) { + chan_write(chan, hdp, desc_phys(pool, chan->head)); + if (chan->rxfree) + chan_write(chan, rxfree, chan->count); + } + + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +int cpdma_chan_stop(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + unsigned long flags; + int ret; + unsigned long timeout; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + + chan->state = CPDMA_STATE_TEARDOWN; + dma_reg_write(ctlr, chan->int_clear, chan->mask); + + /* trigger teardown */ + dma_reg_write(ctlr, chan->td, chan->chan_num); + + /* wait for teardown complete */ + timeout = jiffies + HZ/10; /* 100 msec */ + while (time_before(jiffies, timeout)) { + u32 cp = chan_read(chan, cp); + if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE) + break; + cpu_relax(); + } + WARN_ON(!time_before(jiffies, timeout)); + chan_write(chan, cp, CPDMA_TEARDOWN_VALUE); + + /* handle completed packets */ + do { + ret = __cpdma_chan_process(chan); + if (ret < 0) + break; + } while ((ret & CPDMA_DESC_TD_COMPLETE) == 0); + + /* remaining packets haven't been tx/rx'ed, clean them up */ + while (chan->head) { + struct cpdma_desc __iomem *desc = chan->head; + dma_addr_t next_dma; + + next_dma = desc_read(desc, hw_next); + chan->head = desc_from_phys(pool, next_dma); + chan->stats.teardown_dequeue++; + + /* issue callback without locks held */ + spin_unlock_irqrestore(&chan->lock, flags); + __cpdma_chan_free(chan, desc, 0, -ENOSYS); + spin_lock_irqsave(&chan->lock, flags); + } + + chan->state = CPDMA_STATE_IDLE; + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable) +{ + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + + dma_reg_write(chan->ctlr, enable ? chan->int_set : chan->int_clear, + chan->mask); + spin_unlock_irqrestore(&chan->lock, flags); + + return 0; +} + +struct cpdma_control_info { + u32 reg; + u32 shift, mask; + int access; +#define ACCESS_RO BIT(0) +#define ACCESS_WO BIT(1) +#define ACCESS_RW (ACCESS_RO | ACCESS_WO) +}; + +struct cpdma_control_info controls[] = { + [CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO}, + [CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL, 4, 1, ACCESS_RW}, + [CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL, 2, 1, ACCESS_RW}, + [CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL, 1, 1, ACCESS_RW}, + [CPDMA_TX_PRIO_FIXED] = {CPDMA_DMACONTROL, 0, 1, ACCESS_RW}, + [CPDMA_STAT_IDLE] = {CPDMA_DMASTATUS, 31, 1, ACCESS_RO}, + [CPDMA_STAT_TX_ERR_CODE] = {CPDMA_DMASTATUS, 20, 0xf, ACCESS_RW}, + [CPDMA_STAT_TX_ERR_CHAN] = {CPDMA_DMASTATUS, 16, 0x7, ACCESS_RW}, + [CPDMA_STAT_RX_ERR_CODE] = {CPDMA_DMASTATUS, 12, 0xf, ACCESS_RW}, + [CPDMA_STAT_RX_ERR_CHAN] = {CPDMA_DMASTATUS, 8, 0x7, ACCESS_RW}, + [CPDMA_RX_BUFFER_OFFSET] = {CPDMA_RXBUFFOFS, 0, 0xffff, ACCESS_RW}, +}; + +int cpdma_control_get(struct cpdma_ctlr *ctlr, int control) +{ + unsigned long flags; + struct cpdma_control_info *info = &controls[control]; + int ret; + + spin_lock_irqsave(&ctlr->lock, flags); + + ret = -ENOTSUPP; + if (!ctlr->params.has_ext_regs) + goto unlock_ret; + + ret = -EINVAL; + if (ctlr->state != CPDMA_STATE_ACTIVE) + goto unlock_ret; + + ret = -ENOENT; + if (control < 0 || control >= ARRAY_SIZE(controls)) + goto unlock_ret; + + ret = -EPERM; + if ((info->access & ACCESS_RO) != ACCESS_RO) + goto unlock_ret; + + ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask; + +unlock_ret: + spin_unlock_irqrestore(&ctlr->lock, flags); + return ret; +} + +int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value) +{ + unsigned long flags; + struct cpdma_control_info *info = &controls[control]; + int ret; + u32 val; + + spin_lock_irqsave(&ctlr->lock, flags); + + ret = -ENOTSUPP; + if (!ctlr->params.has_ext_regs) + goto unlock_ret; + + ret = -EINVAL; + if (ctlr->state != CPDMA_STATE_ACTIVE) + goto unlock_ret; + + ret = -ENOENT; + if (control < 0 || control >= ARRAY_SIZE(controls)) + goto unlock_ret; + + ret = -EPERM; + if ((info->access & ACCESS_WO) != ACCESS_WO) + goto unlock_ret; + + val = dma_reg_read(ctlr, info->reg); + val &= ~(info->mask << info->shift); + val |= (value & info->mask) << info->shift; + dma_reg_write(ctlr, info->reg, val); + ret = 0; + +unlock_ret: + spin_unlock_irqrestore(&ctlr->lock, flags); + return ret; +} diff --git a/drivers/net/davinci_cpdma.h b/drivers/net/davinci_cpdma.h new file mode 100644 index 0000000..868e50e --- /dev/null +++ b/drivers/net/davinci_cpdma.h @@ -0,0 +1,108 @@ +/* + * Texas Instruments CPDMA Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __DAVINCI_CPDMA_H__ +#define __DAVINCI_CPDMA_H__ + +#define CPDMA_MAX_CHANNELS BITS_PER_LONG + +#define tx_chan_num(chan) (chan) +#define rx_chan_num(chan) ((chan) + CPDMA_MAX_CHANNELS) +#define is_rx_chan(chan) ((chan)->chan_num >= CPDMA_MAX_CHANNELS) +#define is_tx_chan(chan) (!is_rx_chan(chan)) +#define __chan_linear(chan_num) ((chan_num) & (CPDMA_MAX_CHANNELS - 1)) +#define chan_linear(chan) __chan_linear((chan)->chan_num) + +struct cpdma_params { + struct device *dev; + void __iomem *dmaregs; + void __iomem *txhdp, *rxhdp, *txcp, *rxcp; + void __iomem *rxthresh, *rxfree; + int num_chan; + bool has_soft_reset; + int min_packet_size; + u32 desc_mem_phys; + int desc_mem_size; + int desc_align; + + /* + * Some instances of embedded cpdma controllers have extra control and + * status registers. The following flag enables access to these + * "extended" registers. + */ + bool has_ext_regs; +}; + +struct cpdma_chan_stats { + u32 head_enqueue; + u32 tail_enqueue; + u32 pad_enqueue; + u32 misqueued; + u32 desc_alloc_fail; + u32 pad_alloc_fail; + u32 runt_receive_buff; + u32 runt_transmit_buff; + u32 empty_dequeue; + u32 busy_dequeue; + u32 good_dequeue; + u32 requeue; + u32 teardown_dequeue; +}; + +struct cpdma_ctlr; +struct cpdma_chan; + +typedef void (*cpdma_handler_fn)(void *token, int len, int status); + +struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params); +int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_start(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr); + +struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, + cpdma_handler_fn handler); +int cpdma_chan_destroy(struct cpdma_chan *chan); +int cpdma_chan_start(struct cpdma_chan *chan); +int cpdma_chan_stop(struct cpdma_chan *chan); +int cpdma_chan_dump(struct cpdma_chan *chan); + +int cpdma_chan_get_stats(struct cpdma_chan *chan, + struct cpdma_chan_stats *stats); +int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, + int len, gfp_t gfp_mask); +int cpdma_chan_process(struct cpdma_chan *chan, int quota); + +int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable); +void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr); +int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable); + +enum cpdma_control { + CPDMA_CMD_IDLE, /* write-only */ + CPDMA_COPY_ERROR_FRAMES, /* read-write */ + CPDMA_RX_OFF_LEN_UPDATE, /* read-write */ + CPDMA_RX_OWNERSHIP_FLIP, /* read-write */ + CPDMA_TX_PRIO_FIXED, /* read-write */ + CPDMA_STAT_IDLE, /* read-only */ + CPDMA_STAT_TX_ERR_CHAN, /* read-only */ + CPDMA_STAT_TX_ERR_CODE, /* read-only */ + CPDMA_STAT_RX_ERR_CHAN, /* read-only */ + CPDMA_STAT_RX_ERR_CODE, /* read-only */ + CPDMA_RX_BUFFER_OFFSET, /* read-write */ +}; + +int cpdma_control_get(struct cpdma_ctlr *ctlr, int control); +int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value); + +#endif -- 1.7.0.4 From khilman at deeprootsystems.com Tue Sep 14 18:10:48 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Tue, 14 Sep 2010 16:10:48 -0700 Subject: [PATCH v4 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <1284498612-25294-1-git-send-email-cyril@ti.com> (Cyril Chemparathy's message of "Tue, 14 Sep 2010 17:10:02 -0400") References: <1284498612-25294-1-git-send-email-cyril@ti.com> Message-ID: <87k4mnj4zr.fsf@deeprootsystems.com> Cyril Chemparathy writes: > Davinci's EMAC device has an in-built MDIO controller and a CPDMA engine. > These hardware modules are not restricted to EMAC device alone. For example, > CPSW3G (3-port gigabit ethernet switch) hardware uses these very same modules > internally. This patch series separates out EMAC's MDIO and CPDMA > functionality, allowing these individual pieces to be reused across TI > hardware. [...] > Changes from v3 (rolled in "post cpdma/mdio refactoring fixes" series): > 1. allow forced 100/full mode instead of phy auto-detect > 2. specify phy_id on boards that had a phy_mask defined earlier > 3. requeue cpdma descriptors when EOQ at submit > 4. use calculated mdio bus access times instead of hardcoded delays > 5. work around emac soft-reset impact on mdio controller state > 6. extend register dumps to include cpdma registers Minor nit: you should remove the Michael's and Caglar's Tested-by on the omap:* patches as I don't believe they tested those. While you're at it, please add Tony's ack. Feel free to just update those two patches, and I'll queue up this updated series. Thanks, Kevin From Jon.Povey at racelogic.co.uk Tue Sep 14 21:06:37 2010 From: Jon.Povey at racelogic.co.uk (Jon Povey) Date: Wed, 15 Sep 2010 03:06:37 +0100 Subject: Prefered web server fo Davinci In-Reply-To: <55D474137AF1C541A021F8D73F85CF5D4207993934@ACDCE7MB3.commscope.com> Message-ID: <70E876B0EA86DD4BAF101844BC814DFE0903E89713@Cloud.RL.local> davinci-linux-open-source-bounces at linux.davincidsp.com wrote: > Could someone please tell me if there is a better, smaller, > easier to cross compile, and secure web server that you would > recommend? http://www.acme.com/software/thttpd/ looks promising at a glance. I haven't tried it, but it's small and uses GNU configure so may not be painful to cross-compile. I'd be interested to know your results - I may need to do something similar soon. As for security.. always a crapshoot. Perhaps you gain a little security through obscurity not using Apache. -- Jon Povey jon.povey at racelogic.co.uk Racelogic is a limited company registered in England. Registered number 2743719 . Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB . The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network From Vinod_Nanjaiah at mindtree.com Wed Sep 15 00:11:27 2010 From: Vinod_Nanjaiah at mindtree.com (Vinod Nanjaiah) Date: Wed, 15 Sep 2010 10:41:27 +0530 Subject: Prefered web server fo Davinci In-Reply-To: References: Message-ID: <1B3CA99331DE5E47BB89385002F8D1EF115DDA2A6C@MTW02MSG02.mindtree.com> Could someone please tell me if there is a better, smaller, easier to cross compile, and secure web server that you would recommend? Thanks Michael Rondeau You could try the boa web server. Regards, Vinod http://www.mindtree.com/email/disclaimer.html From mdeneen+davinci at saucontech.com Wed Sep 15 08:35:18 2010 From: mdeneen+davinci at saucontech.com (Mark Deneen) Date: Wed, 15 Sep 2010 09:35:18 -0400 Subject: Prefered web server fo Davinci In-Reply-To: <70E876B0EA86DD4BAF101844BC814DFE0903E89713@Cloud.RL.local> References: <70E876B0EA86DD4BAF101844BC814DFE0903E89713@Cloud.RL.local> Message-ID: <1284557718.16883.11.camel@mdeneen.sdc.saucontech.com> On Wed, 2010-09-15 at 03:06 +0100, Jon Povey wrote: > davinci-linux-open-source-bounces at linux.davincidsp.com wrote: > > Could someone please tell me if there is a better, smaller, > > easier to cross compile, and secure web server that you would > > recommend? > > http://www.acme.com/software/thttpd/ looks promising at a glance. > I haven't tried it, but it's small and uses GNU configure so may > not be painful to cross-compile. > > I'd be interested to know your results - I may need to do something > similar soon. > > As for security.. always a crapshoot. > Perhaps you gain a little security through obscurity not using Apache. Depending on what you need the web server to do, here's a few more options: 1. lighttpd http://www.lighttpd.net/ 2. uhttpd https://dev.openwrt.org/browser/trunk/package/uhttpd?rev=20573 3. publicfile http://cr.yp.to/publicfile.html lighttpd is the most advanced of the three, but it has fewer bells and whistles than apache. uhttpd is part of OpenWrt and is designed to run on systems with few resources. As such, it is single-threaded so you can't overwhelm the resources of the host. This may or may not be desirable for you. publicfile is quite secure, but it doesn't do much. It also uses "the djb way" of thinking, so it's a bit different. Not bad, but different. What are you looking to do with the web server? Just serve up static files or something more dynamic? Best Regards, Mark Deneen Saucon Technologies From steve at fl-eng.com Wed Sep 15 08:38:25 2010 From: steve at fl-eng.com (Steve Spano) Date: Wed, 15 Sep 2010 09:38:25 -0400 Subject: ### DM6446 DVR Message-ID: <002e01cb54db$46564120$d302c360$@fl-eng.com> Hi Folks, Was wondering about a DVR application for the DM6446. We basically want to encode MPEG4 to a USB stick, then playback from it. Seems very similar to the encode/decode demo - except that we put the USB stick in the middle. Has anyone done this and/or is there any reference app that I could review for something similar to this? Thanks Steve -------------- next part -------------- An HTML attachment was scrubbed... URL: From ottavio.campana at dei.unipd.it Wed Sep 15 09:03:41 2010 From: ottavio.campana at dei.unipd.it (Ottavio Campana) Date: Wed, 15 Sep 2010 16:03:41 +0200 Subject: Prefered web server fo Davinci In-Reply-To: <1284557718.16883.11.camel@mdeneen.sdc.saucontech.com> References: <70E876B0EA86DD4BAF101844BC814DFE0903E89713@Cloud.RL.local> <1284557718.16883.11.camel@mdeneen.sdc.saucontech.com> Message-ID: <20100915140340.GA9279@dei.unipd.it> On Wed, Sep 15, 2010 at 09:35:18AM -0400, Mark Deneen wrote: > On Wed, 2010-09-15 at 03:06 +0100, Jon Povey wrote: > > davinci-linux-open-source-bounces at linux.davincidsp.com wrote: > > > Could someone please tell me if there is a better, smaller, > > > easier to cross compile, and secure web server that you would > > > recommend? > > > > http://www.acme.com/software/thttpd/ looks promising at a glance. > > I haven't tried it, but it's small and uses GNU configure so may > > not be painful to cross-compile. > > > > I'd be interested to know your results - I may need to do something > > similar soon. > > > > As for security.. always a crapshoot. > > Perhaps you gain a little security through obscurity not using Apache. > > > Depending on what you need the web server to do, here's a few more > options: > > 1. lighttpd http://www.lighttpd.net/ > 2. uhttpd https://dev.openwrt.org/browser/trunk/package/uhttpd?rev=20573 > 3. publicfile http://cr.yp.to/publicfile.html > > lighttpd is the most advanced of the three, but it has fewer bells and > whistles than apache. if the task is just serving a few pages also busybox comes with a minimal webserver. You can do cgi with it, but you need to write shell scripts. Ottavio From cyril at ti.com Wed Sep 15 09:11:21 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Wed, 15 Sep 2010 10:11:21 -0400 Subject: [PATCH v4 01/10] net: davinci_emac: separate out davinci mdio In-Reply-To: <1284559890-31346-1-git-send-email-cyril@ti.com> References: <1284559890-31346-1-git-send-email-cyril@ti.com> Message-ID: <1284559890-31346-2-git-send-email-cyril@ti.com> Davinci's MDIO controller is present on other TI devices, without an accompanying EMAC. For example, on tnetv107x, the same MDIO module is used in conjunction with a 3-port switch hardware. By separating the MDIO controller code into its own platform driver, this patch allows common logic to be reused on such platforms. Signed-off-by: Cyril Chemparathy Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- drivers/net/Kconfig | 10 + drivers/net/Makefile | 1 + drivers/net/davinci_mdio.c | 475 ++++++++++++++++++++++++++++++++++++++++++ include/linux/davinci_emac.h | 4 + 4 files changed, 490 insertions(+), 0 deletions(-) create mode 100644 drivers/net/davinci_mdio.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2cc81a5..c5c86e0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -958,6 +958,16 @@ config TI_DAVINCI_EMAC To compile this driver as a module, choose M here: the module will be called davinci_emac_driver. This is recommended. +config TI_DAVINCI_MDIO + tristate "TI DaVinci MDIO Support" + depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + select PHYLIB + help + This driver supports TI's DaVinci MDIO module. + + To compile this driver as a module, choose M here: the module + will be called davinci_mdio. This is recommended. + config DM9000 tristate "DM9000 support" depends on ARM || BLACKFIN || MIPS diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 3e8f150..d38a7ab 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_MDIO) += mdio.o obj-$(CONFIG_PHYLIB) += phy/ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o +obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_E1000E) += e1000e/ diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c new file mode 100644 index 0000000..7615040 --- /dev/null +++ b/drivers/net/davinci_mdio.c @@ -0,0 +1,475 @@ +/* + * DaVinci MDIO Module driver + * + * Copyright (C) 2010 Texas Instruments. + * + * Shamelessly ripped out of davinci_emac.c, original copyrights follow: + * + * Copyright (C) 2009 Texas Instruments. + * + * --------------------------------------------------------------------------- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * --------------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This timeout definition is a worst-case ultra defensive measure against + * unexpected controller lock ups. Ideally, we should never ever hit this + * scenario in practice. + */ +#define MDIO_TIMEOUT 100 /* msecs */ + +#define PHY_REG_MASK 0x1f +#define PHY_ID_MASK 0x1f + +#define DEF_OUT_FREQ 2200000 /* 2.2 MHz */ + +struct davinci_mdio_regs { + u32 version; + u32 control; +#define CONTROL_IDLE BIT(31) +#define CONTROL_ENABLE BIT(30) +#define CONTROL_MAX_DIV (0xff) + + u32 alive; + u32 link; + u32 linkintraw; + u32 linkintmasked; + u32 __reserved_0[2]; + u32 userintraw; + u32 userintmasked; + u32 userintmaskset; + u32 userintmaskclr; + u32 __reserved_1[20]; + + struct { + u32 access; +#define USERACCESS_GO BIT(31) +#define USERACCESS_WRITE BIT(30) +#define USERACCESS_ACK BIT(29) +#define USERACCESS_READ (0) +#define USERACCESS_DATA (0xffff) + + u32 physel; + } user[0]; +}; + +struct mdio_platform_data default_pdata = { + .bus_freq = DEF_OUT_FREQ, +}; + +struct davinci_mdio_data { + struct mdio_platform_data pdata; + struct davinci_mdio_regs __iomem *regs; + spinlock_t lock; + struct clk *clk; + struct device *dev; + struct mii_bus *bus; + bool suspended; + unsigned long access_time; /* jiffies */ +}; + +static void __davinci_mdio_reset(struct davinci_mdio_data *data) +{ + u32 mdio_in, div, mdio_out_khz, access_time; + + mdio_in = clk_get_rate(data->clk); + div = (mdio_in / data->pdata.bus_freq) - 1; + if (div > CONTROL_MAX_DIV) + div = CONTROL_MAX_DIV; + + /* set enable and clock divider */ + __raw_writel(div | CONTROL_ENABLE, &data->regs->control); + + /* + * One mdio transaction consists of: + * 32 bits of preamble + * 32 bits of transferred data + * 24 bits of bus yield (not needed unless shared?) + */ + mdio_out_khz = mdio_in / (1000 * (div + 1)); + access_time = (88 * 1000) / mdio_out_khz; + + /* + * In the worst case, we could be kicking off a user-access immediately + * after the mdio bus scan state-machine triggered its own read. If + * so, our request could get deferred by one access cycle. We + * defensively allow for 4 access cycles. + */ + data->access_time = usecs_to_jiffies(access_time * 4); + if (!data->access_time) + data->access_time = 1; +} + +static int davinci_mdio_reset(struct mii_bus *bus) +{ + struct davinci_mdio_data *data = bus->priv; + u32 phy_mask, ver; + + __davinci_mdio_reset(data); + + /* wait for scan logic to settle */ + msleep(PHY_MAX_ADDR * data->access_time); + + /* dump hardware version info */ + ver = __raw_readl(&data->regs->version); + dev_info(data->dev, "davinci mdio revision %d.%d\n", + (ver >> 8) & 0xff, ver & 0xff); + + /* get phy mask from the alive register */ + phy_mask = __raw_readl(&data->regs->alive); + if (phy_mask) { + /* restrict mdio bus to live phys only */ + dev_info(data->dev, "detected phy mask %x\n", ~phy_mask); + phy_mask = ~phy_mask; + } else { + /* desperately scan all phys */ + dev_warn(data->dev, "no live phy, scanning all\n"); + phy_mask = 0; + } + data->bus->phy_mask = phy_mask; + + return 0; +} + +/* wait until hardware is ready for another user access */ +static inline int wait_for_user_access(struct davinci_mdio_data *data) +{ + struct davinci_mdio_regs __iomem *regs = data->regs; + unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT); + u32 reg; + + while (time_after(timeout, jiffies)) { + reg = __raw_readl(®s->user[0].access); + if ((reg & USERACCESS_GO) == 0) + return 0; + + reg = __raw_readl(®s->control); + if ((reg & CONTROL_IDLE) == 0) + continue; + + /* + * An emac soft_reset may have clobbered the mdio controller's + * state machine. We need to reset and retry the current + * operation + */ + dev_warn(data->dev, "resetting idled controller\n"); + __davinci_mdio_reset(data); + return -EAGAIN; + } + dev_err(data->dev, "timed out waiting for user access\n"); + return -ETIMEDOUT; +} + +/* wait until hardware state machine is idle */ +static inline int wait_for_idle(struct davinci_mdio_data *data) +{ + struct davinci_mdio_regs __iomem *regs = data->regs; + unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT); + + while (time_after(timeout, jiffies)) { + if (__raw_readl(®s->control) & CONTROL_IDLE) + return 0; + } + dev_err(data->dev, "timed out waiting for idle\n"); + return -ETIMEDOUT; +} + +static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg) +{ + struct davinci_mdio_data *data = bus->priv; + u32 reg; + int ret; + + if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) + return -EINVAL; + + spin_lock(&data->lock); + + if (data->suspended) { + spin_unlock(&data->lock); + return -ENODEV; + } + + reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) | + (phy_id << 16)); + + while (1) { + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + if (ret < 0) + break; + + __raw_writel(reg, &data->regs->user[0].access); + + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + if (ret < 0) + break; + + reg = __raw_readl(&data->regs->user[0].access); + ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO; + break; + } + + spin_unlock(&data->lock); + + return ret; +} + +static int davinci_mdio_write(struct mii_bus *bus, int phy_id, + int phy_reg, u16 phy_data) +{ + struct davinci_mdio_data *data = bus->priv; + u32 reg; + int ret; + + if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK) + return -EINVAL; + + spin_lock(&data->lock); + + if (data->suspended) { + spin_unlock(&data->lock); + return -ENODEV; + } + + reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) | + (phy_id << 16) | (phy_data & USERACCESS_DATA)); + + while (1) { + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + if (ret < 0) + break; + + __raw_writel(reg, &data->regs->user[0].access); + + ret = wait_for_user_access(data); + if (ret == -EAGAIN) + continue; + break; + } + + spin_unlock(&data->lock); + + return 0; +} + +static int __devinit davinci_mdio_probe(struct platform_device *pdev) +{ + struct mdio_platform_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct davinci_mdio_data *data; + struct resource *res; + struct phy_device *phy; + int ret, addr; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + dev_err(dev, "failed to alloc device data\n"); + return -ENOMEM; + } + + data->pdata = pdata ? (*pdata) : default_pdata; + + data->bus = mdiobus_alloc(); + if (!data->bus) { + dev_err(dev, "failed to alloc mii bus\n"); + ret = -ENOMEM; + goto bail_out; + } + + data->bus->name = dev_name(dev); + data->bus->read = davinci_mdio_read, + data->bus->write = davinci_mdio_write, + data->bus->reset = davinci_mdio_reset, + data->bus->parent = dev; + data->bus->priv = data; + snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); + + data->clk = clk_get(dev, NULL); + if (IS_ERR(data->clk)) { + data->clk = NULL; + dev_err(dev, "failed to get device clock\n"); + ret = PTR_ERR(data->clk); + goto bail_out; + } + + clk_enable(data->clk); + + dev_set_drvdata(dev, data); + data->dev = dev; + spin_lock_init(&data->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "could not find register map resource\n"); + ret = -ENOENT; + goto bail_out; + } + + res = devm_request_mem_region(dev, res->start, resource_size(res), + dev_name(dev)); + if (!res) { + dev_err(dev, "could not allocate register map resource\n"); + ret = -ENXIO; + goto bail_out; + } + + data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); + if (!data->regs) { + dev_err(dev, "could not map mdio registers\n"); + ret = -ENOMEM; + goto bail_out; + } + + /* register the mii bus */ + ret = mdiobus_register(data->bus); + if (ret) + goto bail_out; + + /* scan and dump the bus */ + for (addr = 0; addr < PHY_MAX_ADDR; addr++) { + phy = data->bus->phy_map[addr]; + if (phy) { + dev_info(dev, "phy[%d]: device %s, driver %s\n", + phy->addr, dev_name(&phy->dev), + phy->drv ? phy->drv->name : "unknown"); + } + } + + return 0; + +bail_out: + if (data->bus) + mdiobus_free(data->bus); + + if (data->clk) { + clk_disable(data->clk); + clk_put(data->clk); + } + + kfree(data); + + return ret; +} + +static int __devexit davinci_mdio_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct davinci_mdio_data *data = dev_get_drvdata(dev); + + if (data->bus) + mdiobus_free(data->bus); + + if (data->clk) { + clk_disable(data->clk); + clk_put(data->clk); + } + + dev_set_drvdata(dev, NULL); + + kfree(data); + + return 0; +} + +static int davinci_mdio_suspend(struct device *dev) +{ + struct davinci_mdio_data *data = dev_get_drvdata(dev); + u32 ctrl; + + spin_lock(&data->lock); + + /* shutdown the scan state machine */ + ctrl = __raw_readl(&data->regs->control); + ctrl &= ~CONTROL_ENABLE; + __raw_writel(ctrl, &data->regs->control); + wait_for_idle(data); + + if (data->clk) + clk_disable(data->clk); + + data->suspended = true; + spin_unlock(&data->lock); + + return 0; +} + +static int davinci_mdio_resume(struct device *dev) +{ + struct davinci_mdio_data *data = dev_get_drvdata(dev); + u32 ctrl; + + spin_lock(&data->lock); + if (data->clk) + clk_enable(data->clk); + + /* restart the scan state machine */ + ctrl = __raw_readl(&data->regs->control); + ctrl |= CONTROL_ENABLE; + __raw_writel(ctrl, &data->regs->control); + + data->suspended = false; + spin_unlock(&data->lock); + + return 0; +} + +static const struct dev_pm_ops davinci_mdio_pm_ops = { + .suspend = davinci_mdio_suspend, + .resume = davinci_mdio_resume, +}; + +static struct platform_driver davinci_mdio_driver = { + .driver = { + .name = "davinci_mdio", + .owner = THIS_MODULE, + .pm = &davinci_mdio_pm_ops, + }, + .probe = davinci_mdio_probe, + .remove = __devexit_p(davinci_mdio_remove), +}; + +static int __init davinci_mdio_init(void) +{ + return platform_driver_register(&davinci_mdio_driver); +} +device_initcall(davinci_mdio_init); + +static void __exit davinci_mdio_exit(void) +{ + platform_driver_unregister(&davinci_mdio_driver); +} +module_exit(davinci_mdio_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("DaVinci MDIO driver"); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index 7c930db..a04fd8c 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -14,6 +14,10 @@ #include #include +struct mdio_platform_data { + unsigned long bus_freq; +}; + struct emac_platform_data { char mac_addr[ETH_ALEN]; u32 ctrl_reg_offset; -- 1.7.0.4 From cyril at ti.com Wed Sep 15 09:11:20 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Wed, 15 Sep 2010 10:11:20 -0400 Subject: [PATCH v4 00/10] split out emac cpdma and mdio for reuse Message-ID: <1284559890-31346-1-git-send-email-cyril@ti.com> Davinci's EMAC device has an in-built MDIO controller and a CPDMA engine. These hardware modules are not restricted to EMAC device alone. For example, CPSW3G (3-port gigabit ethernet switch) hardware uses these very same modules internally. This patch series separates out EMAC's MDIO and CPDMA functionality, allowing these individual pieces to be reused across TI hardware. This patch series has been broadly organized as follows: MDIO: - Add new functionality netdev: separate out davinci mdio controller code - Hookup new functionality davinci: add mdio platform devices omap: add mdio platform devices netdev: switch davinci emac to new mdio driver - Cleanup left over cruft davinci: cleanup unused davinci mdio arch code omap: cleanup unused davinci mdio arch code netdev: cleanup unused davinci mdio emac code CPDMA: - Add new functionality netdev: separate out davinci cpdma controller code - Hookup new functionality netdev: switch davinci emac to new cpdma layer - Cleanup left over cruft netdev: cleanup unused davinci emac cpdma code This series has been tested on dm365 and tnetv107x (with additional cpsw patches) hardware. Although am3517 (omap) board support code has been updated as needed, emac does not work on this platform. Changes from v1: 1. Fixed memory leak in cpdma_chan_create() failure case 2. Included new omap patches for am3517, avoids build breakage Changes from v2: 1. Updated series to include mityomapl138 board 2. Minor white-space fixes Changes from v3 (rolled in "post cpdma/mdio refactoring fixes" series): 1. allow forced 100/full mode instead of phy auto-detect 2. specify phy_id on boards that had a phy_mask defined earlier 3. requeue cpdma descriptors when EOQ at submit 4. use calculated mdio bus access times instead of hardcoded delays 5. work around emac soft-reset impact on mdio controller state 6. extend register dumps to include cpdma registers 7. updated sign offs and acks Cyril Chemparathy (10): net: davinci_emac: separate out davinci mdio davinci: add mdio platform devices omap: add mdio platform devices net: davinci_emac: switch to new mdio davinci: cleanup mdio arch code and switch to phy_id omap: cleanup unused davinci mdio arch code net: davinci_emac: cleanup unused mdio emac code net: davinci_emac: separate out cpdma code net: davinci_emac: switch to new cpdma layer net: davinci_emac: cleanup unused cpdma code arch/arm/mach-davinci/board-da830-evm.c | 7 +- arch/arm/mach-davinci/board-da850-evm.c | 7 +- arch/arm/mach-davinci/board-dm365-evm.c | 7 +- arch/arm/mach-davinci/board-dm644x-evm.c | 8 +- arch/arm/mach-davinci/board-dm646x-evm.c | 7 +- arch/arm/mach-davinci/board-mityomapl138.c | 8 +- arch/arm/mach-davinci/board-neuros-osd2.c | 7 +- arch/arm/mach-davinci/board-sffsdr.c | 7 +- arch/arm/mach-davinci/devices-da8xx.c | 31 +- arch/arm/mach-davinci/dm365.c | 23 +- arch/arm/mach-davinci/dm644x.c | 23 +- arch/arm/mach-davinci/dm646x.c | 22 +- arch/arm/mach-davinci/include/mach/dm365.h | 2 +- arch/arm/mach-davinci/include/mach/dm644x.h | 2 +- arch/arm/mach-davinci/include/mach/dm646x.h | 2 +- arch/arm/mach-omap2/board-am3517evm.c | 31 +- drivers/net/Kconfig | 21 + drivers/net/Makefile | 2 + drivers/net/davinci_cpdma.c | 965 +++++++++++++++++++ drivers/net/davinci_cpdma.h | 108 +++ drivers/net/davinci_emac.c | 1338 ++++----------------------- drivers/net/davinci_mdio.c | 475 ++++++++++ include/linux/davinci_emac.h | 16 +- 23 files changed, 1894 insertions(+), 1225 deletions(-) create mode 100644 drivers/net/davinci_cpdma.c create mode 100644 drivers/net/davinci_cpdma.h create mode 100644 drivers/net/davinci_mdio.c From cyril at ti.com Wed Sep 15 09:11:23 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Wed, 15 Sep 2010 10:11:23 -0400 Subject: [PATCH v4 03/10] omap: add mdio platform devices In-Reply-To: <1284559890-31346-1-git-send-email-cyril@ti.com> References: <1284559890-31346-1-git-send-email-cyril@ti.com> Message-ID: <1284559890-31346-4-git-send-email-cyril@ti.com> This patch adds mdio platform devices on SoCs that have the necessary hardware. Clock lookup entries (aliases) have also been added, so that the MDIO and EMAC drivers can independently enable/disable a shared underlying clock. Further, the EMAC MMR region has been split down into separate MDIO and EMAC regions. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller Acked-by: Tony Lindgren --- arch/arm/mach-omap2/board-am3517evm.c | 27 ++++++++++++++++++++++++++- 1 files changed, 26 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 4d0f585..5dd1b73 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,27 @@ #define AM35XX_EVM_PHY_MASK (0xF) #define AM35XX_EVM_MDIO_FREQUENCY (1000000) +static struct mdio_platform_data am3517_evm_mdio_pdata = { + .bus_freq = AM35XX_EVM_MDIO_FREQUENCY, +}; + +static struct resource am3517_mdio_resources[] = { + { + .start = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET, + .end = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET + + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device am3517_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(am3517_mdio_resources), + .resource = am3517_mdio_resources, + .dev.platform_data = &am3517_evm_mdio_pdata, +}; + static struct emac_platform_data am3517_evm_emac_pdata = { .phy_mask = AM35XX_EVM_PHY_MASK, .mdio_max_freq = AM35XX_EVM_MDIO_FREQUENCY, @@ -50,7 +72,7 @@ static struct emac_platform_data am3517_evm_emac_pdata = { static struct resource am3517_emac_resources[] = { { .start = AM35XX_IPSS_EMAC_BASE, - .end = AM35XX_IPSS_EMAC_BASE + 0x3FFFF, + .end = AM35XX_IPSS_EMAC_BASE + 0x2FFFF, .flags = IORESOURCE_MEM, }, { @@ -121,6 +143,9 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata) pdata->interrupt_disable = am3517_disable_ethernet_int; am3517_emac_device.dev.platform_data = pdata; platform_device_register(&am3517_emac_device); + platform_device_register(&am3517_mdio_device); + clk_add_alias(NULL, dev_name(&am3517_mdio_device.dev), + NULL, &am3517_emac_device.dev); regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); regval = regval & (~(AM35XX_CPGMACSS_SW_RST)); -- 1.7.0.4 From cyril at ti.com Wed Sep 15 09:11:24 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Wed, 15 Sep 2010 10:11:24 -0400 Subject: [PATCH v4 04/10] net: davinci_emac: switch to new mdio In-Reply-To: <1284559890-31346-1-git-send-email-cyril@ti.com> References: <1284559890-31346-1-git-send-email-cyril@ti.com> Message-ID: <1284559890-31346-5-git-send-email-cyril@ti.com> This patch switches the emac implementation over to the newly separated MDIO driver. With this, the mdio bus frequency defaults to a safe 2.2MHz. Boards may optionally specify a bus frequency via platform data. The phy identification scheme has been modified to use a phy bus id instead of a mask. This largely serves to eliminate the "phy search" code in emac init. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- drivers/net/Kconfig | 1 + drivers/net/davinci_emac.c | 88 ++++++++++++++--------------------------- include/linux/davinci_emac.h | 9 ++++ 3 files changed, 40 insertions(+), 58 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index c5c86e0..911e7f1 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -951,6 +951,7 @@ config NET_NETX config TI_DAVINCI_EMAC tristate "TI DaVinci EMAC Support" depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + select TI_DAVINCI_MDIO select PHYLIB help This driver supports TI's DaVinci Ethernet . diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 7fbd052..997f599 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -500,6 +500,7 @@ struct emac_priv { u32 phy_mask; /* mii_bus,phy members */ struct mii_bus *mii_bus; + const char *phy_id; struct phy_device *phydev; spinlock_t lock; /*platform specific members*/ @@ -686,7 +687,7 @@ static int emac_get_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) { struct emac_priv *priv = netdev_priv(ndev); - if (priv->phy_mask) + if (priv->phydev) return phy_ethtool_gset(priv->phydev, ecmd); else return -EOPNOTSUPP; @@ -704,7 +705,7 @@ static int emac_get_settings(struct net_device *ndev, static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd) { struct emac_priv *priv = netdev_priv(ndev); - if (priv->phy_mask) + if (priv->phydev) return phy_ethtool_sset(priv->phydev, ecmd); else return -EOPNOTSUPP; @@ -841,7 +842,7 @@ static void emac_update_phystatus(struct emac_priv *priv) mac_control = emac_read(EMAC_MACCONTROL); cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ? DUPLEX_FULL : DUPLEX_HALF; - if (priv->phy_mask) + if (priv->phydev) new_duplex = priv->phydev->duplex; else new_duplex = DUPLEX_FULL; @@ -2485,6 +2486,11 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) return -EOPNOTSUPP; } +static int match_first_device(struct device *dev, void *data) +{ + return 1; +} + /** * emac_dev_open: EMAC device open * @ndev: The DaVinci EMAC network adapter @@ -2499,7 +2505,6 @@ static int emac_dev_open(struct net_device *ndev) { struct device *emac_dev = &ndev->dev; u32 rc, cnt, ch; - int phy_addr; struct resource *res; int q, m; int i = 0; @@ -2560,28 +2565,26 @@ static int emac_dev_open(struct net_device *ndev) emac_set_coalesce(ndev, &coal); } - /* find the first phy */ priv->phydev = NULL; - if (priv->phy_mask) { - emac_mii_reset(priv->mii_bus); - for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { - if (priv->mii_bus->phy_map[phy_addr]) { - priv->phydev = priv->mii_bus->phy_map[phy_addr]; - break; - } - } + /* use the first phy on the bus if pdata did not give us a phy id */ + if (!priv->phy_id) { + struct device *phy; - if (!priv->phydev) { - printk(KERN_ERR "%s: no PHY found\n", ndev->name); - return -1; - } + phy = bus_find_device(&mdio_bus_type, NULL, NULL, + match_first_device); + if (phy) + priv->phy_id = dev_name(phy); + } - priv->phydev = phy_connect(ndev, dev_name(&priv->phydev->dev), - &emac_adjust_link, 0, PHY_INTERFACE_MODE_MII); + if (priv->phy_id && *priv->phy_id) { + priv->phydev = phy_connect(ndev, priv->phy_id, + &emac_adjust_link, 0, + PHY_INTERFACE_MODE_MII); if (IS_ERR(priv->phydev)) { - printk(KERN_ERR "%s: Could not attach to PHY\n", - ndev->name); + dev_err(emac_dev, "could not connect to phy %s\n", + priv->phy_id); + priv->phydev = NULL; return PTR_ERR(priv->phydev); } @@ -2589,12 +2592,13 @@ static int emac_dev_open(struct net_device *ndev) priv->speed = 0; priv->duplex = ~0; - printk(KERN_INFO "%s: attached PHY driver [%s] " - "(mii_bus:phy_addr=%s, id=%x)\n", ndev->name, + dev_info(emac_dev, "attached PHY driver [%s] " + "(mii_bus:phy_addr=%s, id=%x)\n", priv->phydev->drv->name, dev_name(&priv->phydev->dev), priv->phydev->phy_id); - } else{ + } else { /* No PHY , fix the link, speed and duplex settings */ + dev_notice(emac_dev, "no phy, defaulting to 100/full\n"); priv->link = 1; priv->speed = SPEED_100; priv->duplex = DUPLEX_FULL; @@ -2607,7 +2611,7 @@ static int emac_dev_open(struct net_device *ndev) if (netif_msg_drv(priv)) dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name); - if (priv->phy_mask) + if (priv->phydev) phy_start(priv->phydev); return 0; @@ -2794,7 +2798,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) /* MAC addr and PHY mask , RMII enable info from platform_data */ memcpy(priv->mac_addr, pdata->mac_addr, 6); - priv->phy_mask = pdata->phy_mask; + priv->phy_id = pdata->phy_id; priv->rmii_en = pdata->rmii_en; priv->version = pdata->version; priv->int_enable = pdata->interrupt_enable; @@ -2871,32 +2875,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) } - /* MII/Phy intialisation, mdio bus registration */ - emac_mii = mdiobus_alloc(); - if (emac_mii == NULL) { - dev_err(emac_dev, "DaVinci EMAC: Error allocating mii_bus\n"); - rc = -ENOMEM; - goto mdio_alloc_err; - } - - priv->mii_bus = emac_mii; - emac_mii->name = "emac-mii", - emac_mii->read = emac_mii_read, - emac_mii->write = emac_mii_write, - emac_mii->reset = emac_mii_reset, - emac_mii->irq = mii_irqs, - emac_mii->phy_mask = ~(priv->phy_mask); - emac_mii->parent = &pdev->dev; - emac_mii->priv = priv->remap_addr + pdata->mdio_reg_offset; - snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", priv->pdev->id); - mdio_max_freq = pdata->mdio_max_freq; - emac_mii->reset(emac_mii); - - /* Register the MII bus */ - rc = mdiobus_register(emac_mii); - if (rc) - goto mdiobus_quit; - if (netif_msg_probe(priv)) { dev_notice(emac_dev, "DaVinci EMAC Probe found device "\ "(regs: %p, irq: %d)\n", @@ -2904,11 +2882,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) } return 0; -mdiobus_quit: - mdiobus_free(emac_mii); - netdev_reg_err: -mdio_alloc_err: clk_disable(emac_clk); no_irq_res: res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -2938,8 +2912,6 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mdiobus_unregister(priv->mii_bus); - mdiobus_free(priv->mii_bus); release_mem_region(res->start, res->end - res->start + 1); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index a04fd8c..46a759f 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -28,6 +28,15 @@ struct emac_platform_data { u32 ctrl_ram_size; u32 phy_mask; u32 mdio_max_freq; + + /* + * phy_id can be one of the following: + * - NULL : use the first phy on the bus, + * - "" : force to 100/full, no mdio control + * - ":" : use the specified bus and phy + */ + const char *phy_id; + u8 rmii_en; u8 version; void (*interrupt_enable) (void); -- 1.7.0.4 From cyril at ti.com Wed Sep 15 09:11:27 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Wed, 15 Sep 2010 10:11:27 -0400 Subject: [PATCH v4 07/10] net: davinci_emac: cleanup unused mdio emac code In-Reply-To: <1284559890-31346-1-git-send-email-cyril@ti.com> References: <1284559890-31346-1-git-send-email-cyril@ti.com> Message-ID: <1284559890-31346-8-git-send-email-cyril@ti.com> This patch removes code that has been rendered useless by the previous patches in this series. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- drivers/net/davinci_emac.c | 107 ------------------------------------------ include/linux/davinci_emac.h | 3 - 2 files changed, 0 insertions(+), 110 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 997f599..d4298cb 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -113,7 +113,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_FRAME_SIZE (1500 + 14 + 4 + 4) #define EMAC_DEF_TX_CH (0) /* Default 0th channel */ #define EMAC_DEF_RX_CH (0) /* Default 0th channel */ -#define EMAC_DEF_MDIO_TICK_MS (10) /* typically 1 tick=1 ms) */ #define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */ #define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */ #define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */ @@ -303,25 +302,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DM644X_INTMIN_INTVL 0x1 #define EMAC_DM644X_INTMAX_INTVL (EMAC_DM644X_EWINTCNT_MASK) -/* EMAC MDIO related */ -/* Mask & Control defines */ -#define MDIO_CONTROL_CLKDIV (0xFF) -#define MDIO_CONTROL_ENABLE BIT(30) -#define MDIO_USERACCESS_GO BIT(31) -#define MDIO_USERACCESS_WRITE BIT(30) -#define MDIO_USERACCESS_READ (0) -#define MDIO_USERACCESS_REGADR (0x1F << 21) -#define MDIO_USERACCESS_PHYADR (0x1F << 16) -#define MDIO_USERACCESS_DATA (0xFFFF) -#define MDIO_USERPHYSEL_LINKSEL BIT(7) -#define MDIO_VER_MODID (0xFFFF << 16) -#define MDIO_VER_REVMAJ (0xFF << 8) -#define MDIO_VER_REVMIN (0xFF) - -#define MDIO_USERACCESS(inst) (0x80 + (inst * 8)) -#define MDIO_USERPHYSEL(inst) (0x84 + (inst * 8)) -#define MDIO_CONTROL (0x04) - /* EMAC DM646X control module registers */ #define EMAC_DM646X_CMINTCTRL 0x0C #define EMAC_DM646X_CMRXINTEN 0x14 @@ -493,13 +473,6 @@ struct emac_priv { u32 mac_hash2; u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS]; u32 rx_addr_type; - /* periodic timer required for MDIO polling */ - struct timer_list periodic_timer; - u32 periodic_ticks; - u32 timer_active; - u32 phy_mask; - /* mii_bus,phy members */ - struct mii_bus *mii_bus; const char *phy_id; struct phy_device *phydev; spinlock_t lock; @@ -511,7 +484,6 @@ struct emac_priv { /* clock frequency for EMAC */ static struct clk *emac_clk; static unsigned long emac_bus_frequency; -static unsigned long mdio_max_freq; #define emac_virt_to_phys(addr, priv) \ (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \ @@ -549,9 +521,6 @@ static char *emac_rxhost_errcodes[16] = { #define emac_ctrl_read(reg) ioread32((priv->ctrl_base + (reg))) #define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg))) -#define emac_mdio_read(reg) ioread32(bus->priv + (reg)) -#define emac_mdio_write(reg, val) iowrite32(val, (bus->priv + (reg))) - /** * emac_dump_regs: Dump important EMAC registers to debug terminal * @priv: The DaVinci EMAC private adapter structure @@ -657,9 +626,6 @@ static void emac_dump_regs(struct emac_priv *priv) emac_read(EMAC_RXDMAOVERRUNS)); } -/************************************************************************* - * EMAC MDIO/Phy Functionality - *************************************************************************/ /** * emac_get_drvinfo: Get EMAC driver information * @ndev: The DaVinci EMAC network adapter @@ -2349,79 +2315,6 @@ void emac_poll_controller(struct net_device *ndev) } #endif -/* PHY/MII bus related */ - -/* Wait until mdio is ready for next command */ -#define MDIO_WAIT_FOR_USER_ACCESS\ - while ((emac_mdio_read((MDIO_USERACCESS(0))) &\ - MDIO_USERACCESS_GO) != 0) - -static int emac_mii_read(struct mii_bus *bus, int phy_id, int phy_reg) -{ - unsigned int phy_data = 0; - unsigned int phy_control; - - /* Wait until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - phy_control = (MDIO_USERACCESS_GO | - MDIO_USERACCESS_READ | - ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | - ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | - (phy_data & MDIO_USERACCESS_DATA)); - emac_mdio_write(MDIO_USERACCESS(0), phy_control); - - /* Wait until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - return emac_mdio_read(MDIO_USERACCESS(0)) & MDIO_USERACCESS_DATA; - -} - -static int emac_mii_write(struct mii_bus *bus, int phy_id, - int phy_reg, u16 phy_data) -{ - - unsigned int control; - - /* until mdio is ready for next command */ - MDIO_WAIT_FOR_USER_ACCESS; - - control = (MDIO_USERACCESS_GO | - MDIO_USERACCESS_WRITE | - ((phy_reg << 21) & MDIO_USERACCESS_REGADR) | - ((phy_id << 16) & MDIO_USERACCESS_PHYADR) | - (phy_data & MDIO_USERACCESS_DATA)); - emac_mdio_write(MDIO_USERACCESS(0), control); - - return 0; -} - -static int emac_mii_reset(struct mii_bus *bus) -{ - unsigned int clk_div; - int mdio_bus_freq = emac_bus_frequency; - - if (mdio_max_freq && mdio_bus_freq) - clk_div = ((mdio_bus_freq / mdio_max_freq) - 1); - else - clk_div = 0xFF; - - clk_div &= MDIO_CONTROL_CLKDIV; - - /* Set enable and clock divider in MDIOControl */ - emac_mdio_write(MDIO_CONTROL, (clk_div | MDIO_CONTROL_ENABLE)); - - return 0; - -} - -static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, PHY_POLL }; - -/* emac_driver: EMAC MII bus structure */ - -static struct mii_bus *emac_mii; - static void emac_adjust_link(struct net_device *ndev) { struct emac_priv *priv = netdev_priv(ndev); diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h index 46a759f..5dd4285 100644 --- a/include/linux/davinci_emac.h +++ b/include/linux/davinci_emac.h @@ -24,10 +24,7 @@ struct emac_platform_data { u32 ctrl_mod_reg_offset; u32 ctrl_ram_offset; u32 hw_ram_addr; - u32 mdio_reg_offset; u32 ctrl_ram_size; - u32 phy_mask; - u32 mdio_max_freq; /* * phy_id can be one of the following: -- 1.7.0.4 From cyril at ti.com Wed Sep 15 09:11:25 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Wed, 15 Sep 2010 10:11:25 -0400 Subject: [PATCH v4 05/10] davinci: cleanup mdio arch code and switch to phy_id In-Reply-To: <1284559890-31346-1-git-send-email-cyril@ti.com> References: <1284559890-31346-1-git-send-email-cyril@ti.com> Message-ID: <1284559890-31346-6-git-send-email-cyril@ti.com> This patch removes davinci architecture code that has now been rendered useless by the previous patches in the MDIO separation series. In addition, the earlier phy_mask definitions have been replaced with corresponding phy_id definitions. Signed-off-by: Cyril Chemparathy Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- arch/arm/mach-davinci/board-da830-evm.c | 7 ++----- arch/arm/mach-davinci/board-da850-evm.c | 7 ++----- arch/arm/mach-davinci/board-dm365-evm.c | 7 ++----- arch/arm/mach-davinci/board-dm644x-evm.c | 8 ++------ arch/arm/mach-davinci/board-dm646x-evm.c | 7 ++----- arch/arm/mach-davinci/board-mityomapl138.c | 8 ++------ arch/arm/mach-davinci/board-neuros-osd2.c | 7 ++----- arch/arm/mach-davinci/board-sffsdr.c | 7 ++----- arch/arm/mach-davinci/devices-da8xx.c | 2 -- arch/arm/mach-davinci/dm365.c | 1 - arch/arm/mach-davinci/dm644x.c | 1 - arch/arm/mach-davinci/dm646x.c | 1 - arch/arm/mach-davinci/include/mach/dm365.h | 1 - arch/arm/mach-davinci/include/mach/dm644x.h | 1 - arch/arm/mach-davinci/include/mach/dm646x.h | 1 - 15 files changed, 16 insertions(+), 50 deletions(-) diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index ef1ab0b..1bb89d3 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -31,9 +31,7 @@ #include #include -#define DA830_EVM_PHY_MASK 0x0 -#define DA830_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ - +#define DA830_EVM_PHY_ID "" /* * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4]. */ @@ -558,9 +556,8 @@ static __init void da830_evm_init(void) da830_evm_usb_init(); - soc_info->emac_pdata->phy_mask = DA830_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DA830_EVM_MDIO_FREQUENCY; soc_info->emac_pdata->rmii_en = 1; + soc_info->emac_pdata->phy_id = DA830_EVM_PHY_ID; ret = davinci_cfg_reg_list(da830_cpgmac_pins); if (ret) diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index ac2297c..5e435b0 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -38,9 +38,7 @@ #include #include -#define DA850_EVM_PHY_MASK 0x1 -#define DA850_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ - +#define DA850_EVM_PHY_ID "0:00" #define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8) #define DA850_LCD_BL_PIN GPIO_TO_PIN(2, 15) @@ -678,8 +676,7 @@ static int __init da850_evm_config_emac(void) /* Enable/Disable MII MDIO clock */ gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en); - soc_info->emac_pdata->phy_mask = DA850_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DA850_EVM_MDIO_FREQUENCY; + soc_info->emac_pdata->phy_id = DA850_EVM_PHY_ID; ret = da8xx_register_emac(); if (ret) diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index bdea2da..a06b84c 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -54,9 +54,7 @@ static inline int have_tvp7002(void) return 0; } -#define DM365_EVM_PHY_MASK (0x2) -#define DM365_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - +#define DM365_EVM_PHY_ID "0:01" /* * A MAX-II CPLD is used for various board control functions. */ @@ -535,8 +533,7 @@ fail: /* ... and ENET ... */ dm365evm_emac_configure(); - soc_info->emac_pdata->phy_mask = DM365_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DM365_EVM_MDIO_FREQUENCY; + soc_info->emac_pdata->phy_id = DM365_EVM_PHY_ID; resets &= ~BIT(3); /* ... and AIC33 */ diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 65bb940..44a2f0a 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -39,9 +39,7 @@ #include #include -#define DM644X_EVM_PHY_MASK (0x2) -#define DM644X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - +#define DM644X_EVM_PHY_ID "0:01" #define LXT971_PHY_ID (0x001378e2) #define LXT971_PHY_MASK (0xfffffff0) @@ -707,9 +705,7 @@ static __init void davinci_evm_init(void) davinci_serial_init(&uart_config); dm644x_init_asp(&dm644x_evm_snd_data); - soc_info->emac_pdata->phy_mask = DM644X_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DM644X_EVM_MDIO_FREQUENCY; - + soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID; /* Register the fixup for PHY on DaVinci */ phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK, davinci_phy_fixup); diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 5a29955..67669bb 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -729,9 +729,7 @@ static struct davinci_uart_config uart_config __initdata = { .enabled_uarts = (1 << 0), }; -#define DM646X_EVM_PHY_MASK (0x2) -#define DM646X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - +#define DM646X_EVM_PHY_ID "0:01" /* * The following EDMA channels/slots are not being used by drivers (for * example: Timer, GPIO, UART events etc) on dm646x, hence they are being @@ -784,8 +782,7 @@ static __init void evm_init(void) if (HAS_ATA) davinci_init_ide(); - soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY; + soc_info->emac_pdata->phy_id = DM646X_EVM_PHY_ID; } #define DM646X_EVM_REF_FREQ 27000000 diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index 84d5aff..6f12a18 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -24,9 +24,7 @@ #include #include -#define MITYOMAPL138_PHY_MASK 0x08 /* hardcoded for now */ -#define MITYOMAPL138_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - +#define MITYOMAPL138_PHY_ID "0:03" static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = { .bus_freq = 100, /* kHz */ .bus_delay = 0, /* usec */ @@ -273,9 +271,7 @@ static void __init mityomapl138_config_emac(void) /* configure the CFGCHIP3 register for RMII or MII */ __raw_writel(val, cfg_chip3_base); - soc_info->emac_pdata->phy_mask = MITYOMAPL138_PHY_MASK; - pr_debug("setting phy_mask to %x\n", soc_info->emac_pdata->phy_mask); - soc_info->emac_pdata->mdio_max_freq = MITYOMAPL138_MDIO_FREQUENCY; + soc_info->emac_pdata->phy_id = MITYOMAPL138_PHY_ID; ret = da8xx_register_emac(); if (ret) diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index 4c30e92..04a8d16 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -39,9 +39,7 @@ #include #include -#define NEUROS_OSD2_PHY_MASK 0x2 -#define NEUROS_OSD2_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ - +#define NEUROS_OSD2_PHY_ID "0:01" #define LXT971_PHY_ID 0x001378e2 #define LXT971_PHY_MASK 0xfffffff0 @@ -252,8 +250,7 @@ static __init void davinci_ntosd2_init(void) davinci_serial_init(&uart_config); dm644x_init_asp(&dm644x_ntosd2_snd_data); - soc_info->emac_pdata->phy_mask = NEUROS_OSD2_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = NEUROS_OSD2_MDIO_FREQUENCY; + soc_info->emac_pdata->phy_id = NEUROS_OSD2_PHY_ID; davinci_setup_usb(1000, 8); /* diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 23e664a..ab4292d 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -42,9 +42,7 @@ #include #include -#define SFFSDR_PHY_MASK (0x2) -#define SFFSDR_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ - +#define SFFSDR_PHY_ID "0:01" static struct mtd_partition davinci_sffsdr_nandflash_partition[] = { /* U-Boot Environment: Block 0 * UBL: Block 1 @@ -143,8 +141,7 @@ static __init void davinci_sffsdr_init(void) ARRAY_SIZE(davinci_sffsdr_devices)); sffsdr_init_i2c(); davinci_serial_init(&uart_config); - soc_info->emac_pdata->phy_mask = SFFSDR_PHY_MASK; - soc_info->emac_pdata->mdio_max_freq = SFFSDR_MDIO_FREQUENCY; + soc_info->emac_pdata->phy_id = SFFSDR_PHY_ID; davinci_setup_usb(0, 0); /* We support only peripheral mode. */ /* mux VLYNQ pins */ diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 9039221..9eec630 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -42,7 +42,6 @@ #define DA8XX_EMAC_CTRL_REG_OFFSET 0x3000 #define DA8XX_EMAC_MOD_REG_OFFSET 0x2000 #define DA8XX_EMAC_RAM_OFFSET 0x0000 -#define DA8XX_MDIO_REG_OFFSET 0x4000 #define DA8XX_EMAC_CTRL_RAM_SIZE SZ_8K void __iomem *da8xx_syscfg0_base; @@ -381,7 +380,6 @@ struct emac_platform_data da8xx_emac_pdata = { .ctrl_reg_offset = DA8XX_EMAC_CTRL_REG_OFFSET, .ctrl_mod_reg_offset = DA8XX_EMAC_MOD_REG_OFFSET, .ctrl_ram_offset = DA8XX_EMAC_RAM_OFFSET, - .mdio_reg_offset = DA8XX_MDIO_REG_OFFSET, .ctrl_ram_size = DA8XX_EMAC_CTRL_RAM_SIZE, .version = EMAC_VERSION_2, }; diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 71f0f9d..240f392 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -691,7 +691,6 @@ static struct emac_platform_data dm365_emac_pdata = { .ctrl_reg_offset = DM365_EMAC_CNTRL_OFFSET, .ctrl_mod_reg_offset = DM365_EMAC_CNTRL_MOD_OFFSET, .ctrl_ram_offset = DM365_EMAC_CNTRL_RAM_OFFSET, - .mdio_reg_offset = DM365_EMAC_MDIO_OFFSET, .ctrl_ram_size = DM365_EMAC_CNTRL_RAM_SIZE, .version = EMAC_VERSION_2, }; diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index c103b2c..41b7a95 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -322,7 +322,6 @@ static struct emac_platform_data dm644x_emac_pdata = { .ctrl_reg_offset = DM644X_EMAC_CNTRL_OFFSET, .ctrl_mod_reg_offset = DM644X_EMAC_CNTRL_MOD_OFFSET, .ctrl_ram_offset = DM644X_EMAC_CNTRL_RAM_OFFSET, - .mdio_reg_offset = DM644X_EMAC_MDIO_OFFSET, .ctrl_ram_size = DM644X_EMAC_CNTRL_RAM_SIZE, .version = EMAC_VERSION_1, }; diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 8da886b..08db90f 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -358,7 +358,6 @@ static struct emac_platform_data dm646x_emac_pdata = { .ctrl_reg_offset = DM646X_EMAC_CNTRL_OFFSET, .ctrl_mod_reg_offset = DM646X_EMAC_CNTRL_MOD_OFFSET, .ctrl_ram_offset = DM646X_EMAC_CNTRL_RAM_OFFSET, - .mdio_reg_offset = DM646X_EMAC_MDIO_OFFSET, .ctrl_ram_size = DM646X_EMAC_CNTRL_RAM_SIZE, .version = EMAC_VERSION_2, }; diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h index dbb5052..2563bf4 100644 --- a/arch/arm/mach-davinci/include/mach/dm365.h +++ b/arch/arm/mach-davinci/include/mach/dm365.h @@ -25,7 +25,6 @@ #define DM365_EMAC_CNTRL_OFFSET (0x0000) #define DM365_EMAC_CNTRL_MOD_OFFSET (0x3000) #define DM365_EMAC_CNTRL_RAM_OFFSET (0x1000) -#define DM365_EMAC_MDIO_OFFSET (0x4000) #define DM365_EMAC_CNTRL_RAM_SIZE (0x2000) /* Base of key scan register bank */ diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h index 5159117..5a1b26d 100644 --- a/arch/arm/mach-davinci/include/mach/dm644x.h +++ b/arch/arm/mach-davinci/include/mach/dm644x.h @@ -32,7 +32,6 @@ #define DM644X_EMAC_CNTRL_OFFSET (0x0000) #define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000) -#define DM644X_EMAC_MDIO_OFFSET (0x4000) #define DM644X_EMAC_CNTRL_RAM_SIZE (0x2000) #define DM644X_ASYNC_EMIF_CONTROL_BASE 0x01E00000 diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h index 1c4dca9..7a27f3f 100644 --- a/arch/arm/mach-davinci/include/mach/dm646x.h +++ b/arch/arm/mach-davinci/include/mach/dm646x.h @@ -23,7 +23,6 @@ #define DM646X_EMAC_CNTRL_OFFSET (0x0000) #define DM646X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM646X_EMAC_CNTRL_RAM_OFFSET (0x2000) -#define DM646X_EMAC_MDIO_OFFSET (0x4000) #define DM646X_EMAC_CNTRL_RAM_SIZE (0x2000) #define DM646X_ASYNC_EMIF_CONTROL_BASE 0x20008000 -- 1.7.0.4 From cyril at ti.com Wed Sep 15 09:11:22 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Wed, 15 Sep 2010 10:11:22 -0400 Subject: [PATCH v4 02/10] davinci: add mdio platform devices In-Reply-To: <1284559890-31346-1-git-send-email-cyril@ti.com> References: <1284559890-31346-1-git-send-email-cyril@ti.com> Message-ID: <1284559890-31346-3-git-send-email-cyril@ti.com> This patch adds mdio platform devices on SoCs that have the necessary hardware. Clock lookup entries (aliases) have also been added, so that the MDIO and EMAC drivers can independently enable/disable a shared underlying clock. Further, the EMAC MMR region has been split down into separate MDIO and EMAC regions. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- arch/arm/mach-davinci/devices-da8xx.c | 29 +++++++++++++++++++++++++- arch/arm/mach-davinci/dm365.c | 22 +++++++++++++++++++- arch/arm/mach-davinci/dm644x.c | 22 +++++++++++++++++++- arch/arm/mach-davinci/dm646x.c | 21 ++++++++++++++++++- arch/arm/mach-davinci/include/mach/dm365.h | 1 + arch/arm/mach-davinci/include/mach/dm644x.h | 1 + arch/arm/mach-davinci/include/mach/dm646x.h | 1 + 7 files changed, 92 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index caeb7f4..9039221 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -352,7 +352,7 @@ int __init da8xx_register_watchdog(void) static struct resource da8xx_emac_resources[] = { { .start = DA8XX_EMAC_CPPI_PORT_BASE, - .end = DA8XX_EMAC_CPPI_PORT_BASE + 0x5000 - 1, + .end = DA8XX_EMAC_CPPI_PORT_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -396,9 +396,34 @@ static struct platform_device da8xx_emac_device = { .resource = da8xx_emac_resources, }; +static struct resource da8xx_mdio_resources[] = { + { + .start = DA8XX_EMAC_MDIO_BASE, + .end = DA8XX_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device da8xx_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(da8xx_mdio_resources), + .resource = da8xx_mdio_resources, +}; + int __init da8xx_register_emac(void) { - return platform_device_register(&da8xx_emac_device); + int ret; + + ret = platform_device_register(&da8xx_mdio_device); + if (ret < 0) + return ret; + ret = platform_device_register(&da8xx_emac_device); + if (ret < 0) + return ret; + ret = clk_add_alias(NULL, dev_name(&da8xx_mdio_device.dev), + NULL, &da8xx_emac_device.dev); + return ret; } static struct resource da830_mcasp1_resources[] = { diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 6b6f4c6..71f0f9d 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -699,7 +699,7 @@ static struct emac_platform_data dm365_emac_pdata = { static struct resource dm365_emac_resources[] = { { .start = DM365_EMAC_BASE, - .end = DM365_EMAC_BASE + 0x47ff, + .end = DM365_EMAC_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -734,6 +734,21 @@ static struct platform_device dm365_emac_device = { .resource = dm365_emac_resources, }; +static struct resource dm365_mdio_resources[] = { + { + .start = DM365_EMAC_MDIO_BASE, + .end = DM365_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device dm365_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(dm365_mdio_resources), + .resource = dm365_mdio_resources, +}; + static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = { [IRQ_VDINT0] = 2, [IRQ_VDINT1] = 6, @@ -1220,7 +1235,12 @@ static int __init dm365_init_devices(void) davinci_cfg_reg(DM365_INT_EDMA_CC); platform_device_register(&dm365_edma_device); + + platform_device_register(&dm365_mdio_device); platform_device_register(&dm365_emac_device); + clk_add_alias(NULL, dev_name(&dm365_mdio_device.dev), + NULL, &dm365_emac_device.dev); + /* Add isif clock alias */ clk_add_alias("master", dm365_isif_dev.name, "vpss_master", NULL); platform_device_register(&dm365_vpss_device); diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 40fec31..c103b2c 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -330,7 +330,7 @@ static struct emac_platform_data dm644x_emac_pdata = { static struct resource dm644x_emac_resources[] = { { .start = DM644X_EMAC_BASE, - .end = DM644X_EMAC_BASE + 0x47ff, + .end = DM644X_EMAC_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -350,6 +350,21 @@ static struct platform_device dm644x_emac_device = { .resource = dm644x_emac_resources, }; +static struct resource dm644x_mdio_resources[] = { + { + .start = DM644X_EMAC_MDIO_BASE, + .end = DM644X_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device dm644x_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(dm644x_mdio_resources), + .resource = dm644x_mdio_resources, +}; + /* * Device specific mux setup * @@ -777,7 +792,12 @@ static int __init dm644x_init_devices(void) clk_add_alias("master", dm644x_ccdc_dev.name, "vpss_master", NULL); clk_add_alias("slave", dm644x_ccdc_dev.name, "vpss_slave", NULL); platform_device_register(&dm644x_edma_device); + + platform_device_register(&dm644x_mdio_device); platform_device_register(&dm644x_emac_device); + clk_add_alias(NULL, dev_name(&dm644x_mdio_device.dev), + NULL, &dm644x_emac_device.dev); + platform_device_register(&dm644x_vpss_device); platform_device_register(&dm644x_ccdc_dev); platform_device_register(&vpfe_capture_dev); diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index e4a3df1..8da886b 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -366,7 +366,7 @@ static struct emac_platform_data dm646x_emac_pdata = { static struct resource dm646x_emac_resources[] = { { .start = DM646X_EMAC_BASE, - .end = DM646X_EMAC_BASE + 0x47ff, + .end = DM646X_EMAC_BASE + SZ_16K - 1, .flags = IORESOURCE_MEM, }, { @@ -401,6 +401,21 @@ static struct platform_device dm646x_emac_device = { .resource = dm646x_emac_resources, }; +static struct resource dm646x_mdio_resources[] = { + { + .start = DM646X_EMAC_MDIO_BASE, + .end = DM646X_EMAC_MDIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device dm646x_mdio_device = { + .name = "davinci_mdio", + .id = 0, + .num_resources = ARRAY_SIZE(dm646x_mdio_resources), + .resource = dm646x_mdio_resources, +}; + /* * Device specific mux setup * @@ -897,7 +912,11 @@ static int __init dm646x_init_devices(void) if (!cpu_is_davinci_dm646x()) return 0; + platform_device_register(&dm646x_mdio_device); platform_device_register(&dm646x_emac_device); + clk_add_alias(NULL, dev_name(&dm646x_mdio_device.dev), + NULL, &dm646x_emac_device.dev); + return 0; } postcore_initcall(dm646x_init_devices); diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h index ea5df3b..dbb5052 100644 --- a/arch/arm/mach-davinci/include/mach/dm365.h +++ b/arch/arm/mach-davinci/include/mach/dm365.h @@ -21,6 +21,7 @@ #include #define DM365_EMAC_BASE (0x01D07000) +#define DM365_EMAC_MDIO_BASE (DM365_EMAC_BASE + 0x4000) #define DM365_EMAC_CNTRL_OFFSET (0x0000) #define DM365_EMAC_CNTRL_MOD_OFFSET (0x3000) #define DM365_EMAC_CNTRL_RAM_OFFSET (0x1000) diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h index 6fca568..5159117 100644 --- a/arch/arm/mach-davinci/include/mach/dm644x.h +++ b/arch/arm/mach-davinci/include/mach/dm644x.h @@ -28,6 +28,7 @@ #include #define DM644X_EMAC_BASE (0x01C80000) +#define DM644X_EMAC_MDIO_BASE (DM644X_EMAC_BASE + 0x4000) #define DM644X_EMAC_CNTRL_OFFSET (0x0000) #define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000) diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h index 0a27ee9..1c4dca9 100644 --- a/arch/arm/mach-davinci/include/mach/dm646x.h +++ b/arch/arm/mach-davinci/include/mach/dm646x.h @@ -19,6 +19,7 @@ #include #define DM646X_EMAC_BASE (0x01C80000) +#define DM646X_EMAC_MDIO_BASE (DM646X_EMAC_BASE + 0x4000) #define DM646X_EMAC_CNTRL_OFFSET (0x0000) #define DM646X_EMAC_CNTRL_MOD_OFFSET (0x1000) #define DM646X_EMAC_CNTRL_RAM_OFFSET (0x2000) -- 1.7.0.4 From cyril at ti.com Wed Sep 15 09:11:28 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Wed, 15 Sep 2010 10:11:28 -0400 Subject: [PATCH v4 08/10] net: davinci_emac: separate out cpdma code In-Reply-To: <1284559890-31346-1-git-send-email-cyril@ti.com> References: <1284559890-31346-1-git-send-email-cyril@ti.com> Message-ID: <1284559890-31346-9-git-send-email-cyril@ti.com> In addition to being embedded into the EMAC controller, the CPDMA hardware block is used in TI's CPSW switch controller. Fortunately, the programming interface to this hardware block remains pretty nicely consistent across these devices. This patch adds a new CPDMA services layer, which can then be reused across EMAC and CPSW drivers. Signed-off-by: Cyril Chemparathy Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- drivers/net/Kconfig | 10 + drivers/net/Makefile | 1 + drivers/net/davinci_cpdma.c | 965 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/davinci_cpdma.h | 108 +++++ 4 files changed, 1084 insertions(+), 0 deletions(-) create mode 100644 drivers/net/davinci_cpdma.c create mode 100644 drivers/net/davinci_cpdma.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 911e7f1..775fd87 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -952,6 +952,7 @@ config TI_DAVINCI_EMAC tristate "TI DaVinci EMAC Support" depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) select TI_DAVINCI_MDIO + select TI_DAVINCI_CPDMA select PHYLIB help This driver supports TI's DaVinci Ethernet . @@ -969,6 +970,15 @@ config TI_DAVINCI_MDIO To compile this driver as a module, choose M here: the module will be called davinci_mdio. This is recommended. +config TI_DAVINCI_CPDMA + tristate "TI DaVinci CPDMA Support" + depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) + help + This driver supports TI's DaVinci CPDMA dma engine. + + To compile this driver as a module, choose M here: the module + will be called davinci_cpdma. This is recommended. + config DM9000 tristate "DM9000 support" depends on ARM || BLACKFIN || MIPS diff --git a/drivers/net/Makefile b/drivers/net/Makefile index d38a7ab..65da885 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_PHYLIB) += phy/ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o +obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_E1000E) += e1000e/ diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c new file mode 100644 index 0000000..e92b2b6 --- /dev/null +++ b/drivers/net/davinci_cpdma.c @@ -0,0 +1,965 @@ +/* + * Texas Instruments CPDMA Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "davinci_cpdma.h" + +/* DMA Registers */ +#define CPDMA_TXIDVER 0x00 +#define CPDMA_TXCONTROL 0x04 +#define CPDMA_TXTEARDOWN 0x08 +#define CPDMA_RXIDVER 0x10 +#define CPDMA_RXCONTROL 0x14 +#define CPDMA_SOFTRESET 0x1c +#define CPDMA_RXTEARDOWN 0x18 +#define CPDMA_TXINTSTATRAW 0x80 +#define CPDMA_TXINTSTATMASKED 0x84 +#define CPDMA_TXINTMASKSET 0x88 +#define CPDMA_TXINTMASKCLEAR 0x8c +#define CPDMA_MACINVECTOR 0x90 +#define CPDMA_MACEOIVECTOR 0x94 +#define CPDMA_RXINTSTATRAW 0xa0 +#define CPDMA_RXINTSTATMASKED 0xa4 +#define CPDMA_RXINTMASKSET 0xa8 +#define CPDMA_RXINTMASKCLEAR 0xac +#define CPDMA_DMAINTSTATRAW 0xb0 +#define CPDMA_DMAINTSTATMASKED 0xb4 +#define CPDMA_DMAINTMASKSET 0xb8 +#define CPDMA_DMAINTMASKCLEAR 0xbc +#define CPDMA_DMAINT_HOSTERR BIT(1) + +/* the following exist only if has_ext_regs is set */ +#define CPDMA_DMACONTROL 0x20 +#define CPDMA_DMASTATUS 0x24 +#define CPDMA_RXBUFFOFS 0x28 +#define CPDMA_EM_CONTROL 0x2c + +/* Descriptor mode bits */ +#define CPDMA_DESC_SOP BIT(31) +#define CPDMA_DESC_EOP BIT(30) +#define CPDMA_DESC_OWNER BIT(29) +#define CPDMA_DESC_EOQ BIT(28) +#define CPDMA_DESC_TD_COMPLETE BIT(27) +#define CPDMA_DESC_PASS_CRC BIT(26) + +#define CPDMA_TEARDOWN_VALUE 0xfffffffc + +struct cpdma_desc { + /* hardware fields */ + u32 hw_next; + u32 hw_buffer; + u32 hw_len; + u32 hw_mode; + /* software fields */ + void *sw_token; + u32 sw_buffer; + u32 sw_len; +}; + +struct cpdma_desc_pool { + u32 phys; + void __iomem *iomap; /* ioremap map */ + void *cpumap; /* dma_alloc map */ + int desc_size, mem_size; + int num_desc, used_desc; + unsigned long *bitmap; + struct device *dev; + spinlock_t lock; +}; + +enum cpdma_state { + CPDMA_STATE_IDLE, + CPDMA_STATE_ACTIVE, + CPDMA_STATE_TEARDOWN, +}; + +const char *cpdma_state_str[] = { "idle", "active", "teardown" }; + +struct cpdma_ctlr { + enum cpdma_state state; + struct cpdma_params params; + struct device *dev; + struct cpdma_desc_pool *pool; + spinlock_t lock; + struct cpdma_chan *channels[2 * CPDMA_MAX_CHANNELS]; +}; + +struct cpdma_chan { + enum cpdma_state state; + struct cpdma_ctlr *ctlr; + int chan_num; + spinlock_t lock; + struct cpdma_desc __iomem *head, *tail; + int count; + void __iomem *hdp, *cp, *rxfree; + u32 mask; + cpdma_handler_fn handler; + enum dma_data_direction dir; + struct cpdma_chan_stats stats; + /* offsets into dmaregs */ + int int_set, int_clear, td; +}; + +/* The following make access to common cpdma_ctlr params more readable */ +#define dmaregs params.dmaregs +#define num_chan params.num_chan + +/* various accessors */ +#define dma_reg_read(ctlr, ofs) __raw_readl((ctlr)->dmaregs + (ofs)) +#define chan_read(chan, fld) __raw_readl((chan)->fld) +#define desc_read(desc, fld) __raw_readl(&(desc)->fld) +#define dma_reg_write(ctlr, ofs, v) __raw_writel(v, (ctlr)->dmaregs + (ofs)) +#define chan_write(chan, fld, v) __raw_writel(v, (chan)->fld) +#define desc_write(desc, fld, v) __raw_writel((u32)(v), &(desc)->fld) + +/* + * Utility constructs for a cpdma descriptor pool. Some devices (e.g. davinci + * emac) have dedicated on-chip memory for these descriptors. Some other + * devices (e.g. cpsw switches) use plain old memory. Descriptor pools + * abstract out these details + */ +static struct cpdma_desc_pool * +cpdma_desc_pool_create(struct device *dev, u32 phys, int size, int align) +{ + int bitmap_size; + struct cpdma_desc_pool *pool; + + pool = kzalloc(sizeof(*pool), GFP_KERNEL); + if (!pool) + return NULL; + + spin_lock_init(&pool->lock); + + pool->dev = dev; + pool->mem_size = size; + pool->desc_size = ALIGN(sizeof(struct cpdma_desc), align); + pool->num_desc = size / pool->desc_size; + + bitmap_size = (pool->num_desc / BITS_PER_LONG) * sizeof(long); + pool->bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!pool->bitmap) + goto fail; + + if (phys) { + pool->phys = phys; + pool->iomap = ioremap(phys, size); + } else { + pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys, + GFP_KERNEL); + pool->iomap = (void __force __iomem *)pool->cpumap; + } + + if (pool->iomap) + return pool; + +fail: + kfree(pool->bitmap); + kfree(pool); + return NULL; +} + +static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool) +{ + unsigned long flags; + + if (!pool) + return; + + spin_lock_irqsave(&pool->lock, flags); + WARN_ON(pool->used_desc); + kfree(pool->bitmap); + if (pool->cpumap) { + dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap, + pool->phys); + } else { + iounmap(pool->iomap); + } + spin_unlock_irqrestore(&pool->lock, flags); + kfree(pool); +} + +static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool, + struct cpdma_desc __iomem *desc) +{ + if (!desc) + return 0; + return pool->phys + (__force dma_addr_t)desc - + (__force dma_addr_t)pool->iomap; +} + +static inline struct cpdma_desc __iomem * +desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma) +{ + return dma ? pool->iomap + dma - pool->phys : NULL; +} + +static struct cpdma_desc __iomem * +cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc) +{ + unsigned long flags; + int index; + struct cpdma_desc __iomem *desc = NULL; + + spin_lock_irqsave(&pool->lock, flags); + + index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0, + num_desc, 0); + if (index < pool->num_desc) { + bitmap_set(pool->bitmap, index, num_desc); + desc = pool->iomap + pool->desc_size * index; + pool->used_desc++; + } + + spin_unlock_irqrestore(&pool->lock, flags); + return desc; +} + +static void cpdma_desc_free(struct cpdma_desc_pool *pool, + struct cpdma_desc __iomem *desc, int num_desc) +{ + unsigned long flags, index; + + index = ((unsigned long)desc - (unsigned long)pool->iomap) / + pool->desc_size; + spin_lock_irqsave(&pool->lock, flags); + bitmap_clear(pool->bitmap, index, num_desc); + pool->used_desc--; + spin_unlock_irqrestore(&pool->lock, flags); +} + +struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params) +{ + struct cpdma_ctlr *ctlr; + + ctlr = kzalloc(sizeof(*ctlr), GFP_KERNEL); + if (!ctlr) + return NULL; + + ctlr->state = CPDMA_STATE_IDLE; + ctlr->params = *params; + ctlr->dev = params->dev; + spin_lock_init(&ctlr->lock); + + ctlr->pool = cpdma_desc_pool_create(ctlr->dev, + ctlr->params.desc_mem_phys, + ctlr->params.desc_mem_size, + ctlr->params.desc_align); + if (!ctlr->pool) { + kfree(ctlr); + return NULL; + } + + if (WARN_ON(ctlr->num_chan > CPDMA_MAX_CHANNELS)) + ctlr->num_chan = CPDMA_MAX_CHANNELS; + return ctlr; +} + +int cpdma_ctlr_start(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_IDLE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EBUSY; + } + + if (ctlr->params.has_soft_reset) { + unsigned long timeout = jiffies + HZ/10; + + dma_reg_write(ctlr, CPDMA_SOFTRESET, 1); + while (time_before(jiffies, timeout)) { + if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0) + break; + } + WARN_ON(!time_before(jiffies, timeout)); + } + + for (i = 0; i < ctlr->num_chan; i++) { + __raw_writel(0, ctlr->params.txhdp + 4 * i); + __raw_writel(0, ctlr->params.rxhdp + 4 * i); + __raw_writel(0, ctlr->params.txcp + 4 * i); + __raw_writel(0, ctlr->params.rxcp + 4 * i); + } + + dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); + dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); + + dma_reg_write(ctlr, CPDMA_TXCONTROL, 1); + dma_reg_write(ctlr, CPDMA_RXCONTROL, 1); + + ctlr->state = CPDMA_STATE_ACTIVE; + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_start(ctlr->channels[i]); + } + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EINVAL; + } + + ctlr->state = CPDMA_STATE_TEARDOWN; + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_stop(ctlr->channels[i]); + } + + dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff); + dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff); + + dma_reg_write(ctlr, CPDMA_TXCONTROL, 0); + dma_reg_write(ctlr, CPDMA_RXCONTROL, 0); + + ctlr->state = CPDMA_STATE_IDLE; + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr) +{ + struct device *dev = ctlr->dev; + unsigned long flags; + int i; + + spin_lock_irqsave(&ctlr->lock, flags); + + dev_info(dev, "CPDMA: state: %s", cpdma_state_str[ctlr->state]); + + dev_info(dev, "CPDMA: txidver: %x", + dma_reg_read(ctlr, CPDMA_TXIDVER)); + dev_info(dev, "CPDMA: txcontrol: %x", + dma_reg_read(ctlr, CPDMA_TXCONTROL)); + dev_info(dev, "CPDMA: txteardown: %x", + dma_reg_read(ctlr, CPDMA_TXTEARDOWN)); + dev_info(dev, "CPDMA: rxidver: %x", + dma_reg_read(ctlr, CPDMA_RXIDVER)); + dev_info(dev, "CPDMA: rxcontrol: %x", + dma_reg_read(ctlr, CPDMA_RXCONTROL)); + dev_info(dev, "CPDMA: softreset: %x", + dma_reg_read(ctlr, CPDMA_SOFTRESET)); + dev_info(dev, "CPDMA: rxteardown: %x", + dma_reg_read(ctlr, CPDMA_RXTEARDOWN)); + dev_info(dev, "CPDMA: txintstatraw: %x", + dma_reg_read(ctlr, CPDMA_TXINTSTATRAW)); + dev_info(dev, "CPDMA: txintstatmasked: %x", + dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED)); + dev_info(dev, "CPDMA: txintmaskset: %x", + dma_reg_read(ctlr, CPDMA_TXINTMASKSET)); + dev_info(dev, "CPDMA: txintmaskclear: %x", + dma_reg_read(ctlr, CPDMA_TXINTMASKCLEAR)); + dev_info(dev, "CPDMA: macinvector: %x", + dma_reg_read(ctlr, CPDMA_MACINVECTOR)); + dev_info(dev, "CPDMA: maceoivector: %x", + dma_reg_read(ctlr, CPDMA_MACEOIVECTOR)); + dev_info(dev, "CPDMA: rxintstatraw: %x", + dma_reg_read(ctlr, CPDMA_RXINTSTATRAW)); + dev_info(dev, "CPDMA: rxintstatmasked: %x", + dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED)); + dev_info(dev, "CPDMA: rxintmaskset: %x", + dma_reg_read(ctlr, CPDMA_RXINTMASKSET)); + dev_info(dev, "CPDMA: rxintmaskclear: %x", + dma_reg_read(ctlr, CPDMA_RXINTMASKCLEAR)); + dev_info(dev, "CPDMA: dmaintstatraw: %x", + dma_reg_read(ctlr, CPDMA_DMAINTSTATRAW)); + dev_info(dev, "CPDMA: dmaintstatmasked: %x", + dma_reg_read(ctlr, CPDMA_DMAINTSTATMASKED)); + dev_info(dev, "CPDMA: dmaintmaskset: %x", + dma_reg_read(ctlr, CPDMA_DMAINTMASKSET)); + dev_info(dev, "CPDMA: dmaintmaskclear: %x", + dma_reg_read(ctlr, CPDMA_DMAINTMASKCLEAR)); + + if (!ctlr->params.has_ext_regs) { + dev_info(dev, "CPDMA: dmacontrol: %x", + dma_reg_read(ctlr, CPDMA_DMACONTROL)); + dev_info(dev, "CPDMA: dmastatus: %x", + dma_reg_read(ctlr, CPDMA_DMASTATUS)); + dev_info(dev, "CPDMA: rxbuffofs: %x", + dma_reg_read(ctlr, CPDMA_RXBUFFOFS)); + } + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) + if (ctlr->channels[i]) + cpdma_chan_dump(ctlr->channels[i]); + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr) +{ + unsigned long flags; + int ret = 0, i; + + if (!ctlr) + return -EINVAL; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_IDLE) + cpdma_ctlr_stop(ctlr); + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_destroy(ctlr->channels[i]); + } + + cpdma_desc_pool_destroy(ctlr->pool); + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(ctlr); + return ret; +} + +int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable) +{ + unsigned long flags; + int i, reg; + + spin_lock_irqsave(&ctlr->lock, flags); + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&ctlr->lock, flags); + return -EINVAL; + } + + reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR; + dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR); + + for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { + if (ctlr->channels[i]) + cpdma_chan_int_ctrl(ctlr->channels[i], enable); + } + + spin_unlock_irqrestore(&ctlr->lock, flags); + return 0; +} + +void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr) +{ + dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0); +} + +struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, + cpdma_handler_fn handler) +{ + struct cpdma_chan *chan; + int ret, offset = (chan_num % CPDMA_MAX_CHANNELS) * 4; + unsigned long flags; + + if (__chan_linear(chan_num) >= ctlr->num_chan) + return NULL; + + ret = -ENOMEM; + chan = kzalloc(sizeof(*chan), GFP_KERNEL); + if (!chan) + goto err_chan_alloc; + + spin_lock_irqsave(&ctlr->lock, flags); + ret = -EBUSY; + if (ctlr->channels[chan_num]) + goto err_chan_busy; + + chan->ctlr = ctlr; + chan->state = CPDMA_STATE_IDLE; + chan->chan_num = chan_num; + chan->handler = handler; + + if (is_rx_chan(chan)) { + chan->hdp = ctlr->params.rxhdp + offset; + chan->cp = ctlr->params.rxcp + offset; + chan->rxfree = ctlr->params.rxfree + offset; + chan->int_set = CPDMA_RXINTMASKSET; + chan->int_clear = CPDMA_RXINTMASKCLEAR; + chan->td = CPDMA_RXTEARDOWN; + chan->dir = DMA_FROM_DEVICE; + } else { + chan->hdp = ctlr->params.txhdp + offset; + chan->cp = ctlr->params.txcp + offset; + chan->int_set = CPDMA_TXINTMASKSET; + chan->int_clear = CPDMA_TXINTMASKCLEAR; + chan->td = CPDMA_TXTEARDOWN; + chan->dir = DMA_TO_DEVICE; + } + chan->mask = BIT(chan_linear(chan)); + + spin_lock_init(&chan->lock); + + ctlr->channels[chan_num] = chan; + spin_unlock_irqrestore(&ctlr->lock, flags); + return chan; + +err_chan_busy: + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(chan); +err_chan_alloc: + return ERR_PTR(ret); +} + +int cpdma_chan_destroy(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + unsigned long flags; + + if (!chan) + return -EINVAL; + + spin_lock_irqsave(&ctlr->lock, flags); + if (chan->state != CPDMA_STATE_IDLE) + cpdma_chan_stop(chan); + ctlr->channels[chan->chan_num] = NULL; + spin_unlock_irqrestore(&ctlr->lock, flags); + kfree(chan); + return 0; +} + +int cpdma_chan_get_stats(struct cpdma_chan *chan, + struct cpdma_chan_stats *stats) +{ + unsigned long flags; + if (!chan) + return -EINVAL; + spin_lock_irqsave(&chan->lock, flags); + memcpy(stats, &chan->stats, sizeof(*stats)); + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +int cpdma_chan_dump(struct cpdma_chan *chan) +{ + unsigned long flags; + struct device *dev = chan->ctlr->dev; + + spin_lock_irqsave(&chan->lock, flags); + + dev_info(dev, "channel %d (%s %d) state %s", + chan->chan_num, is_rx_chan(chan) ? "rx" : "tx", + chan_linear(chan), cpdma_state_str[chan->state]); + dev_info(dev, "\thdp: %x\n", chan_read(chan, hdp)); + dev_info(dev, "\tcp: %x\n", chan_read(chan, cp)); + if (chan->rxfree) { + dev_info(dev, "\trxfree: %x\n", + chan_read(chan, rxfree)); + } + + dev_info(dev, "\tstats head_enqueue: %d\n", + chan->stats.head_enqueue); + dev_info(dev, "\tstats tail_enqueue: %d\n", + chan->stats.tail_enqueue); + dev_info(dev, "\tstats pad_enqueue: %d\n", + chan->stats.pad_enqueue); + dev_info(dev, "\tstats misqueued: %d\n", + chan->stats.misqueued); + dev_info(dev, "\tstats desc_alloc_fail: %d\n", + chan->stats.desc_alloc_fail); + dev_info(dev, "\tstats pad_alloc_fail: %d\n", + chan->stats.pad_alloc_fail); + dev_info(dev, "\tstats runt_receive_buff: %d\n", + chan->stats.runt_receive_buff); + dev_info(dev, "\tstats runt_transmit_buff: %d\n", + chan->stats.runt_transmit_buff); + dev_info(dev, "\tstats empty_dequeue: %d\n", + chan->stats.empty_dequeue); + dev_info(dev, "\tstats busy_dequeue: %d\n", + chan->stats.busy_dequeue); + dev_info(dev, "\tstats good_dequeue: %d\n", + chan->stats.good_dequeue); + dev_info(dev, "\tstats requeue: %d\n", + chan->stats.requeue); + dev_info(dev, "\tstats teardown_dequeue: %d\n", + chan->stats.teardown_dequeue); + + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +static void __cpdma_chan_submit(struct cpdma_chan *chan, + struct cpdma_desc __iomem *desc) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *prev = chan->tail; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t desc_dma; + u32 mode; + + desc_dma = desc_phys(pool, desc); + + /* simple case - idle channel */ + if (!chan->head) { + chan->stats.head_enqueue++; + chan->head = desc; + chan->tail = desc; + if (chan->state == CPDMA_STATE_ACTIVE) + chan_write(chan, hdp, desc_dma); + return; + } + + /* first chain the descriptor at the tail of the list */ + desc_write(prev, hw_next, desc_dma); + chan->tail = desc; + chan->stats.tail_enqueue++; + + /* next check if EOQ has been triggered already */ + mode = desc_read(prev, hw_mode); + if (((mode & (CPDMA_DESC_EOQ | CPDMA_DESC_OWNER)) == CPDMA_DESC_EOQ) && + (chan->state == CPDMA_STATE_ACTIVE)) { + desc_write(prev, hw_mode, mode & ~CPDMA_DESC_EOQ); + chan_write(chan, hdp, desc_dma); + chan->stats.misqueued++; + } +} + +int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, + int len, gfp_t gfp_mask) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *desc; + dma_addr_t buffer; + unsigned long flags; + u32 mode; + int ret = 0; + + spin_lock_irqsave(&chan->lock, flags); + + if (chan->state == CPDMA_STATE_TEARDOWN) { + ret = -EINVAL; + goto unlock_ret; + } + + desc = cpdma_desc_alloc(ctlr->pool, 1); + if (!desc) { + chan->stats.desc_alloc_fail++; + ret = -ENOMEM; + goto unlock_ret; + } + + if (len < ctlr->params.min_packet_size) { + len = ctlr->params.min_packet_size; + chan->stats.runt_transmit_buff++; + } + + buffer = dma_map_single(ctlr->dev, data, len, chan->dir); + mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP; + + desc_write(desc, hw_next, 0); + desc_write(desc, hw_buffer, buffer); + desc_write(desc, hw_len, len); + desc_write(desc, hw_mode, mode | len); + desc_write(desc, sw_token, token); + desc_write(desc, sw_buffer, buffer); + desc_write(desc, sw_len, len); + + __cpdma_chan_submit(chan, desc); + + if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree) + chan_write(chan, rxfree, 1); + + chan->count++; + +unlock_ret: + spin_unlock_irqrestore(&chan->lock, flags); + return ret; +} + +static void __cpdma_chan_free(struct cpdma_chan *chan, + struct cpdma_desc __iomem *desc, + int outlen, int status) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t buff_dma; + int origlen; + void *token; + + token = (void *)desc_read(desc, sw_token); + buff_dma = desc_read(desc, sw_buffer); + origlen = desc_read(desc, sw_len); + + dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir); + cpdma_desc_free(pool, desc, 1); + (*chan->handler)(token, outlen, status); +} + +static int __cpdma_chan_process(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc __iomem *desc; + int status, outlen; + struct cpdma_desc_pool *pool = ctlr->pool; + dma_addr_t desc_dma; + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + + desc = chan->head; + if (!desc) { + chan->stats.empty_dequeue++; + status = -ENOENT; + goto unlock_ret; + } + desc_dma = desc_phys(pool, desc); + + status = __raw_readl(&desc->hw_mode); + outlen = status & 0x7ff; + if (status & CPDMA_DESC_OWNER) { + chan->stats.busy_dequeue++; + status = -EBUSY; + goto unlock_ret; + } + status = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE); + + chan->head = desc_from_phys(pool, desc_read(desc, hw_next)); + chan_write(chan, cp, desc_dma); + chan->count--; + chan->stats.good_dequeue++; + + if (status & CPDMA_DESC_EOQ) { + chan->stats.requeue++; + chan_write(chan, hdp, desc_phys(pool, chan->head)); + } + + spin_unlock_irqrestore(&chan->lock, flags); + + __cpdma_chan_free(chan, desc, outlen, status); + return status; + +unlock_ret: + spin_unlock_irqrestore(&chan->lock, flags); + return status; +} + +int cpdma_chan_process(struct cpdma_chan *chan, int quota) +{ + int used = 0, ret = 0; + + if (chan->state != CPDMA_STATE_ACTIVE) + return -EINVAL; + + while (used < quota) { + ret = __cpdma_chan_process(chan); + if (ret < 0) + break; + used++; + } + return used; +} + +int cpdma_chan_start(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_IDLE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EBUSY; + } + if (ctlr->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + dma_reg_write(ctlr, chan->int_set, chan->mask); + chan->state = CPDMA_STATE_ACTIVE; + if (chan->head) { + chan_write(chan, hdp, desc_phys(pool, chan->head)); + if (chan->rxfree) + chan_write(chan, rxfree, chan->count); + } + + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +int cpdma_chan_stop(struct cpdma_chan *chan) +{ + struct cpdma_ctlr *ctlr = chan->ctlr; + struct cpdma_desc_pool *pool = ctlr->pool; + unsigned long flags; + int ret; + unsigned long timeout; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + + chan->state = CPDMA_STATE_TEARDOWN; + dma_reg_write(ctlr, chan->int_clear, chan->mask); + + /* trigger teardown */ + dma_reg_write(ctlr, chan->td, chan->chan_num); + + /* wait for teardown complete */ + timeout = jiffies + HZ/10; /* 100 msec */ + while (time_before(jiffies, timeout)) { + u32 cp = chan_read(chan, cp); + if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE) + break; + cpu_relax(); + } + WARN_ON(!time_before(jiffies, timeout)); + chan_write(chan, cp, CPDMA_TEARDOWN_VALUE); + + /* handle completed packets */ + do { + ret = __cpdma_chan_process(chan); + if (ret < 0) + break; + } while ((ret & CPDMA_DESC_TD_COMPLETE) == 0); + + /* remaining packets haven't been tx/rx'ed, clean them up */ + while (chan->head) { + struct cpdma_desc __iomem *desc = chan->head; + dma_addr_t next_dma; + + next_dma = desc_read(desc, hw_next); + chan->head = desc_from_phys(pool, next_dma); + chan->stats.teardown_dequeue++; + + /* issue callback without locks held */ + spin_unlock_irqrestore(&chan->lock, flags); + __cpdma_chan_free(chan, desc, 0, -ENOSYS); + spin_lock_irqsave(&chan->lock, flags); + } + + chan->state = CPDMA_STATE_IDLE; + spin_unlock_irqrestore(&chan->lock, flags); + return 0; +} + +int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable) +{ + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->state != CPDMA_STATE_ACTIVE) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EINVAL; + } + + dma_reg_write(chan->ctlr, enable ? chan->int_set : chan->int_clear, + chan->mask); + spin_unlock_irqrestore(&chan->lock, flags); + + return 0; +} + +struct cpdma_control_info { + u32 reg; + u32 shift, mask; + int access; +#define ACCESS_RO BIT(0) +#define ACCESS_WO BIT(1) +#define ACCESS_RW (ACCESS_RO | ACCESS_WO) +}; + +struct cpdma_control_info controls[] = { + [CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO}, + [CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL, 4, 1, ACCESS_RW}, + [CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL, 2, 1, ACCESS_RW}, + [CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL, 1, 1, ACCESS_RW}, + [CPDMA_TX_PRIO_FIXED] = {CPDMA_DMACONTROL, 0, 1, ACCESS_RW}, + [CPDMA_STAT_IDLE] = {CPDMA_DMASTATUS, 31, 1, ACCESS_RO}, + [CPDMA_STAT_TX_ERR_CODE] = {CPDMA_DMASTATUS, 20, 0xf, ACCESS_RW}, + [CPDMA_STAT_TX_ERR_CHAN] = {CPDMA_DMASTATUS, 16, 0x7, ACCESS_RW}, + [CPDMA_STAT_RX_ERR_CODE] = {CPDMA_DMASTATUS, 12, 0xf, ACCESS_RW}, + [CPDMA_STAT_RX_ERR_CHAN] = {CPDMA_DMASTATUS, 8, 0x7, ACCESS_RW}, + [CPDMA_RX_BUFFER_OFFSET] = {CPDMA_RXBUFFOFS, 0, 0xffff, ACCESS_RW}, +}; + +int cpdma_control_get(struct cpdma_ctlr *ctlr, int control) +{ + unsigned long flags; + struct cpdma_control_info *info = &controls[control]; + int ret; + + spin_lock_irqsave(&ctlr->lock, flags); + + ret = -ENOTSUPP; + if (!ctlr->params.has_ext_regs) + goto unlock_ret; + + ret = -EINVAL; + if (ctlr->state != CPDMA_STATE_ACTIVE) + goto unlock_ret; + + ret = -ENOENT; + if (control < 0 || control >= ARRAY_SIZE(controls)) + goto unlock_ret; + + ret = -EPERM; + if ((info->access & ACCESS_RO) != ACCESS_RO) + goto unlock_ret; + + ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask; + +unlock_ret: + spin_unlock_irqrestore(&ctlr->lock, flags); + return ret; +} + +int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value) +{ + unsigned long flags; + struct cpdma_control_info *info = &controls[control]; + int ret; + u32 val; + + spin_lock_irqsave(&ctlr->lock, flags); + + ret = -ENOTSUPP; + if (!ctlr->params.has_ext_regs) + goto unlock_ret; + + ret = -EINVAL; + if (ctlr->state != CPDMA_STATE_ACTIVE) + goto unlock_ret; + + ret = -ENOENT; + if (control < 0 || control >= ARRAY_SIZE(controls)) + goto unlock_ret; + + ret = -EPERM; + if ((info->access & ACCESS_WO) != ACCESS_WO) + goto unlock_ret; + + val = dma_reg_read(ctlr, info->reg); + val &= ~(info->mask << info->shift); + val |= (value & info->mask) << info->shift; + dma_reg_write(ctlr, info->reg, val); + ret = 0; + +unlock_ret: + spin_unlock_irqrestore(&ctlr->lock, flags); + return ret; +} diff --git a/drivers/net/davinci_cpdma.h b/drivers/net/davinci_cpdma.h new file mode 100644 index 0000000..868e50e --- /dev/null +++ b/drivers/net/davinci_cpdma.h @@ -0,0 +1,108 @@ +/* + * Texas Instruments CPDMA Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __DAVINCI_CPDMA_H__ +#define __DAVINCI_CPDMA_H__ + +#define CPDMA_MAX_CHANNELS BITS_PER_LONG + +#define tx_chan_num(chan) (chan) +#define rx_chan_num(chan) ((chan) + CPDMA_MAX_CHANNELS) +#define is_rx_chan(chan) ((chan)->chan_num >= CPDMA_MAX_CHANNELS) +#define is_tx_chan(chan) (!is_rx_chan(chan)) +#define __chan_linear(chan_num) ((chan_num) & (CPDMA_MAX_CHANNELS - 1)) +#define chan_linear(chan) __chan_linear((chan)->chan_num) + +struct cpdma_params { + struct device *dev; + void __iomem *dmaregs; + void __iomem *txhdp, *rxhdp, *txcp, *rxcp; + void __iomem *rxthresh, *rxfree; + int num_chan; + bool has_soft_reset; + int min_packet_size; + u32 desc_mem_phys; + int desc_mem_size; + int desc_align; + + /* + * Some instances of embedded cpdma controllers have extra control and + * status registers. The following flag enables access to these + * "extended" registers. + */ + bool has_ext_regs; +}; + +struct cpdma_chan_stats { + u32 head_enqueue; + u32 tail_enqueue; + u32 pad_enqueue; + u32 misqueued; + u32 desc_alloc_fail; + u32 pad_alloc_fail; + u32 runt_receive_buff; + u32 runt_transmit_buff; + u32 empty_dequeue; + u32 busy_dequeue; + u32 good_dequeue; + u32 requeue; + u32 teardown_dequeue; +}; + +struct cpdma_ctlr; +struct cpdma_chan; + +typedef void (*cpdma_handler_fn)(void *token, int len, int status); + +struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params); +int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_start(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr); +int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr); + +struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num, + cpdma_handler_fn handler); +int cpdma_chan_destroy(struct cpdma_chan *chan); +int cpdma_chan_start(struct cpdma_chan *chan); +int cpdma_chan_stop(struct cpdma_chan *chan); +int cpdma_chan_dump(struct cpdma_chan *chan); + +int cpdma_chan_get_stats(struct cpdma_chan *chan, + struct cpdma_chan_stats *stats); +int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, + int len, gfp_t gfp_mask); +int cpdma_chan_process(struct cpdma_chan *chan, int quota); + +int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable); +void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr); +int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable); + +enum cpdma_control { + CPDMA_CMD_IDLE, /* write-only */ + CPDMA_COPY_ERROR_FRAMES, /* read-write */ + CPDMA_RX_OFF_LEN_UPDATE, /* read-write */ + CPDMA_RX_OWNERSHIP_FLIP, /* read-write */ + CPDMA_TX_PRIO_FIXED, /* read-write */ + CPDMA_STAT_IDLE, /* read-only */ + CPDMA_STAT_TX_ERR_CHAN, /* read-only */ + CPDMA_STAT_TX_ERR_CODE, /* read-only */ + CPDMA_STAT_RX_ERR_CHAN, /* read-only */ + CPDMA_STAT_RX_ERR_CODE, /* read-only */ + CPDMA_RX_BUFFER_OFFSET, /* read-write */ +}; + +int cpdma_control_get(struct cpdma_ctlr *ctlr, int control); +int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value); + +#endif -- 1.7.0.4 From cyril at ti.com Wed Sep 15 09:11:30 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Wed, 15 Sep 2010 10:11:30 -0400 Subject: [PATCH v4 10/10] net: davinci_emac: cleanup unused cpdma code In-Reply-To: <1284559890-31346-1-git-send-email-cyril@ti.com> References: <1284559890-31346-1-git-send-email-cyril@ti.com> Message-ID: <1284559890-31346-11-git-send-email-cyril@ti.com> Having switched over to the newly introduced cpdma layer, this patch now removes a whole bunch of code that is now unused. This patch has been maintained separate strictly for reasons of readability. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- drivers/net/davinci_emac.c | 930 -------------------------------------------- 1 files changed, 0 insertions(+), 930 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 67dbcfb..2a628d1 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -127,7 +127,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; /* EMAC register related defines */ #define EMAC_ALL_MULTI_REG_VALUE (0xFFFFFFFF) #define EMAC_NUM_MULTICAST_BITS (64) -#define EMAC_TEARDOWN_VALUE (0xFFFFFFFC) #define EMAC_TX_CONTROL_TX_ENABLE_VAL (0x1) #define EMAC_RX_CONTROL_RX_ENABLE_VAL (0x1) #define EMAC_MAC_HOST_ERR_INTMASK_VAL (0x2) @@ -214,24 +213,10 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */ /* EMAC Peripheral Device Register Memory Layout structure */ -#define EMAC_TXIDVER 0x0 -#define EMAC_TXCONTROL 0x4 -#define EMAC_TXTEARDOWN 0x8 -#define EMAC_RXIDVER 0x10 -#define EMAC_RXCONTROL 0x14 -#define EMAC_RXTEARDOWN 0x18 -#define EMAC_TXINTSTATRAW 0x80 -#define EMAC_TXINTSTATMASKED 0x84 -#define EMAC_TXINTMASKSET 0x88 -#define EMAC_TXINTMASKCLEAR 0x8C #define EMAC_MACINVECTOR 0x90 #define EMAC_DM646X_MACEOIVECTOR 0x94 -#define EMAC_RXINTSTATRAW 0xA0 -#define EMAC_RXINTSTATMASKED 0xA4 -#define EMAC_RXINTMASKSET 0xA8 -#define EMAC_RXINTMASKCLEAR 0xAC #define EMAC_MACINTSTATRAW 0xB0 #define EMAC_MACINTSTATMASKED 0xB4 #define EMAC_MACINTMASKSET 0xB8 @@ -258,12 +243,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_MACADDRHI 0x504 #define EMAC_MACINDEX 0x508 -/* EMAC HDP and Completion registors */ -#define EMAC_TXHDP(ch) (0x600 + (ch * 4)) -#define EMAC_RXHDP(ch) (0x620 + (ch * 4)) -#define EMAC_TXCP(ch) (0x640 + (ch * 4)) -#define EMAC_RXCP(ch) (0x660 + (ch * 4)) - /* EMAC statistics registers */ #define EMAC_RXGOODFRAMES 0x200 #define EMAC_RXBCASTFRAMES 0x204 @@ -328,120 +307,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; /* EMAC Stats Clear Mask */ #define EMAC_STATS_CLR_MASK (0xFFFFFFFF) -/** net_buf_obj: EMAC network bufferdata structure - * - * EMAC network buffer data structure - */ -struct emac_netbufobj { - void *buf_token; - char *data_ptr; - int length; -}; - -/** net_pkt_obj: EMAC network packet data structure - * - * EMAC network packet data structure - supports buffer list (for future) - */ -struct emac_netpktobj { - void *pkt_token; /* data token may hold tx/rx chan id */ - struct emac_netbufobj *buf_list; /* array of network buffer objects */ - int num_bufs; - int pkt_length; -}; - -/** emac_tx_bd: EMAC TX Buffer descriptor data structure - * - * EMAC TX Buffer descriptor data structure - */ -struct emac_tx_bd { - int h_next; - int buff_ptr; - int off_b_len; - int mode; /* SOP, EOP, ownership, EOQ, teardown,Qstarv, length */ - struct emac_tx_bd __iomem *next; - void *buf_token; -}; - -/** emac_txch: EMAC TX Channel data structure - * - * EMAC TX Channel data structure - */ -struct emac_txch { - /* Config related */ - u32 num_bd; - u32 service_max; - - /* CPPI specific */ - u32 alloc_size; - void __iomem *bd_mem; - struct emac_tx_bd __iomem *bd_pool_head; - struct emac_tx_bd __iomem *active_queue_head; - struct emac_tx_bd __iomem *active_queue_tail; - struct emac_tx_bd __iomem *last_hw_bdprocessed; - u32 queue_active; - u32 teardown_pending; - u32 *tx_complete; - - /** statistics */ - u32 proc_count; /* TX: # of times emac_tx_bdproc is called */ - u32 mis_queued_packets; - u32 queue_reinit; - u32 end_of_queue_add; - u32 out_of_tx_bd; - u32 no_active_pkts; /* IRQ when there were no packets to process */ - u32 active_queue_count; -}; - -/** emac_rx_bd: EMAC RX Buffer descriptor data structure - * - * EMAC RX Buffer descriptor data structure - */ -struct emac_rx_bd { - int h_next; - int buff_ptr; - int off_b_len; - int mode; - struct emac_rx_bd __iomem *next; - void *data_ptr; - void *buf_token; -}; - -/** emac_rxch: EMAC RX Channel data structure - * - * EMAC RX Channel data structure - */ -struct emac_rxch { - /* configuration info */ - u32 num_bd; - u32 service_max; - u32 buf_size; - char mac_addr[6]; - - /** CPPI specific */ - u32 alloc_size; - void __iomem *bd_mem; - struct emac_rx_bd __iomem *bd_pool_head; - struct emac_rx_bd __iomem *active_queue_head; - struct emac_rx_bd __iomem *active_queue_tail; - u32 queue_active; - u32 teardown_pending; - - /* packet and buffer objects */ - struct emac_netpktobj pkt_queue; - struct emac_netbufobj buf_queue; - - /** statistics */ - u32 proc_count; /* number of times emac_rx_bdproc is called */ - u32 processed_bd; - u32 recycled_bd; - u32 out_of_rx_bd; - u32 out_of_rx_buffers; - u32 queue_reinit; - u32 end_of_queue_add; - u32 end_of_queue; - u32 mis_queued_packets; -}; - /* emac_priv: EMAC private data structure * * EMAC adapter private data structure @@ -452,17 +317,10 @@ struct emac_priv { struct platform_device *pdev; struct napi_struct napi; char mac_addr[6]; - spinlock_t tx_lock; - spinlock_t rx_lock; void __iomem *remap_addr; u32 emac_base_phys; void __iomem *emac_base; void __iomem *ctrl_base; - void __iomem *emac_ctrl_ram; - u32 ctrl_ram_size; - u32 hw_ram_addr; - struct emac_txch *txch[EMAC_DEF_MAX_TX_CH]; - struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH]; struct cpdma_ctlr *dma; struct cpdma_chan *txchan; struct cpdma_chan *rxchan; @@ -491,18 +349,6 @@ struct emac_priv { static struct clk *emac_clk; static unsigned long emac_bus_frequency; -#define emac_virt_to_phys(addr, priv) \ - (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \ - + priv->hw_ram_addr) - -/* Cache macros - Packet buffers would be from skb pool which is cached */ -#define EMAC_VIRT_NOCACHE(addr) (addr) - -/* DM644x does not have BD's in cached memory - so no cache functions */ -#define BD_CACHE_INVALIDATE(addr, size) -#define BD_CACHE_WRITEBACK(addr, size) -#define BD_CACHE_WRITEBACK_INVALIDATE(addr, size) - /* EMAC TX Host Error description strings */ static char *emac_txhost_errcodes[16] = { "No error", "SOP error", "Ownership bit not set in SOP buffer", @@ -545,20 +391,6 @@ static void emac_dump_regs(struct emac_priv *priv) emac_ctrl_read(EMAC_CTRL_EWCTL), emac_ctrl_read(EMAC_CTRL_EWINTTCNT)); } - dev_info(emac_dev, "EMAC: TXID: %08X %s, RXID: %08X %s\n", - emac_read(EMAC_TXIDVER), - ((emac_read(EMAC_TXCONTROL)) ? "enabled" : "disabled"), - emac_read(EMAC_RXIDVER), - ((emac_read(EMAC_RXCONTROL)) ? "enabled" : "disabled")); - dev_info(emac_dev, "EMAC: TXIntRaw:%08X, TxIntMasked: %08X, "\ - "TxIntMasSet: %08X\n", emac_read(EMAC_TXINTSTATRAW), - emac_read(EMAC_TXINTSTATMASKED), emac_read(EMAC_TXINTMASKSET)); - dev_info(emac_dev, "EMAC: RXIntRaw:%08X, RxIntMasked: %08X, "\ - "RxIntMasSet: %08X\n", emac_read(EMAC_RXINTSTATRAW), - emac_read(EMAC_RXINTSTATMASKED), emac_read(EMAC_RXINTMASKSET)); - dev_info(emac_dev, "EMAC: MacIntRaw:%08X, MacIntMasked: %08X, "\ - "MacInVector=%08X\n", emac_read(EMAC_MACINTSTATRAW), - emac_read(EMAC_MACINTSTATMASKED), emac_read(EMAC_MACINVECTOR)); dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n", emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL)); dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\ @@ -567,8 +399,6 @@ static void emac_dump_regs(struct emac_priv *priv) dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\ "MacConfig=%08X\n", emac_read(EMAC_MACCONTROL), emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG)); - dev_info(emac_dev, "EMAC: TXHDP[0]:%08X, RXHDP[0]: %08X\n", - emac_read(EMAC_TXHDP(0)), emac_read(EMAC_RXHDP(0))); dev_info(emac_dev, "EMAC Statistics\n"); dev_info(emac_dev, "EMAC: rx_good_frames:%d\n", emac_read(EMAC_RXGOODFRAMES)); @@ -1223,373 +1053,6 @@ static void emac_tx_handler(void *token, int len, int status) dev_kfree_skb_any(skb); } -/** EMAC on-chip buffer descriptor memory - * - * WARNING: Please note that the on chip memory is used for both TX and RX - * buffer descriptor queues and is equally divided between TX and RX desc's - * If the number of TX or RX descriptors change this memory pointers need - * to be adjusted. If external memory is allocated then these pointers can - * pointer to the memory - * - */ -#define EMAC_TX_BD_MEM(priv) ((priv)->emac_ctrl_ram) -#define EMAC_RX_BD_MEM(priv) ((priv)->emac_ctrl_ram + \ - (((priv)->ctrl_ram_size) >> 1)) - -/** - * emac_init_txch: TX channel initialization - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device init to setup a TX channel (allocate buffer desc - * create free pool and keep ready for transmission - * - * Returns success(0) or mem alloc failures error code - */ -static int emac_init_txch(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 cnt, bd_size; - void __iomem *mem; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch = NULL; - - txch = kzalloc(sizeof(struct emac_txch), GFP_KERNEL); - if (NULL == txch) { - dev_err(emac_dev, "DaVinci EMAC: TX Ch mem alloc failed"); - return -ENOMEM; - } - priv->txch[ch] = txch; - txch->service_max = EMAC_DEF_TX_MAX_SERVICE; - txch->active_queue_head = NULL; - txch->active_queue_tail = NULL; - txch->queue_active = 0; - txch->teardown_pending = 0; - - /* allocate memory for TX CPPI channel on a 4 byte boundry */ - txch->tx_complete = kzalloc(txch->service_max * sizeof(u32), - GFP_KERNEL); - if (NULL == txch->tx_complete) { - dev_err(emac_dev, "DaVinci EMAC: Tx service mem alloc failed"); - kfree(txch); - return -ENOMEM; - } - - /* allocate buffer descriptor pool align every BD on four word - * boundry for future requirements */ - bd_size = (sizeof(struct emac_tx_bd) + 0xF) & ~0xF; - txch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; - txch->alloc_size = (((bd_size * txch->num_bd) + 0xF) & ~0xF); - - /* alloc TX BD memory */ - txch->bd_mem = EMAC_TX_BD_MEM(priv); - __memzero((void __force *)txch->bd_mem, txch->alloc_size); - - /* initialize the BD linked list */ - mem = (void __force __iomem *) - (((u32 __force) txch->bd_mem + 0xF) & ~0xF); - txch->bd_pool_head = NULL; - for (cnt = 0; cnt < txch->num_bd; cnt++) { - curr_bd = mem + (cnt * bd_size); - curr_bd->next = txch->bd_pool_head; - txch->bd_pool_head = curr_bd; - } - - /* reset statistics counters */ - txch->out_of_tx_bd = 0; - txch->no_active_pkts = 0; - txch->active_queue_count = 0; - - return 0; -} - -/** - * emac_cleanup_txch: Book-keep function to clean TX channel resources - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to clean up TX channel resources - * - */ -static void emac_cleanup_txch(struct emac_priv *priv, u32 ch) -{ - struct emac_txch *txch = priv->txch[ch]; - - if (txch) { - if (txch->bd_mem) - txch->bd_mem = NULL; - kfree(txch->tx_complete); - kfree(txch); - priv->txch[ch] = NULL; - } -} - -/** - * emac_net_tx_complete: TX packet completion function - * @priv: The DaVinci EMAC private adapter structure - * @net_data_tokens: packet token - skb pointer - * @num_tokens: number of skb's to free - * @ch: TX channel number - * - * Frees the skb once packet is transmitted - * - */ -static int emac_net_tx_complete(struct emac_priv *priv, - void **net_data_tokens, - int num_tokens, u32 ch) -{ - struct net_device *ndev = priv->ndev; - u32 cnt; - - if (unlikely(num_tokens && netif_queue_stopped(ndev))) - netif_start_queue(ndev); - for (cnt = 0; cnt < num_tokens; cnt++) { - struct sk_buff *skb = (struct sk_buff *)net_data_tokens[cnt]; - if (skb == NULL) - continue; - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += skb->len; - dev_kfree_skb_any(skb); - } - return 0; -} - -/** - * emac_txch_teardown: TX channel teardown - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to teardown TX channel - * - */ -static void emac_txch_teardown(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ - struct emac_txch *txch = priv->txch[ch]; - struct emac_tx_bd __iomem *curr_bd; - - while ((emac_read(EMAC_TXCP(ch)) & EMAC_TEARDOWN_VALUE) != - EMAC_TEARDOWN_VALUE) { - /* wait till tx teardown complete */ - cpu_relax(); /* TODO: check if this helps ... */ - --teardown_cnt; - if (0 == teardown_cnt) { - dev_err(emac_dev, "EMAC: TX teardown aborted\n"); - break; - } - } - emac_write(EMAC_TXCP(ch), EMAC_TEARDOWN_VALUE); - - /* process sent packets and return skb's to upper layer */ - if (1 == txch->queue_active) { - curr_bd = txch->active_queue_head; - while (curr_bd != NULL) { - dma_unmap_single(emac_dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_TO_DEVICE); - - emac_net_tx_complete(priv, (void __force *) - &curr_bd->buf_token, 1, ch); - if (curr_bd != txch->active_queue_tail) - curr_bd = curr_bd->next; - else - break; - } - txch->bd_pool_head = txch->active_queue_head; - txch->active_queue_head = - txch->active_queue_tail = NULL; - } -} - -/** - * emac_stop_txch: Stop TX channel operation - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number - * - * Called to stop TX channel operation - * - */ -static void emac_stop_txch(struct emac_priv *priv, u32 ch) -{ - struct emac_txch *txch = priv->txch[ch]; - - if (txch) { - txch->teardown_pending = 1; - emac_write(EMAC_TXTEARDOWN, 0); - emac_txch_teardown(priv, ch); - txch->teardown_pending = 0; - emac_write(EMAC_TXINTMASKCLEAR, BIT(ch)); - } -} - -/** - * emac_tx_bdproc: TX buffer descriptor (packet) processing - * @priv: The DaVinci EMAC private adapter structure - * @ch: TX channel number to process buffer descriptors for - * @budget: number of packets allowed to process - * @pending: indication to caller that packets are pending to process - * - * Processes TX buffer descriptors after packets are transmitted - checks - * ownership bit on the TX * descriptor and requeues it to free pool & frees - * the SKB buffer. Only "budget" number of packets are processed and - * indication of pending packets provided to the caller - * - * Returns number of packets processed - */ -static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) -{ - struct device *emac_dev = &priv->ndev->dev; - unsigned long flags; - u32 frame_status; - u32 pkts_processed = 0; - u32 tx_complete_cnt = 0; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch = priv->txch[ch]; - u32 *tx_complete_ptr = txch->tx_complete; - - if (unlikely(1 == txch->teardown_pending)) { - if (netif_msg_tx_err(priv) && net_ratelimit()) { - dev_err(emac_dev, "DaVinci EMAC:emac_tx_bdproc: "\ - "teardown pending\n"); - } - return 0; /* dont handle any pkt completions */ - } - - ++txch->proc_count; - spin_lock_irqsave(&priv->tx_lock, flags); - curr_bd = txch->active_queue_head; - if (NULL == curr_bd) { - emac_write(EMAC_TXCP(ch), - emac_virt_to_phys(txch->last_hw_bdprocessed, priv)); - txch->no_active_pkts++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return 0; - } - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - while ((curr_bd) && - ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && - (pkts_processed < budget)) { - emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd, priv)); - txch->active_queue_head = curr_bd->next; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - if (curr_bd->next) { /* misqueued packet */ - emac_write(EMAC_TXHDP(ch), curr_bd->h_next); - ++txch->mis_queued_packets; - } else { - txch->queue_active = 0; /* end of queue */ - } - } - - dma_unmap_single(emac_dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_TO_DEVICE); - - *tx_complete_ptr = (u32) curr_bd->buf_token; - ++tx_complete_ptr; - ++tx_complete_cnt; - curr_bd->next = txch->bd_pool_head; - txch->bd_pool_head = curr_bd; - --txch->active_queue_count; - pkts_processed++; - txch->last_hw_bdprocessed = curr_bd; - curr_bd = txch->active_queue_head; - if (curr_bd) { - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - } - } /* end of pkt processing loop */ - - emac_net_tx_complete(priv, - (void *)&txch->tx_complete[0], - tx_complete_cnt, ch); - spin_unlock_irqrestore(&priv->tx_lock, flags); - return pkts_processed; -} - -#define EMAC_ERR_TX_OUT_OF_BD -1 - -/** - * emac_send: EMAC Transmit function (internal) - * @priv: The DaVinci EMAC private adapter structure - * @pkt: packet pointer (contains skb ptr) - * @ch: TX channel number - * - * Called by the transmit function to queue the packet in EMAC hardware queue - * - * Returns success(0) or error code (typically out of desc's) - */ -static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch) -{ - unsigned long flags; - struct emac_tx_bd __iomem *curr_bd; - struct emac_txch *txch; - struct emac_netbufobj *buf_list; - - txch = priv->txch[ch]; - buf_list = pkt->buf_list; /* get handle to the buffer array */ - - /* check packet size and pad if short */ - if (pkt->pkt_length < EMAC_DEF_MIN_ETHPKTSIZE) { - buf_list->length += (EMAC_DEF_MIN_ETHPKTSIZE - pkt->pkt_length); - pkt->pkt_length = EMAC_DEF_MIN_ETHPKTSIZE; - } - - spin_lock_irqsave(&priv->tx_lock, flags); - curr_bd = txch->bd_pool_head; - if (curr_bd == NULL) { - txch->out_of_tx_bd++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return EMAC_ERR_TX_OUT_OF_BD; - } - - txch->bd_pool_head = curr_bd->next; - curr_bd->buf_token = buf_list->buf_token; - curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buf_list->data_ptr, - buf_list->length, DMA_TO_DEVICE); - curr_bd->off_b_len = buf_list->length; - curr_bd->h_next = 0; - curr_bd->next = NULL; - curr_bd->mode = (EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT | - EMAC_CPPI_EOP_BIT | pkt->pkt_length); - - /* flush the packet from cache if write back cache is present */ - BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - - /* send the packet */ - if (txch->active_queue_head == NULL) { - txch->active_queue_head = curr_bd; - txch->active_queue_tail = curr_bd; - if (1 != txch->queue_active) { - emac_write(EMAC_TXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - txch->queue_active = 1; - } - ++txch->queue_reinit; - } else { - register struct emac_tx_bd __iomem *tail_bd; - register u32 frame_status; - - tail_bd = txch->active_queue_tail; - tail_bd->next = curr_bd; - txch->active_queue_tail = curr_bd; - tail_bd = EMAC_VIRT_NOCACHE(tail_bd); - tail_bd->h_next = (int)emac_virt_to_phys(curr_bd, priv); - frame_status = tail_bd->mode; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - emac_write(EMAC_TXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - frame_status &= ~(EMAC_CPPI_EOQ_BIT); - tail_bd->mode = frame_status; - ++txch->end_of_queue_add; - } - } - txch->active_queue_count++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - return 0; -} - /** * emac_dev_xmit: EMAC Transmit function * @skb: SKB pointer @@ -1664,207 +1127,6 @@ static void emac_dev_tx_timeout(struct net_device *ndev) } /** - * emac_net_alloc_rx_buf: Allocate a skb for RX - * @priv: The DaVinci EMAC private adapter structure - * @buf_size: size of SKB data buffer to allocate - * @data_token: data token returned (skb handle for storing in buffer desc) - * @ch: RX channel number - * - * Called during RX channel setup - allocates skb buffer of required size - * and provides the skb handle and allocated buffer data pointer to caller - * - * Returns skb data pointer or 0 on failure to alloc skb - */ -static void *emac_net_alloc_rx_buf(struct emac_priv *priv, int buf_size, - void **data_token, u32 ch) -{ - struct net_device *ndev = priv->ndev; - struct device *emac_dev = &ndev->dev; - struct sk_buff *p_skb; - - p_skb = dev_alloc_skb(buf_size); - if (unlikely(NULL == p_skb)) { - if (netif_msg_rx_err(priv) && net_ratelimit()) - dev_err(emac_dev, "DaVinci EMAC: failed to alloc skb"); - return NULL; - } - - /* set device pointer in skb and reserve space for extra bytes */ - p_skb->dev = ndev; - skb_reserve(p_skb, NET_IP_ALIGN); - *data_token = (void *) p_skb; - return p_skb->data; -} - -/** - * emac_init_rxch: RX channel initialization - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * @param: mac address for RX channel - * - * Called during device init to setup a RX channel (allocate buffers and - * buffer descriptors, create queue and keep ready for reception - * - * Returns success(0) or mem alloc failures error code - */ -static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 cnt, bd_size; - void __iomem *mem; - struct emac_rx_bd __iomem *curr_bd; - struct emac_rxch *rxch = NULL; - - rxch = kzalloc(sizeof(struct emac_rxch), GFP_KERNEL); - if (NULL == rxch) { - dev_err(emac_dev, "DaVinci EMAC: RX Ch mem alloc failed"); - return -ENOMEM; - } - priv->rxch[ch] = rxch; - rxch->buf_size = priv->rx_buf_size; - rxch->service_max = EMAC_DEF_RX_MAX_SERVICE; - rxch->queue_active = 0; - rxch->teardown_pending = 0; - - /* save mac address */ - for (cnt = 0; cnt < 6; cnt++) - rxch->mac_addr[cnt] = param[cnt]; - - /* allocate buffer descriptor pool align every BD on four word - * boundry for future requirements */ - bd_size = (sizeof(struct emac_rx_bd) + 0xF) & ~0xF; - rxch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size; - rxch->alloc_size = (((bd_size * rxch->num_bd) + 0xF) & ~0xF); - rxch->bd_mem = EMAC_RX_BD_MEM(priv); - __memzero((void __force *)rxch->bd_mem, rxch->alloc_size); - rxch->pkt_queue.buf_list = &rxch->buf_queue; - - /* allocate RX buffer and initialize the BD linked list */ - mem = (void __force __iomem *) - (((u32 __force) rxch->bd_mem + 0xF) & ~0xF); - rxch->active_queue_head = NULL; - rxch->active_queue_tail = mem; - for (cnt = 0; cnt < rxch->num_bd; cnt++) { - curr_bd = mem + (cnt * bd_size); - /* for future use the last parameter contains the BD ptr */ - curr_bd->data_ptr = emac_net_alloc_rx_buf(priv, - rxch->buf_size, - (void __force **)&curr_bd->buf_token, - EMAC_DEF_RX_CH); - if (curr_bd->data_ptr == NULL) { - dev_err(emac_dev, "DaVinci EMAC: RX buf mem alloc " \ - "failed for ch %d\n", ch); - kfree(rxch); - return -ENOMEM; - } - - /* populate the hardware descriptor */ - curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head, - priv); - curr_bd->buff_ptr = dma_map_single(emac_dev, curr_bd->data_ptr, - rxch->buf_size, DMA_FROM_DEVICE); - curr_bd->off_b_len = rxch->buf_size; - curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; - - /* write back to hardware memory */ - BD_CACHE_WRITEBACK_INVALIDATE((u32) curr_bd, - EMAC_BD_LENGTH_FOR_CACHE); - curr_bd->next = rxch->active_queue_head; - rxch->active_queue_head = curr_bd; - } - - /* At this point rxCppi->activeQueueHead points to the first - RX BD ready to be given to RX HDP and rxch->active_queue_tail - points to the last RX BD - */ - return 0; -} - -/** - * emac_rxch_teardown: RX channel teardown - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to teardown RX channel - * - */ -static void emac_rxch_teardown(struct emac_priv *priv, u32 ch) -{ - struct device *emac_dev = &priv->ndev->dev; - u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */ - - while ((emac_read(EMAC_RXCP(ch)) & EMAC_TEARDOWN_VALUE) != - EMAC_TEARDOWN_VALUE) { - /* wait till tx teardown complete */ - cpu_relax(); /* TODO: check if this helps ... */ - --teardown_cnt; - if (0 == teardown_cnt) { - dev_err(emac_dev, "EMAC: RX teardown aborted\n"); - break; - } - } - emac_write(EMAC_RXCP(ch), EMAC_TEARDOWN_VALUE); -} - -/** - * emac_stop_rxch: Stop RX channel operation - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to stop RX channel operation - * - */ -static void emac_stop_rxch(struct emac_priv *priv, u32 ch) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - - if (rxch) { - rxch->teardown_pending = 1; - emac_write(EMAC_RXTEARDOWN, ch); - /* wait for teardown complete */ - emac_rxch_teardown(priv, ch); - rxch->teardown_pending = 0; - emac_write(EMAC_RXINTMASKCLEAR, BIT(ch)); - } -} - -/** - * emac_cleanup_rxch: Book-keep function to clean RX channel resources - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number - * - * Called during device stop to clean up RX channel resources - * - */ -static void emac_cleanup_rxch(struct emac_priv *priv, u32 ch) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - struct emac_rx_bd __iomem *curr_bd; - - if (rxch) { - /* free the receive buffers previously allocated */ - curr_bd = rxch->active_queue_head; - while (curr_bd) { - if (curr_bd->buf_token) { - dma_unmap_single(&priv->ndev->dev, - curr_bd->buff_ptr, - curr_bd->off_b_len - & EMAC_RX_BD_BUF_SIZE, - DMA_FROM_DEVICE); - - dev_kfree_skb_any((struct sk_buff *)\ - curr_bd->buf_token); - } - curr_bd = curr_bd->next; - } - if (rxch->bd_mem) - rxch->bd_mem = NULL; - kfree(rxch); - priv->rxch[ch] = NULL; - } -} - -/** * emac_set_type0addr: Set EMAC Type0 mac address * @priv: The DaVinci EMAC private adapter structure * @ch: RX channel number @@ -2004,194 +1266,6 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) } /** - * emac_addbd_to_rx_queue: Recycle RX buffer descriptor - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number to process buffer descriptors for - * @curr_bd: current buffer descriptor - * @buffer: buffer pointer for descriptor - * @buf_token: buffer token (stores skb information) - * - * Prepares the recycled buffer descriptor and addes it to hardware - * receive queue - if queue empty this descriptor becomes the head - * else addes the descriptor to end of queue - * - */ -static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch, - struct emac_rx_bd __iomem *curr_bd, - char *buffer, void *buf_token) -{ - struct emac_rxch *rxch = priv->rxch[ch]; - - /* populate the hardware descriptor */ - curr_bd->h_next = 0; - curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buffer, - rxch->buf_size, DMA_FROM_DEVICE); - curr_bd->off_b_len = rxch->buf_size; - curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT; - curr_bd->next = NULL; - curr_bd->data_ptr = buffer; - curr_bd->buf_token = buf_token; - - /* write back */ - BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - if (rxch->active_queue_head == NULL) { - rxch->active_queue_head = curr_bd; - rxch->active_queue_tail = curr_bd; - if (0 != rxch->queue_active) { - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(rxch->active_queue_head, priv)); - rxch->queue_active = 1; - } - } else { - struct emac_rx_bd __iomem *tail_bd; - u32 frame_status; - - tail_bd = rxch->active_queue_tail; - rxch->active_queue_tail = curr_bd; - tail_bd->next = curr_bd; - tail_bd = EMAC_VIRT_NOCACHE(tail_bd); - tail_bd->h_next = emac_virt_to_phys(curr_bd, priv); - frame_status = tail_bd->mode; - if (frame_status & EMAC_CPPI_EOQ_BIT) { - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - frame_status &= ~(EMAC_CPPI_EOQ_BIT); - tail_bd->mode = frame_status; - ++rxch->end_of_queue_add; - } - } - ++rxch->recycled_bd; -} - -/** - * emac_net_rx_cb: Prepares packet and sends to upper layer - * @priv: The DaVinci EMAC private adapter structure - * @net_pkt_list: Network packet list (received packets) - * - * Invalidates packet buffer memory and sends the received packet to upper - * layer - * - * Returns success or appropriate error code (none as of now) - */ -static int emac_net_rx_cb(struct emac_priv *priv, - struct emac_netpktobj *net_pkt_list) -{ - struct net_device *ndev = priv->ndev; - struct sk_buff *p_skb = net_pkt_list->pkt_token; - /* set length of packet */ - skb_put(p_skb, net_pkt_list->pkt_length); - p_skb->protocol = eth_type_trans(p_skb, priv->ndev); - netif_receive_skb(p_skb); - ndev->stats.rx_bytes += net_pkt_list->pkt_length; - ndev->stats.rx_packets++; - return 0; -} - -/** - * emac_rx_bdproc: RX buffer descriptor (packet) processing - * @priv: The DaVinci EMAC private adapter structure - * @ch: RX channel number to process buffer descriptors for - * @budget: number of packets allowed to process - * @pending: indication to caller that packets are pending to process - * - * Processes RX buffer descriptors - checks ownership bit on the RX buffer - * descriptor, sends the receive packet to upper layer, allocates a new SKB - * and recycles the buffer descriptor (requeues it in hardware RX queue). - * Only "budget" number of packets are processed and indication of pending - * packets provided to the caller. - * - * Returns number of packets processed (and indication of pending packets) - */ -static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) -{ - unsigned long flags; - u32 frame_status; - u32 pkts_processed = 0; - char *new_buffer; - struct emac_rx_bd __iomem *curr_bd; - struct emac_rx_bd __iomem *last_bd; - struct emac_netpktobj *curr_pkt, pkt_obj; - struct emac_netbufobj buf_obj; - struct emac_netbufobj *rx_buf_obj; - void *new_buf_token; - struct emac_rxch *rxch = priv->rxch[ch]; - - if (unlikely(1 == rxch->teardown_pending)) - return 0; - ++rxch->proc_count; - spin_lock_irqsave(&priv->rx_lock, flags); - pkt_obj.buf_list = &buf_obj; - curr_pkt = &pkt_obj; - curr_bd = rxch->active_queue_head; - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - - while ((curr_bd) && - ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) && - (pkts_processed < budget)) { - - new_buffer = emac_net_alloc_rx_buf(priv, rxch->buf_size, - &new_buf_token, EMAC_DEF_RX_CH); - if (unlikely(NULL == new_buffer)) { - ++rxch->out_of_rx_buffers; - goto end_emac_rx_bdproc; - } - - /* populate received packet data structure */ - rx_buf_obj = &curr_pkt->buf_list[0]; - rx_buf_obj->data_ptr = (char *)curr_bd->data_ptr; - rx_buf_obj->length = curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE; - rx_buf_obj->buf_token = curr_bd->buf_token; - - dma_unmap_single(&priv->ndev->dev, curr_bd->buff_ptr, - curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE, - DMA_FROM_DEVICE); - - curr_pkt->pkt_token = curr_pkt->buf_list->buf_token; - curr_pkt->num_bufs = 1; - curr_pkt->pkt_length = - (frame_status & EMAC_RX_BD_PKT_LENGTH_MASK); - emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd, priv)); - ++rxch->processed_bd; - last_bd = curr_bd; - curr_bd = last_bd->next; - rxch->active_queue_head = curr_bd; - - /* check if end of RX queue ? */ - if (frame_status & EMAC_CPPI_EOQ_BIT) { - if (curr_bd) { - ++rxch->mis_queued_packets; - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(curr_bd, priv)); - } else { - ++rxch->end_of_queue; - rxch->queue_active = 0; - } - } - - /* recycle BD */ - emac_addbd_to_rx_queue(priv, ch, last_bd, new_buffer, - new_buf_token); - - /* return the packet to the user - BD ptr passed in - * last parameter for potential *future* use */ - spin_unlock_irqrestore(&priv->rx_lock, flags); - emac_net_rx_cb(priv, curr_pkt); - spin_lock_irqsave(&priv->rx_lock, flags); - curr_bd = rxch->active_queue_head; - if (curr_bd) { - BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE); - frame_status = curr_bd->mode; - } - ++pkts_processed; - } - -end_emac_rx_bdproc: - spin_unlock_irqrestore(&priv->rx_lock, flags); - return pkts_processed; -} - -/** * emac_hw_enable: Enable EMAC hardware for packet transmission/reception * @priv: The DaVinci EMAC private adapter structure * @@ -2717,8 +1791,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->ndev = ndev; priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG); - spin_lock_init(&priv->tx_lock); - spin_lock_init(&priv->rx_lock); spin_lock_init(&priv->lock); pdata = pdev->dev.platform_data; @@ -2766,8 +1838,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) ndev->base_addr = (unsigned long)priv->remap_addr; priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset; - priv->ctrl_ram_size = pdata->ctrl_ram_size; - priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset; hw_ram_addr = pdata->hw_ram_addr; if (!hw_ram_addr) -- 1.7.0.4 From cyril at ti.com Wed Sep 15 09:11:26 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Wed, 15 Sep 2010 10:11:26 -0400 Subject: [PATCH v4 06/10] omap: cleanup unused davinci mdio arch code In-Reply-To: <1284559890-31346-1-git-send-email-cyril@ti.com> References: <1284559890-31346-1-git-send-email-cyril@ti.com> Message-ID: <1284559890-31346-7-git-send-email-cyril@ti.com> This patch removes davinci architecture code that has now been rendered useless by the previous patches in the MDIO separation series. Signed-off-by: Cyril Chemparathy Acked-by: David S. Miller Acked-by: Tony Lindgren --- arch/arm/mach-omap2/board-am3517evm.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 5dd1b73..5225df6 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -39,7 +39,6 @@ #include "mux.h" -#define AM35XX_EVM_PHY_MASK (0xF) #define AM35XX_EVM_MDIO_FREQUENCY (1000000) static struct mdio_platform_data am3517_evm_mdio_pdata = { @@ -64,8 +63,6 @@ static struct platform_device am3517_mdio_device = { }; static struct emac_platform_data am3517_evm_emac_pdata = { - .phy_mask = AM35XX_EVM_PHY_MASK, - .mdio_max_freq = AM35XX_EVM_MDIO_FREQUENCY, .rmii_en = 1, }; @@ -135,7 +132,6 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata) pdata->ctrl_reg_offset = AM35XX_EMAC_CNTRL_OFFSET; pdata->ctrl_mod_reg_offset = AM35XX_EMAC_CNTRL_MOD_OFFSET; pdata->ctrl_ram_offset = AM35XX_EMAC_CNTRL_RAM_OFFSET; - pdata->mdio_reg_offset = AM35XX_EMAC_MDIO_OFFSET; pdata->ctrl_ram_size = AM35XX_EMAC_CNTRL_RAM_SIZE; pdata->version = EMAC_VERSION_2; pdata->hw_ram_addr = AM35XX_EMAC_HW_RAM_ADDR; -- 1.7.0.4 From cyril at ti.com Wed Sep 15 09:11:29 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Wed, 15 Sep 2010 10:11:29 -0400 Subject: [PATCH v4 09/10] net: davinci_emac: switch to new cpdma layer In-Reply-To: <1284559890-31346-1-git-send-email-cyril@ti.com> References: <1284559890-31346-1-git-send-email-cyril@ti.com> Message-ID: <1284559890-31346-10-git-send-email-cyril@ti.com> This patch hooks up the emac driver with the newly separated cpdma driver. Key differences introduced here: - The old buffer list scheme is no longer required - The original code maintained mac address per rx channel, even if only one rx channel was being used. With this change, mac address is maintained device wide. If support for multiple rx channels is added in future, this will need to be reworked a bit. - The new CPDMA code handles short packets better than before. The earlier code was adjusting the length up, without ensuring that the tail end of the padding was cleared - a possible security issue. This has been fixed to use skb_padto(). Signed-off-by: Cyril Chemparathy Tested-by: Michael Williamson Tested-by: Caglar Akyuz --- drivers/net/davinci_emac.c | 249 +++++++++++++++++++++++++++++--------------- 1 files changed, 164 insertions(+), 85 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index d4298cb..67dbcfb 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -63,6 +63,8 @@ #include #include +#include "davinci_cpdma.h" + static int debug_level; module_param(debug_level, int, 0); MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)"); @@ -113,6 +115,7 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1"; #define EMAC_DEF_MAX_FRAME_SIZE (1500 + 14 + 4 + 4) #define EMAC_DEF_TX_CH (0) /* Default 0th channel */ #define EMAC_DEF_RX_CH (0) /* Default 0th channel */ +#define EMAC_DEF_RX_NUM_DESC (128) #define EMAC_DEF_MAX_TX_CH (1) /* Max TX channels configured */ #define EMAC_DEF_MAX_RX_CH (1) /* Max RX channels configured */ #define EMAC_POLL_WEIGHT (64) /* Default NAPI poll weight */ @@ -460,6 +463,9 @@ struct emac_priv { u32 hw_ram_addr; struct emac_txch *txch[EMAC_DEF_MAX_TX_CH]; struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH]; + struct cpdma_ctlr *dma; + struct cpdma_chan *txchan; + struct cpdma_chan *rxchan; u32 link; /* 1=link on, 0=link off */ u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */ u32 duplex; /* Link duplex: 0=Half, 1=Full */ @@ -624,6 +630,8 @@ static void emac_dump_regs(struct emac_priv *priv) emac_read(EMAC_RXMOFOVERRUNS)); dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n", emac_read(EMAC_RXDMAOVERRUNS)); + + cpdma_ctlr_dump(priv->dma); } /** @@ -1151,6 +1159,70 @@ static irqreturn_t emac_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static struct sk_buff *emac_rx_alloc(struct emac_priv *priv) +{ + struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size); + if (WARN_ON(!skb)) + return NULL; + skb->dev = priv->ndev; + skb_reserve(skb, NET_IP_ALIGN); + return skb; +} + +static void emac_rx_handler(void *token, int len, int status) +{ + struct sk_buff *skb = token; + struct net_device *ndev = skb->dev; + struct emac_priv *priv = netdev_priv(ndev); + struct device *emac_dev = &ndev->dev; + int ret; + + /* free and bail if we are shutting down */ + if (unlikely(!netif_running(ndev))) { + dev_kfree_skb_any(skb); + return; + } + + /* recycle on recieve error */ + if (status < 0) { + ndev->stats.rx_errors++; + goto recycle; + } + + /* feed received packet up the stack */ + skb_put(skb, len); + skb->protocol = eth_type_trans(skb, ndev); + netif_receive_skb(skb); + ndev->stats.rx_bytes += len; + ndev->stats.rx_packets++; + + /* alloc a new packet for receive */ + skb = emac_rx_alloc(priv); + if (!skb) { + if (netif_msg_rx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "failed rx buffer alloc\n"); + return; + } + +recycle: + ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, + skb_tailroom(skb), GFP_KERNEL); + if (WARN_ON(ret < 0)) + dev_kfree_skb_any(skb); +} + +static void emac_tx_handler(void *token, int len, int status) +{ + struct sk_buff *skb = token; + struct net_device *ndev = skb->dev; + + if (unlikely(netif_queue_stopped(ndev))) + netif_start_queue(ndev); + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += len; + dev_kfree_skb_any(skb); +} + /** EMAC on-chip buffer descriptor memory * * WARNING: Please note that the on chip memory is used for both TX and RX @@ -1532,42 +1604,36 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) { struct device *emac_dev = &ndev->dev; int ret_code; - struct emac_netbufobj tx_buf; /* buffer obj-only single frame support */ - struct emac_netpktobj tx_packet; /* packet object */ struct emac_priv *priv = netdev_priv(ndev); /* If no link, return */ if (unlikely(!priv->link)) { if (netif_msg_tx_err(priv) && net_ratelimit()) dev_err(emac_dev, "DaVinci EMAC: No link to transmit"); - return NETDEV_TX_BUSY; + goto fail_tx; } - /* Build the buffer and packet objects - Since only single fragment is - * supported, need not set length and token in both packet & object. - * Doing so for completeness sake & to show that this needs to be done - * in multifragment case - */ - tx_packet.buf_list = &tx_buf; - tx_packet.num_bufs = 1; /* only single fragment supported */ - tx_packet.pkt_length = skb->len; - tx_packet.pkt_token = (void *)skb; - tx_buf.length = skb->len; - tx_buf.buf_token = (void *)skb; - tx_buf.data_ptr = skb->data; - ret_code = emac_send(priv, &tx_packet, EMAC_DEF_TX_CH); + ret_code = skb_padto(skb, EMAC_DEF_MIN_ETHPKTSIZE); + if (unlikely(ret_code < 0)) { + if (netif_msg_tx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "DaVinci EMAC: packet pad failed"); + goto fail_tx; + } + + ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len, + GFP_KERNEL); if (unlikely(ret_code != 0)) { - if (ret_code == EMAC_ERR_TX_OUT_OF_BD) { - if (netif_msg_tx_err(priv) && net_ratelimit()) - dev_err(emac_dev, "DaVinci EMAC: xmit() fatal"\ - " err. Out of TX BD's"); - netif_stop_queue(priv->ndev); - } - ndev->stats.tx_dropped++; - return NETDEV_TX_BUSY; + if (netif_msg_tx_err(priv) && net_ratelimit()) + dev_err(emac_dev, "DaVinci EMAC: desc submit failed"); + goto fail_tx; } return NETDEV_TX_OK; + +fail_tx: + ndev->stats.tx_dropped++; + netif_stop_queue(ndev); + return NETDEV_TX_BUSY; } /** @@ -1588,13 +1654,12 @@ static void emac_dev_tx_timeout(struct net_device *ndev) if (netif_msg_tx_err(priv)) dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX"); + emac_dump_regs(priv); + ndev->stats.tx_errors++; emac_int_disable(priv); - emac_stop_txch(priv, EMAC_DEF_TX_CH); - emac_cleanup_txch(priv, EMAC_DEF_TX_CH); - emac_init_txch(priv, EMAC_DEF_TX_CH); - emac_write(EMAC_TXHDP(0), 0); - emac_write(EMAC_TXINTMASKSET, BIT(EMAC_DEF_TX_CH)); + cpdma_chan_stop(priv->txchan); + cpdma_chan_start(priv->txchan); emac_int_enable(priv); } @@ -1915,7 +1980,6 @@ static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr) static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) { struct emac_priv *priv = netdev_priv(ndev); - struct emac_rxch *rxch = priv->rxch[EMAC_DEF_RX_CH]; struct device *emac_dev = &priv->ndev->dev; struct sockaddr *sa = addr; @@ -1926,11 +1990,10 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len); - /* If the interface is down - rxch is NULL. */ /* MAC address is configured only after the interface is enabled. */ if (netif_running(ndev)) { - memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len); - emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr); + memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); + emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); } if (netif_msg_drv(priv)) @@ -2139,7 +2202,7 @@ end_emac_rx_bdproc: */ static int emac_hw_enable(struct emac_priv *priv) { - u32 ch, val, mbp_enable, mac_control; + u32 val, mbp_enable, mac_control; /* Soft reset */ emac_write(EMAC_SOFTRESET, 1); @@ -2182,26 +2245,9 @@ static int emac_hw_enable(struct emac_priv *priv) emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL); priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF; - val = emac_read(EMAC_TXCONTROL); - val |= EMAC_TX_CONTROL_TX_ENABLE_VAL; - emac_write(EMAC_TXCONTROL, val); - val = emac_read(EMAC_RXCONTROL); - val |= EMAC_RX_CONTROL_RX_ENABLE_VAL; - emac_write(EMAC_RXCONTROL, val); emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL); - for (ch = 0; ch < EMAC_DEF_MAX_TX_CH; ch++) { - emac_write(EMAC_TXHDP(ch), 0); - emac_write(EMAC_TXINTMASKSET, BIT(ch)); - } - for (ch = 0; ch < EMAC_DEF_MAX_RX_CH; ch++) { - struct emac_rxch *rxch = priv->rxch[ch]; - emac_setmac(priv, ch, rxch->mac_addr); - emac_write(EMAC_RXINTMASKSET, BIT(ch)); - rxch->queue_active = 1; - emac_write(EMAC_RXHDP(ch), - emac_virt_to_phys(rxch->active_queue_head, priv)); - } + emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr); /* Enable MII */ val = emac_read(EMAC_MACCONTROL); @@ -2246,8 +2292,8 @@ static int emac_poll(struct napi_struct *napi, int budget) mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC; if (status & mask) { - num_tx_pkts = emac_tx_bdproc(priv, EMAC_DEF_TX_CH, - EMAC_DEF_TX_MAX_SERVICE); + num_tx_pkts = cpdma_chan_process(priv->txchan, + EMAC_DEF_TX_MAX_SERVICE); } /* TX processing */ mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC; @@ -2256,7 +2302,7 @@ static int emac_poll(struct napi_struct *napi, int budget) mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC; if (status & mask) { - num_rx_pkts = emac_rx_bdproc(priv, EMAC_DEF_RX_CH, budget); + num_rx_pkts = cpdma_chan_process(priv->rxchan, budget); } /* RX processing */ mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT; @@ -2397,9 +2443,9 @@ static int match_first_device(struct device *dev, void *data) static int emac_dev_open(struct net_device *ndev) { struct device *emac_dev = &ndev->dev; - u32 rc, cnt, ch; + u32 cnt; struct resource *res; - int q, m; + int q, m, ret; int i = 0; int k = 0; struct emac_priv *priv = netdev_priv(ndev); @@ -2411,29 +2457,21 @@ static int emac_dev_open(struct net_device *ndev) /* Configuration items */ priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN; - /* Clear basic hardware */ - for (ch = 0; ch < EMAC_MAX_TXRX_CHANNELS; ch++) { - emac_write(EMAC_TXHDP(ch), 0); - emac_write(EMAC_RXHDP(ch), 0); - emac_write(EMAC_RXHDP(ch), 0); - emac_write(EMAC_RXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); - emac_write(EMAC_TXINTMASKCLEAR, EMAC_INT_MASK_CLEAR); - } priv->mac_hash1 = 0; priv->mac_hash2 = 0; emac_write(EMAC_MACHASH1, 0); emac_write(EMAC_MACHASH2, 0); - /* multi ch not supported - open 1 TX, 1RX ch by default */ - rc = emac_init_txch(priv, EMAC_DEF_TX_CH); - if (0 != rc) { - dev_err(emac_dev, "DaVinci EMAC: emac_init_txch() failed"); - return rc; - } - rc = emac_init_rxch(priv, EMAC_DEF_RX_CH, priv->mac_addr); - if (0 != rc) { - dev_err(emac_dev, "DaVinci EMAC: emac_init_rxch() failed"); - return rc; + for (i = 0; i < EMAC_DEF_RX_NUM_DESC; i++) { + struct sk_buff *skb = emac_rx_alloc(priv); + + if (!skb) + break; + + ret = cpdma_chan_submit(priv->rxchan, skb, skb->data, + skb_tailroom(skb), GFP_KERNEL); + if (WARN_ON(ret < 0)) + break; } /* Request IRQ */ @@ -2458,6 +2496,8 @@ static int emac_dev_open(struct net_device *ndev) emac_set_coalesce(ndev, &coal); } + cpdma_ctlr_start(priv->dma); + priv->phydev = NULL; /* use the first phy on the bus if pdata did not give us a phy id */ if (!priv->phy_id) { @@ -2545,10 +2585,7 @@ static int emac_dev_stop(struct net_device *ndev) netif_carrier_off(ndev); emac_int_disable(priv); - emac_stop_txch(priv, EMAC_DEF_TX_CH); - emac_stop_rxch(priv, EMAC_DEF_RX_CH); - emac_cleanup_txch(priv, EMAC_DEF_TX_CH); - emac_cleanup_rxch(priv, EMAC_DEF_RX_CH); + cpdma_ctlr_stop(priv->dma); emac_write(EMAC_SOFTRESET, 1); if (priv->phydev) @@ -2653,9 +2690,10 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) struct resource *res; struct net_device *ndev; struct emac_priv *priv; - unsigned long size; + unsigned long size, hw_ram_addr; struct emac_platform_data *pdata; struct device *emac_dev; + struct cpdma_params dma_params; /* obtain emac clock from kernel */ emac_clk = clk_get(&pdev->dev, NULL); @@ -2731,11 +2769,40 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->ctrl_ram_size = pdata->ctrl_ram_size; priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset; - if (pdata->hw_ram_addr) - priv->hw_ram_addr = pdata->hw_ram_addr; - else - priv->hw_ram_addr = (u32 __force)res->start + - pdata->ctrl_ram_offset; + hw_ram_addr = pdata->hw_ram_addr; + if (!hw_ram_addr) + hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset; + + memset(&dma_params, 0, sizeof(dma_params)); + dma_params.dev = emac_dev; + dma_params.dmaregs = priv->emac_base; + dma_params.rxthresh = priv->emac_base + 0x120; + dma_params.rxfree = priv->emac_base + 0x140; + dma_params.txhdp = priv->emac_base + 0x600; + dma_params.rxhdp = priv->emac_base + 0x620; + dma_params.txcp = priv->emac_base + 0x640; + dma_params.rxcp = priv->emac_base + 0x660; + dma_params.num_chan = EMAC_MAX_TXRX_CHANNELS; + dma_params.min_packet_size = EMAC_DEF_MIN_ETHPKTSIZE; + dma_params.desc_mem_phys = hw_ram_addr; + dma_params.desc_mem_size = pdata->ctrl_ram_size; + dma_params.desc_align = 16; + + priv->dma = cpdma_ctlr_create(&dma_params); + if (!priv->dma) { + dev_err(emac_dev, "DaVinci EMAC: Error initializing DMA\n"); + rc = -ENOMEM; + goto no_dma; + } + + priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH), + emac_tx_handler); + priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH), + emac_rx_handler); + if (WARN_ON(!priv->txchan || !priv->rxchan)) { + rc = -ENOMEM; + goto no_irq_res; + } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { @@ -2778,6 +2845,12 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) netdev_reg_err: clk_disable(emac_clk); no_irq_res: + if (priv->txchan) + cpdma_chan_destroy(priv->txchan); + if (priv->rxchan) + cpdma_chan_destroy(priv->rxchan); + cpdma_ctlr_destroy(priv->dma); +no_dma: res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, res->end - res->start + 1); iounmap(priv->remap_addr); @@ -2806,6 +2879,12 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (priv->txchan) + cpdma_chan_destroy(priv->txchan); + if (priv->rxchan) + cpdma_chan_destroy(priv->rxchan); + cpdma_ctlr_destroy(priv->dma); + release_mem_region(res->start, res->end - res->start + 1); unregister_netdev(ndev); -- 1.7.0.4 From mdeneen+davinci at saucontech.com Wed Sep 15 09:19:51 2010 From: mdeneen+davinci at saucontech.com (Mark Deneen) Date: Wed, 15 Sep 2010 10:19:51 -0400 Subject: Prefered web server fo Davinci In-Reply-To: <20100915140340.GA9279@dei.unipd.it> References: <70E876B0EA86DD4BAF101844BC814DFE0903E89713@Cloud.RL.local> <1284557718.16883.11.camel@mdeneen.sdc.saucontech.com> <20100915140340.GA9279@dei.unipd.it> Message-ID: <1284560391.16883.48.camel@mdeneen.sdc.saucontech.com> On Wed, 2010-09-15 at 16:03 +0200, Ottavio Campana wrote: > On Wed, Sep 15, 2010 at 09:35:18AM -0400, Mark Deneen wrote: > > On Wed, 2010-09-15 at 03:06 +0100, Jon Povey wrote: > > > davinci-linux-open-source-bounces at linux.davincidsp.com wrote: > > > > Could someone please tell me if there is a better, smaller, > > > > easier to cross compile, and secure web server that you would > > > > recommend? > > > > > > http://www.acme.com/software/thttpd/ looks promising at a glance. > > > I haven't tried it, but it's small and uses GNU configure so may > > > not be painful to cross-compile. > > > > > > I'd be interested to know your results - I may need to do something > > > similar soon. > > > > > > As for security.. always a crapshoot. > > > Perhaps you gain a little security through obscurity not using Apache. > > > > > > Depending on what you need the web server to do, here's a few more > > options: > > > > 1. lighttpd http://www.lighttpd.net/ > > 2. uhttpd https://dev.openwrt.org/browser/trunk/package/uhttpd?rev=20573 > > 3. publicfile http://cr.yp.to/publicfile.html > > > > lighttpd is the most advanced of the three, but it has fewer bells and > > whistles than apache. > > if the task is just serving a few pages also busybox comes with a minimal webserver. > > You can do cgi with it, but you need to write shell scripts. > Yes, busybox does a pretty good job. It spawns a process per connection, which may not be what you want. I don't believe you can (easily) control the maximum number of concurrent connections, so it would be pretty easy to perform a DoS attack. uhttpd was designed to be a drop in replacement for busybox, so it also does cgi. In short, you have a lot of portable options! Best Regards, Mark Deneen Saucon Technologies From albertbu at gmail.com Wed Sep 15 09:24:16 2010 From: albertbu at gmail.com (Albert Burbea) Date: Wed, 15 Sep 2010 16:24:16 +0200 Subject: ### DM6446 DVR In-Reply-To: <002e01cb54db$46564120$d302c360$@fl-eng.com> References: <002e01cb54db$46564120$d302c360$@fl-eng.com> Message-ID: hi this is quite simple: just enable usb host support in kernel, connect the usb stick to board, mount the new device and you have usb storage If you ise the EVM, look for jumpers setting / hardware hacks to enable the host interface (should be very simple) Now, the hurdle is encoding the mpeg 4 in a way that can be played by a pc (if you need this) Good luck Albert On Wed, Sep 15, 2010 at 3:38 PM, Steve Spano wrote: > Hi Folks, > > > Was wondering about a DVR application for the DM6446. > > We basically want to encode MPEG4 to a USB stick, then playback from it. > > Seems very similar to the encode/decode demo ? except that we put the USB > stick in the middle. > > Has anyone done this and/or is there any reference app that I could review > for something similar to this? > > > > Thanks > > > > Steve > > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source at linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source > > -- Albert Burbea Harishonim 8 Ramat Gan 52502, Israel Tel/Fax + 972-3-7526016 Mobile: +972-52-3541842 -------------- next part -------------- An HTML attachment was scrubbed... URL: From khilman at deeprootsystems.com Wed Sep 15 09:54:03 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Wed, 15 Sep 2010 07:54:03 -0700 Subject: [PATCH v4 00/10] split out emac cpdma and mdio for reuse In-Reply-To: <1284559890-31346-1-git-send-email-cyril@ti.com> (Cyril Chemparathy's message of "Wed, 15 Sep 2010 10:11:20 -0400") References: <1284559890-31346-1-git-send-email-cyril@ti.com> Message-ID: <87aanjgir8.fsf@deeprootsystems.com> Cyril Chemparathy writes: > Davinci's EMAC device has an in-built MDIO controller and a CPDMA engine. > These hardware modules are not restricted to EMAC device alone. For example, > CPSW3G (3-port gigabit ethernet switch) hardware uses these very same modules > internally. This patch series separates out EMAC's MDIO and CPDMA > functionality, allowing these individual pieces to be reused across TI > hardware. [...] > Changes from v3 (rolled in "post cpdma/mdio refactoring fixes" series): > 1. allow forced 100/full mode instead of phy auto-detect > 2. specify phy_id on boards that had a phy_mask defined earlier > 3. requeue cpdma descriptors when EOQ at submit > 4. use calculated mdio bus access times instead of hardcoded delays > 5. work around emac soft-reset impact on mdio controller state > 6. extend register dumps to include cpdma registers > 7. updated sign offs and acks Thanks Cyril for one more spin with these updates. Queuing this one for 2.6.37 in davinci-next. davinci git is now updated with this series (may take a bit to propagate to kernel.org mirrors though) Kevin From jon.povey at racelogic.co.uk Thu Sep 16 05:21:20 2010 From: jon.povey at racelogic.co.uk (Jon Povey) Date: Thu, 16 Sep 2010 19:21:20 +0900 Subject: [PATCH] i2c: davinci: Fix race when setting up for TX Message-ID: <1284632480-24035-1-git-send-email-jon.povey@racelogic.co.uk> When setting up to transmit, a race exists between the ISR and i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. This is mostly visible for transmits > 1 byte long. The ISR may run at any time after the mode register has been set. While we are setting up and loading the first byte, protect this critical section from the ISR with a spinlock. The RX path or zero-length transmits do not need this locking. Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 Signed-off-by: Jon Povey --- I suspect this hasn't shown up for others using single-byte transmits as the interrupt tends to either run entirely before or entirely after this block in i2c_davinci_xfer_msg(): /* * First byte should be set here, not after interrupt, * because transmit-data-ready interrupt can come before * NACK-interrupt during sending of previous message and * ICDXR may have wrong data */ if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); dev->buf_len--; } Often the entire message would be sent before that test was executed (observed with LED wiggling and a logic analyser), so dev->buf_len would be untrue and things merrily went on their way. That seems to be counter to the intent in the comment. I tried some fiddling around reordering the register loads but couldn't get things reliable so stuck in a spinlock. Better solutions welcome. P.S.: Having run into the the bus reset code a lot during testing, I am pretty sure that that generic_i2c_clock_pulse() does NOTHING due to pinmuxing, at least on DM355, it is misleading and may be better replaced with a comment saying "It would be great to toggle SCL here". drivers/i2c/busses/i2c-davinci.c | 21 ++++++++++++++++++++- 1 files changed, 20 insertions(+), 1 deletions(-) diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 2222c87..43aa55d 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -107,6 +107,7 @@ struct davinci_i2c_dev { u8 *buf; size_t buf_len; int irq; + spinlock_t lock; int stop; u8 terminate; struct i2c_adapter adapter; @@ -312,6 +313,8 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) u32 flag; u16 w; int r; + unsigned long flags; + int preload = 0; if (!pdata) pdata = &davinci_i2c_platform_data_default; @@ -347,6 +350,15 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) flag &= ~DAVINCI_I2C_MDR_STP; } + /* + * When transmitting, lock ISR out to avoid it racing on the buffer and + * DXR register before we are done + */ + if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { + preload = 1; + spin_lock_irqsave(&dev->lock, flags); + } + /* Enable receive or transmit interrupts */ w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); if (msg->flags & I2C_M_RD) @@ -366,13 +378,15 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) * NACK-interrupt during sending of previous message and * ICDXR may have wrong data */ - if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { + if (preload) { davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); dev->buf_len--; + spin_unlock_irqrestore(&dev->lock, flags); } r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, dev->adapter.timeout); + if (r == 0) { dev_err(dev->dev, "controller timed out\n"); i2c_recover_bus(dev); @@ -490,6 +504,8 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) int count = 0; u16 w; + spin_lock(&dev->lock); + while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) { dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat); if (count++ == 100) { @@ -579,6 +595,8 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) } } + spin_unlock(&dev->lock); + return count ? IRQ_HANDLED : IRQ_NONE; } @@ -662,6 +680,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) goto err_release_region; } + spin_lock_init(&dev->lock); init_completion(&dev->cmd_complete); #ifdef CONFIG_CPU_FREQ init_completion(&dev->xfr_complete); -- 1.6.3.3 From Michael.Rondeau at andrew.com Thu Sep 16 07:05:45 2010 From: Michael.Rondeau at andrew.com (Rondeau, Michael) Date: Thu, 16 Sep 2010 07:05:45 -0500 Subject: Prefered web server for Davinci Message-ID: <55D474137AF1C541A021F8D73F85CF5D4207993BBA@ACDCE7MB3.commscope.com> I want to thank everyone who responded to my earlier request. I wanted to share this with everyone. I have tried the lighttpd web server and have it working now. It was easy to cross compile and took a little effort to configure but seems to be running OK now. I used the 1.4.28 version which supposedly fixed a bug from the 1.2.27 version that had an abort problem with some CPU's. I was getting the abort at first but after changing one of the config settings, it has stopped. I am going to do some more testing, and if I am satisfied, I will write up what I did and will gladly share it with anyone who wants it. BTW: We use the web server for checking status, configuring, uploading new SW, and downloading log files from our product. Mike Rondeau -------------- next part -------------- An HTML attachment was scrubbed... URL: From albertbu at gmail.com Thu Sep 16 07:53:00 2010 From: albertbu at gmail.com (Albert Burbea) Date: Thu, 16 Sep 2010 14:53:00 +0200 Subject: Prefered web server for Davinci In-Reply-To: <55D474137AF1C541A021F8D73F85CF5D4207993BBA@ACDCE7MB3.commscope.com> References: <55D474137AF1C541A021F8D73F85CF5D4207993BBA@ACDCE7MB3.commscope.com> Message-ID: Hi pls share all the compliation, cfg, etc. Maybe you can ask one of the git linux maintainers to add it as an accessory product in the git kernel Albert On Thu, Sep 16, 2010 at 2:05 PM, Rondeau, Michael < Michael.Rondeau at andrew.com> wrote: > I want to thank everyone who responded to my earlier request. > > > > I wanted to share this with everyone. I have tried the lighttpd web server > and have it working now. It was easy to cross compile and took a little > effort to configure but seems to be running OK now. I used the 1.4.28 > version which supposedly fixed a bug from the 1.2.27 version that had an > abort problem with some CPU?s. I was getting the abort at first but after > changing one of the config settings, it has stopped. I am going to do some > more testing, and if I am satisfied, I will write up what I did and will > gladly share it with anyone who wants it. > > > > BTW: We use the web server for checking status, configuring, uploading new > SW, and downloading log files from our product. > > > > Mike Rondeau > > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source at linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source > > -- Albert Burbea Harishonim 8 Ramat Gan 52502, Israel Tel/Fax + 972-3-7526016 Mobile: +972-52-3541842 -------------- next part -------------- An HTML attachment was scrubbed... URL: From khilman at deeprootsystems.com Thu Sep 16 12:24:50 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 16 Sep 2010 10:24:50 -0700 Subject: [PATCH v4 1/2] davinci: Add generic PWM support for PWM control In-Reply-To: <201009132106.08932.caglarakyuz@gmail.com> (Caglar Akyuz's message of "Mon, 13 Sep 2010 21:06:08 +0300") References: <1284028849-16680-1-git-send-email-sugumar@ti.com> <201009102042.36977.caglarakyuz@gmail.com> <201009132106.08932.caglarakyuz@gmail.com> Message-ID: <87vd65a9el.fsf@deeprootsystems.com> Caglar Akyuz writes: >> Sugumar Natarajan wrote: >>On Fri, Sep 10, 2010 at 23:12:36, Caglar Akyuz wrote: >>> On Thursday 09 September 2010 01:40:49 pm Sugumar Natarajan wrote: >>> > This patch adds generic PWM support where it maintains the list of PWM >>> > control devices that can be added or removed. >>> > >>> > The interface provides a list of functions that can be accessed by the >>> > PWM control driver module and the generic PWM driver. >>> > >>> > The PWM control driver module such as eCAP uses the interface to >>> > register and add itself to the list as a PWM control device. >>> > The generic PWM driver uses the interface to search for a PWM control >>> > device and if present, uses the device for PWM control. >>> > >>> > Signed-off-by: Sugumar Natarajan >>> > --- >>> >>> Hi, >>> >>> [...] >>> >>> > + >>> > +int pwm_enable(struct pwm_device *pwm) { >>> > + if (WARN_ON(!pwm)) >>> > + return -EINVAL; >>> > + >>> > + return clk_enable(pwm->clk); >>> > +} >>> > +EXPORT_SYMBOL(pwm_enable); >>> > + >>> >>> I think 'clk_enable' should be controlled for un-matched pwm_enable/disable >>operation. Otherwise, disabling PWM won't shut down >>peripheral clock. If I understand inner workings of DaVinci clock >>implementation clock use_count is incremented with every >>clk_enable. >>> >>> Regards, >>> Caglar >>> >> >>Caglar, >> I could not understand what you mean by "un-match" .could you please >>explain? > >>Regards, >>N.sugumar > > > List server didn't deliver this mail to me, I saw it from the archives. I mean > something like this: > > int pwm_enable(struct pwm_device *pwm) > { > int rc = 0; > > if (WARN_ON(!pwm)) > return -EINVAL; > > if (!pwm->clk_enabled) { > rc = clk_enable(pwm->clk); > if (!rc) > pwm->clk_enabled = 1; > } > return rc; > } > > > The reason is 'pwm_enable' can be called over and over without 'pwm_disable' > and vice versa. For instance, every time backlight value is changed, > pwm_enable is called by the backlight framework. Implementing these extra checks is usually a safe way to go, however, this could also be considered a bug in the backlight driver. IOW, why is it repeatedly calling pwm_enable() when the value is changed? Either it should call disable, change the value, call enable, or if it leaves it enabled, it should not call pwm_enable() again. Kevin From khilman at deeprootsystems.com Thu Sep 16 12:37:00 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 16 Sep 2010 10:37:00 -0700 Subject: [PATCH] i2c: davinci: Fix race when setting up for TX In-Reply-To: <1284632480-24035-1-git-send-email-jon.povey@racelogic.co.uk> (Jon Povey's message of "Thu, 16 Sep 2010 19:21:20 +0900") References: <1284632480-24035-1-git-send-email-jon.povey@racelogic.co.uk> Message-ID: <87pqwda8ub.fsf@deeprootsystems.com> Jon Povey writes: > When setting up to transmit, a race exists between the ISR and > i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. > This is mostly visible for transmits > 1 byte long. > > The ISR may run at any time after the mode register has been set. > While we are setting up and loading the first byte, protect this critical > section from the ISR with a spinlock. > > The RX path or zero-length transmits do not need this locking. > > Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 > > Signed-off-by: Jon Povey This looks like a good fix. Anyone else care to test on other platforms and add a 'Tested-by'? Thanks, Kevin > --- > I suspect this hasn't shown up for others using single-byte transmits as the > interrupt tends to either run entirely before or entirely after this block > in i2c_davinci_xfer_msg(): > > /* > * First byte should be set here, not after interrupt, > * because transmit-data-ready interrupt can come before > * NACK-interrupt during sending of previous message and > * ICDXR may have wrong data > */ > if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { > davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); > dev->buf_len--; > } > > Often the entire message would be sent before that test was executed > (observed with LED wiggling and a logic analyser), so dev->buf_len would > be untrue and things merrily went on their way. That seems to be counter > to the intent in the comment. > > I tried some fiddling around reordering the register loads but couldn't > get things reliable so stuck in a spinlock. Better solutions welcome. > > P.S.: Having run into the the bus reset code a lot during testing, I > am pretty sure that that generic_i2c_clock_pulse() does NOTHING due to > pinmuxing, at least on DM355, it is misleading and may be better > replaced with a comment saying "It would be great to toggle SCL here". > > drivers/i2c/busses/i2c-davinci.c | 21 ++++++++++++++++++++- > 1 files changed, 20 insertions(+), 1 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c > index 2222c87..43aa55d 100644 > --- a/drivers/i2c/busses/i2c-davinci.c > +++ b/drivers/i2c/busses/i2c-davinci.c > @@ -107,6 +107,7 @@ struct davinci_i2c_dev { > u8 *buf; > size_t buf_len; > int irq; > + spinlock_t lock; > int stop; > u8 terminate; > struct i2c_adapter adapter; > @@ -312,6 +313,8 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) > u32 flag; > u16 w; > int r; > + unsigned long flags; > + int preload = 0; > > if (!pdata) > pdata = &davinci_i2c_platform_data_default; > @@ -347,6 +350,15 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) > flag &= ~DAVINCI_I2C_MDR_STP; > } > > + /* > + * When transmitting, lock ISR out to avoid it racing on the buffer and > + * DXR register before we are done > + */ > + if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { > + preload = 1; > + spin_lock_irqsave(&dev->lock, flags); > + } > + > /* Enable receive or transmit interrupts */ > w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); > if (msg->flags & I2C_M_RD) > @@ -366,13 +378,15 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) > * NACK-interrupt during sending of previous message and > * ICDXR may have wrong data > */ > - if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { > + if (preload) { > davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); > dev->buf_len--; > + spin_unlock_irqrestore(&dev->lock, flags); > } > > r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, > dev->adapter.timeout); > + > if (r == 0) { > dev_err(dev->dev, "controller timed out\n"); > i2c_recover_bus(dev); > @@ -490,6 +504,8 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) > int count = 0; > u16 w; > > + spin_lock(&dev->lock); > + > while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) { > dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat); > if (count++ == 100) { > @@ -579,6 +595,8 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) > } > } > > + spin_unlock(&dev->lock); > + > return count ? IRQ_HANDLED : IRQ_NONE; > } > > @@ -662,6 +680,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) > goto err_release_region; > } > > + spin_lock_init(&dev->lock); > init_completion(&dev->cmd_complete); > #ifdef CONFIG_CPU_FREQ > init_completion(&dev->xfr_complete); From caglarakyuz at gmail.com Thu Sep 16 12:57:26 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Thu, 16 Sep 2010 20:57:26 +0300 Subject: [PATCH v4 1/2] davinci: Add generic PWM support for PWM control In-Reply-To: <87vd65a9el.fsf@deeprootsystems.com> References: <1284028849-16680-1-git-send-email-sugumar@ti.com> <201009132106.08932.caglarakyuz@gmail.com> <87vd65a9el.fsf@deeprootsystems.com> Message-ID: <201009162057.26232.caglarakyuz@gmail.com> On Thursday 16 September 2010 08:24:50 pm Kevin Hilman wrote: > Caglar Akyuz writes: > >> Sugumar Natarajan wrote: > >> > >>On Fri, Sep 10, 2010 at 23:12:36, Caglar Akyuz wrote: > >>> On Thursday 09 September 2010 01:40:49 pm Sugumar Natarajan wrote: > >>> > This patch adds generic PWM support where it maintains the list of > >>> > PWM control devices that can be added or removed. > >>> > > >>> > The interface provides a list of functions that can be accessed by > >>> > the PWM control driver module and the generic PWM driver. > >>> > > >>> > The PWM control driver module such as eCAP uses the interface to > >>> > register and add itself to the list as a PWM control device. > >>> > The generic PWM driver uses the interface to search for a PWM control > >>> > device and if present, uses the device for PWM control. > >>> > > >>> > Signed-off-by: Sugumar Natarajan > >>> > --- > >>> > >>> Hi, > >>> > >>> [...] > >>> > >>> > + > >>> > +int pwm_enable(struct pwm_device *pwm) { > >>> > + if (WARN_ON(!pwm)) > >>> > + return -EINVAL; > >>> > + > >>> > + return clk_enable(pwm->clk); > >>> > +} > >>> > +EXPORT_SYMBOL(pwm_enable); > >>> > + > >>> > >>> I think 'clk_enable' should be controlled for un-matched > >>> pwm_enable/disable > >> > >>operation. Otherwise, disabling PWM won't shut down > >>peripheral clock. If I understand inner workings of DaVinci clock > >>implementation clock use_count is incremented with every > >>clk_enable. > >> > >>> Regards, > >>> Caglar > >> > >>Caglar, > >> I could not understand what you mean by "un-match" .could you please > >>explain? > >> > >>Regards, > >>N.sugumar > > > > List server didn't deliver this mail to me, I saw it from the archives. I > > mean something like this: > > > > int pwm_enable(struct pwm_device *pwm) > > { > > int rc = 0; > > > > if (WARN_ON(!pwm)) > > return -EINVAL; > > > > if (!pwm->clk_enabled) { > > rc = clk_enable(pwm->clk); > > if (!rc) > > pwm->clk_enabled = 1; > > } > > return rc; > > } > > > > > > The reason is 'pwm_enable' can be called over and over without > > 'pwm_disable' and vice versa. For instance, every time backlight value is > > changed, pwm_enable is called by the backlight framework. > > Implementing these extra checks is usually a safe way to go, however, > this could also be considered a bug in the backlight driver. > > IOW, why is it repeatedly calling pwm_enable() when the value is > changed? My guess is that because there is not any state variable it can rely on to? Backlight update operation can be due to either user writing to sysfs node or fb blanking. > Either it should call disable, change the value, call enable, > or if it leaves it enabled, it should not call pwm_enable() again. > Code is attached for your reference, I don't see a way of fixing it. This code is called un-conditionally when anything is written to sysfs node(no check there either). Regards, Caglar static int pwm_backlight_update_status(struct backlight_device *bl) { struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); int brightness = bl->props.brightness; int max = bl->props.max_brightness; if (bl->props.power != FB_BLANK_UNBLANK) brightness = 0; if (bl->props.fb_blank != FB_BLANK_UNBLANK) brightness = 0; if (pb->notify) brightness = pb->notify(pb->dev, brightness); if (brightness == 0) { pwm_config(pb->pwm, 0, pb->period); pwm_disable(pb->pwm); } else { pwm_config(pb->pwm, brightness * pb->period / max, pb->period); pwm_enable(pb->pwm); } return 0; } > Kevin > From khilman at deeprootsystems.com Thu Sep 16 12:49:32 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 16 Sep 2010 10:49:32 -0700 Subject: [PATCH] davinci: MityDSP-L138/MityARM-1808 read MAC address from I2C Prom In-Reply-To: <1284061257-9017-1-git-send-email-michael.williamson@criticallink.com> (Michael Williamson's message of "Thu, 9 Sep 2010 15:40:57 -0400") References: <1284061257-9017-1-git-send-email-michael.williamson@criticallink.com> Message-ID: <878w31a89f.fsf@deeprootsystems.com> Michael Williamson writes: > For the MityDSP-L138/MityARM-1808 SOMS, read the factory assigned > MAC address from the onboard I2C EPROM and assign it to the emac > device during platform initialization. > > Signed-off-by: Michael Williamson Hi Michael, A couple minor comments below... Also, the right address for the linux-arm-kernel mailing list is linux-arm-kernel at lists.infradead.org. Please CC that one. Thanks. > --- > arch/arm/mach-davinci/board-mityomapl138.c | 55 ++++++++++++++++++++++++++++ > 1 files changed, 55 insertions(+), 0 deletions(-) > > diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c > index e872fcc..e1cffb8 100644 > --- a/arch/arm/mach-davinci/board-mityomapl138.c > +++ b/arch/arm/mach-davinci/board-mityomapl138.c > @@ -15,6 +15,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -24,6 +25,59 @@ > #include > #include > > +#define FACTORY_CONFIG_MAGIC 0x012C0138 > +#define FACTORY_CONFIG_VERSION 0x00010001 > + > +/* Data Held in On-Board I2C device */ > +struct factory_config { > + uint32_t magic; > + uint32_t version; > + uint8_t mac[6]; > + uint32_t fpga_type; > + uint32_t spare; > + uint32_t serialnumber; u32 and u8 are more customary here. > + char partnum[32]; > +}; > + > +static struct factory_config factory_config; > + > +static void read_factory_config(struct memory_accessor *a, void *context) > +{ > + int ret; > + struct davinci_soc_info *soc_info = &davinci_soc_info; > + > + ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config)); > + if (ret != sizeof(struct factory_config)) { > + pr_warning("Read Factory Config Failed: %d\n", ret); > + return; > + } > + > + if (factory_config.magic != FACTORY_CONFIG_MAGIC) { > + pr_warning("Factory Config Magic Wrong (%X)\n", > + factory_config.magic); > + return; > + } > + > + if (factory_config.version != FACTORY_CONFIG_VERSION) { > + pr_warning("Factory Config Version Wrong (%X)\n", > + factory_config.version); > + return; > + } > + > + pr_info("Found MAC = %pM\n", factory_config.mac); > + pr_info("Part Number = %s\n", factory_config.partnum); Might be nice to prefix these prings with 'MityOMAPL138' or something similar. > + memcpy(&soc_info->emac_pdata->mac_addr[0], > + &factory_config.mac[0], 6); Rather than '6', use ETH_ALEN (from #include ) Also, for some extra sanity, you might want to test the MAC using is_valid_ether_addr() (from the same header) and warn if it's not a valid MAC. Kevin > +} > + > +static struct at24_platform_data mityomapl138_fd_chip = { > + .byte_len = 256, > + .page_size = 8, > + .flags = AT24_FLAG_READONLY | AT24_FLAG_IRUGO, > + .setup = read_factory_config, > + .context = NULL, > +}; > + > static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = { > .bus_freq = 100, /* kHz */ > .bus_delay = 0, /* usec */ > @@ -150,6 +204,7 @@ static struct i2c_board_info __initdata mityomap_tps65023_info[] = { > }, > { > I2C_BOARD_INFO("24c02", 0x50), > + .platform_data = &mityomapl138_fd_chip, > }, > }; From khilman at deeprootsystems.com Thu Sep 16 12:53:56 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 16 Sep 2010 10:53:56 -0700 Subject: [PATCH 0/7] add tnetv107x input drivers In-Reply-To: <1284395388-32687-1-git-send-email-cyril@ti.com> (Cyril Chemparathy's message of "Mon, 13 Sep 2010 12:29:41 -0400") References: <1284395388-32687-1-git-send-email-cyril@ti.com> Message-ID: <87vd658thn.fsf@deeprootsystems.com> Cyril Chemparathy writes: > Texas Instruments' TNETV107X is an ARM1176 based SoC, with on-chip > touchscreen and keypad controllers. This patch series adds drivers for these > controllers. Dmitry, With you're review/ack, I can merge these via the davinci tree so the drivers can merge with the platform code that goes with them. That way we can avoid potential conflicts from other davinci changes touching the same platform files. Kevin > > Cyril Chemparathy (7): > davinci: define tnetv107x keypad platform data > input: add driver for tnetv107x on-chip keypad controller > davinci: add tnetv107x keypad platform device > davinci: add keypad config for tnetv107x evm board > input: add driver for tnetv107x touchscreen controller > davinci: add tnetv107x touchscreen platform device > davinci: add touchscreen config for tnetv107x evm board > > arch/arm/mach-davinci/board-tnetv107x-evm.c | 51 +++ > arch/arm/mach-davinci/devices-tnetv107x.c | 54 +++ > arch/arm/mach-davinci/include/mach/tnetv107x.h | 24 ++ > drivers/input/keyboard/Kconfig | 9 + > drivers/input/keyboard/Makefile | 1 + > drivers/input/keyboard/tnetv107x-keypad.c | 324 ++++++++++++++++ > drivers/input/touchscreen/Kconfig | 6 + > drivers/input/touchscreen/Makefile | 1 + > drivers/input/touchscreen/tnetv107x-ts.c | 481 ++++++++++++++++++++++++ > 9 files changed, 951 insertions(+), 0 deletions(-) > create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c > create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c > > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source at linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source From michael.williamson at criticallink.com Thu Sep 16 13:08:18 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Thu, 16 Sep 2010 14:08:18 -0400 Subject: [PATCH] davinci: MityDSP-L138/MityARM-1808 read MAC address from I2C Prom In-Reply-To: <878w31a89f.fsf@deeprootsystems.com> References: <1284061257-9017-1-git-send-email-michael.williamson@criticallink.com> <878w31a89f.fsf@deeprootsystems.com> Message-ID: <4C925D12.2020900@criticallink.com> On 9/16/2010 1:49 PM, Kevin Hilman wrote: > Michael Williamson writes: > >> For the MityDSP-L138/MityARM-1808 SOMS, read the factory assigned >> MAC address from the onboard I2C EPROM and assign it to the emac >> device during platform initialization. >> >> Signed-off-by: Michael Williamson > > Hi Michael, > > A couple minor comments below... > > Also, the right address for the linux-arm-kernel mailing list is > linux-arm-kernel at lists.infradead.org. Please CC that one. Thanks. > These should only go to linux-arm-kernel at lists.infradead.org? Or both linux-arm-kernel as well as davini-linux-open-source? Thanks. >> --- >> arch/arm/mach-davinci/board-mityomapl138.c | 55 ++++++++++++++++++++++++++++ >> 1 files changed, 55 insertions(+), 0 deletions(-) >> >> diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c >> index e872fcc..e1cffb8 100644 >> --- a/arch/arm/mach-davinci/board-mityomapl138.c >> +++ b/arch/arm/mach-davinci/board-mityomapl138.c >> @@ -15,6 +15,7 @@ >> #include >> #include >> #include >> +#include >> >> #include >> #include >> @@ -24,6 +25,59 @@ >> #include >> #include >> >> +#define FACTORY_CONFIG_MAGIC 0x012C0138 >> +#define FACTORY_CONFIG_VERSION 0x00010001 >> + >> +/* Data Held in On-Board I2C device */ >> +struct factory_config { >> + uint32_t magic; >> + uint32_t version; >> + uint8_t mac[6]; >> + uint32_t fpga_type; >> + uint32_t spare; >> + uint32_t serialnumber; > > u32 and u8 are more customary here. OK. I've always wondered why there were those types in addition to the ones in stdint.h. I will switch. Just never understood why there are separate types. maybe before stdint came into existence? > >> + char partnum[32]; >> +}; >> + >> +static struct factory_config factory_config; >> + >> +static void read_factory_config(struct memory_accessor *a, void *context) >> +{ >> + int ret; >> + struct davinci_soc_info *soc_info = &davinci_soc_info; >> + >> + ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config)); >> + if (ret != sizeof(struct factory_config)) { >> + pr_warning("Read Factory Config Failed: %d\n", ret); >> + return; >> + } >> + >> + if (factory_config.magic != FACTORY_CONFIG_MAGIC) { >> + pr_warning("Factory Config Magic Wrong (%X)\n", >> + factory_config.magic); >> + return; >> + } >> + >> + if (factory_config.version != FACTORY_CONFIG_VERSION) { >> + pr_warning("Factory Config Version Wrong (%X)\n", >> + factory_config.version); >> + return; >> + } >> + >> + pr_info("Found MAC = %pM\n", factory_config.mac); >> + pr_info("Part Number = %s\n", factory_config.partnum); > > Might be nice to prefix these prings with 'MityOMAPL138' or something > similar. Sure. > >> + memcpy(&soc_info->emac_pdata->mac_addr[0], >> + &factory_config.mac[0], 6); > > Rather than '6', use ETH_ALEN (from #include ) > > Also, for some extra sanity, you might want to test the MAC using > is_valid_ether_addr() (from the same header) and warn if it's not a > valid MAC. > No problem. I will resubmit and make sure the other list is on there. Thanks for the comments. -Mike From khilman at deeprootsystems.com Thu Sep 16 13:29:43 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 16 Sep 2010 11:29:43 -0700 Subject: [PATCH 0/7] add tnetv107x input drivers In-Reply-To: <201009161111.56465.dmitry.torokhov@gmail.com> (Dmitry Torokhov's message of "Thu, 16 Sep 2010 11:11:56 -0700") References: <1284395388-32687-1-git-send-email-cyril@ti.com> <87vd658thn.fsf@deeprootsystems.com> <201009161111.56465.dmitry.torokhov@gmail.com> Message-ID: <87sk197d9k.fsf@deeprootsystems.com> Dmitry Torokhov writes: > On Thursday, September 16, 2010 10:53:56 am Kevin Hilman wrote: >> Cyril Chemparathy writes: >> > Texas Instruments' TNETV107X is an ARM1176 based SoC, with on-chip >> > touchscreen and keypad controllers. This patch series adds drivers for >> > these controllers. >> >> Dmitry, >> >> With you're review/ack, I can merge these via the davinci tree so the >> drivers can merge with the platform code that goes with them. That way >> we can avoid potential conflicts from other davinci changes touching the >> same platform files. > > Kevin, > > I am OK with the drivers coming through your tree, however I am not yet > completely happy with the patches (as they were posted - their initial > version). > Sure, I'll wait for your review and will not merge them without your ack. Thanks, Kevin From khilman at deeprootsystems.com Thu Sep 16 13:31:58 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 16 Sep 2010 11:31:58 -0700 Subject: [PATCH] davinci: MityDSP-L138/MityARM-1808 read MAC address from I2C Prom In-Reply-To: <4C925D12.2020900@criticallink.com> (Michael Williamson's message of "Thu, 16 Sep 2010 14:08:18 -0400") References: <1284061257-9017-1-git-send-email-michael.williamson@criticallink.com> <878w31a89f.fsf@deeprootsystems.com> <4C925D12.2020900@criticallink.com> Message-ID: <87mxrh7d5t.fsf@deeprootsystems.com> Michael Williamson writes: > On 9/16/2010 1:49 PM, Kevin Hilman wrote: > >> Michael Williamson writes: >> >>> For the MityDSP-L138/MityARM-1808 SOMS, read the factory assigned >>> MAC address from the onboard I2C EPROM and assign it to the emac >>> device during platform initialization. >>> >>> Signed-off-by: Michael Williamson >> >> Hi Michael, >> >> A couple minor comments below... >> >> Also, the right address for the linux-arm-kernel mailing list is >> linux-arm-kernel at lists.infradead.org. Please CC that one. Thanks. >> > > > These should only go to linux-arm-kernel at lists.infradead.org? Or both > linux-arm-kernel as well as davini-linux-open-source? Thanks. both please. Thanks, Kevin From khilman at deeprootsystems.com Thu Sep 16 13:37:06 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 16 Sep 2010 11:37:06 -0700 Subject: [PATCH v4 1/2] davinci: Add generic PWM support for PWM control In-Reply-To: <201009162057.26232.caglarakyuz@gmail.com> (Caglar Akyuz's message of "Thu, 16 Sep 2010 20:57:26 +0300") References: <1284028849-16680-1-git-send-email-sugumar@ti.com> <201009132106.08932.caglarakyuz@gmail.com> <87vd65a9el.fsf@deeprootsystems.com> <201009162057.26232.caglarakyuz@gmail.com> Message-ID: <877hil7cx9.fsf@deeprootsystems.com> Caglar Akyuz writes: > On Thursday 16 September 2010 08:24:50 pm Kevin Hilman wrote: >> Caglar Akyuz writes: >> >> Sugumar Natarajan wrote: >> >> >> >>On Fri, Sep 10, 2010 at 23:12:36, Caglar Akyuz wrote: >> >>> On Thursday 09 September 2010 01:40:49 pm Sugumar Natarajan wrote: >> >>> > This patch adds generic PWM support where it maintains the list of >> >>> > PWM control devices that can be added or removed. >> >>> > >> >>> > The interface provides a list of functions that can be accessed by >> >>> > the PWM control driver module and the generic PWM driver. >> >>> > >> >>> > The PWM control driver module such as eCAP uses the interface to >> >>> > register and add itself to the list as a PWM control device. >> >>> > The generic PWM driver uses the interface to search for a PWM control >> >>> > device and if present, uses the device for PWM control. >> >>> > >> >>> > Signed-off-by: Sugumar Natarajan >> >>> > --- >> >>> >> >>> Hi, >> >>> >> >>> [...] >> >>> >> >>> > + >> >>> > +int pwm_enable(struct pwm_device *pwm) { >> >>> > + if (WARN_ON(!pwm)) >> >>> > + return -EINVAL; >> >>> > + >> >>> > + return clk_enable(pwm->clk); >> >>> > +} >> >>> > +EXPORT_SYMBOL(pwm_enable); >> >>> > + >> >>> >> >>> I think 'clk_enable' should be controlled for un-matched >> >>> pwm_enable/disable >> >> >> >>operation. Otherwise, disabling PWM won't shut down >> >>peripheral clock. If I understand inner workings of DaVinci clock >> >>implementation clock use_count is incremented with every >> >>clk_enable. >> >> >> >>> Regards, >> >>> Caglar >> >> >> >>Caglar, >> >> I could not understand what you mean by "un-match" .could you please >> >>explain? >> >> >> >>Regards, >> >>N.sugumar >> > >> > List server didn't deliver this mail to me, I saw it from the archives. I >> > mean something like this: >> > >> > int pwm_enable(struct pwm_device *pwm) >> > { >> > int rc = 0; >> > >> > if (WARN_ON(!pwm)) >> > return -EINVAL; >> > >> > if (!pwm->clk_enabled) { >> > rc = clk_enable(pwm->clk); >> > if (!rc) >> > pwm->clk_enabled = 1; >> > } >> > return rc; >> > } >> > >> > >> > The reason is 'pwm_enable' can be called over and over without >> > 'pwm_disable' and vice versa. For instance, every time backlight value is >> > changed, pwm_enable is called by the backlight framework. >> >> Implementing these extra checks is usually a safe way to go, however, >> this could also be considered a bug in the backlight driver. >> >> IOW, why is it repeatedly calling pwm_enable() when the value is >> changed? > > My guess is that because there is not any state variable it can rely on to? Exactly. Either the backlight code or the PWM driver needs to keep state. Looks like Sugumar decided to add it to his PWM layer in v5. > Backlight update operation can be due to either user writing to sysfs node or > fb blanking. > >> Either it should call disable, change the value, call enable, >> or if it leaves it enabled, it should not call pwm_enable() again. >> > > Code is attached for your reference, I don't see a way of fixing it. This code > is called un-conditionally when anything is written to sysfs node(no check > there either). It could be fixed as easily as Sugumar fixed his patch, simply by adding state. Anyways, it's a minor concern. Kevin From cyril at ti.com Thu Sep 16 14:54:40 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 16 Sep 2010 15:54:40 -0400 Subject: [PATCH v2 1/5] input: add driver for tnetv107x on-chip keypad controller In-Reply-To: <1284666884-10374-1-git-send-email-cyril@ti.com> References: <1284666884-10374-1-git-send-email-cyril@ti.com> Message-ID: <1284666884-10374-2-git-send-email-cyril@ti.com> This patch adds support for tnetv107x's on-chip keypad controller. Signed-off-by: Cyril Chemparathy --- drivers/input/keyboard/Kconfig | 9 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/tnetv107x-keypad.c | 329 +++++++++++++++++++++++++++++ 3 files changed, 339 insertions(+), 0 deletions(-) create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 9cc488d..df1facb 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -424,6 +424,15 @@ config KEYBOARD_OMAP To compile this driver as a module, choose M here: the module will be called omap-keypad. +config KEYBOARD_TNETV107X + tristate "TI TNETV107X keypad support" + depends on ARCH_DAVINCI_TNETV107X + help + Say Y here if you want to use the TNETV107X keypad. + + To compile this driver as a module, choose M here: the + module will be called tnetv107x-keypad. + config KEYBOARD_TWL4030 tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" depends on TWL4030_CORE diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 504b591..dc04518 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o +obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c new file mode 100644 index 0000000..c262cb4 --- /dev/null +++ b/drivers/input/keyboard/tnetv107x-keypad.c @@ -0,0 +1,329 @@ +/* + * Texas Instruments TNETV107X Keypad Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BITS(x) (BIT(x) - 1) + +#define KEYPAD_ROWS 9 +#define KEYPAD_COLS 9 + +#define DEBOUNCE_MIN BIT(10) +#define DEBOUNCE_MAX BITS(30) + +struct keypad_regs { + u32 rev; + u32 mode; + u32 mask; + u32 pol; + u32 dclock; + u32 rclock; + u32 stable_cnt; + u32 in_en; + u32 out; + u32 out_en; + u32 in; + u32 lock; + u32 pres[3]; +}; + +#define keypad_read(kp, reg) __raw_readl(&(kp)->regs->reg) +#define keypad_write(kp, reg, val) __raw_writel(val, &(kp)->regs->reg) + +struct keypad_data { + struct input_dev *input_dev; + struct resource *res; + struct keypad_regs __iomem *regs; + struct clk *clk; + struct device *dev; + u32 irq_press; + u32 irq_release; + int rows, cols, row_shift; + int debounce_ms, active_low; + unsigned short *keycodes; + u32 prev_keys[3]; +}; + +static irqreturn_t keypad_irq(int irq, void *data) +{ + struct keypad_data *kp = (struct keypad_data *)data; + int i, bit, val, row, col, code; + u32 curr_keys[3]; + u32 change; + + memset(curr_keys, 0, sizeof(curr_keys)); + if (irq == kp->irq_press) + for (i = 0; i < 3; i++) + curr_keys[i] = keypad_read(kp, pres[i]); + + for (i = 0; i < 3; i++) { + change = curr_keys[i] ^ kp->prev_keys[i]; + + while (change) { + bit = fls(change) - 1; + change ^= BIT(bit); + val = curr_keys[i] & BIT(bit); + bit += i * 32; + row = bit / KEYPAD_COLS; + col = bit % KEYPAD_COLS; + + code = MATRIX_SCAN_CODE(row, col, kp->row_shift); + input_event(kp->input_dev, EV_MSC, MSC_SCAN, code); + input_report_key(kp->input_dev, kp->keycodes[code], + val); + } + } + input_sync(kp->input_dev); + memcpy(kp->prev_keys, curr_keys, sizeof(curr_keys)); + + if (irq == kp->irq_press) + keypad_write(kp, lock, 0); /* Allow hardware updates */ + + return IRQ_HANDLED; +} + +static int keypad_start(struct input_dev *dev) +{ + struct keypad_data *kp = input_get_drvdata(dev); + unsigned long mask, debounce, clk_rate_khz; + int error; + + clk_enable(kp->clk); + clk_rate_khz = clk_get_rate(kp->clk) / 1000; + + /* Initialize device registers */ + keypad_write(kp, mode, 0); + + mask = BITS(kp->rows) << KEYPAD_COLS; + mask |= BITS(kp->cols); + keypad_write(kp, mask, ~mask); + + keypad_write(kp, pol, kp->active_low ? 0 : 0x3ffff); + debounce = kp->debounce_ms * clk_rate_khz; + debounce = min(debounce, DEBOUNCE_MAX); + debounce = max(debounce, DEBOUNCE_MIN); + keypad_write(kp, dclock, debounce); + keypad_write(kp, rclock, 4 * debounce); + keypad_write(kp, stable_cnt, 3); + keypad_write(kp, in_en, 1); + + error = request_irq(kp->irq_press, keypad_irq, 0, "key-press", kp); + if (error < 0) { + dev_err(kp->dev, "Could not allocate keypad press key irq\n"); + clk_disable(kp->clk); + return error; + } + + error = request_irq(kp->irq_release, keypad_irq, 0, "key-release", kp); + if (error < 0) { + dev_err(kp->dev, "Could not allocate keypad release key irq\n"); + free_irq(kp->irq_press, kp); + clk_disable(kp->clk); + return error; + } + + return 0; +} + +static void keypad_stop(struct input_dev *dev) +{ + struct keypad_data *kp = input_get_drvdata(dev); + + free_irq(kp->irq_press, kp); + free_irq(kp->irq_release, kp); + clk_disable(kp->clk); +} + +static int __devinit keypad_probe(struct platform_device *pdev) +{ + const struct matrix_keypad_platform_data *pdata; + const struct matrix_keymap_data *keymap_data; + struct device *dev = &pdev->dev; + struct keypad_data *kp; + int error = 0, sz; + u32 rev = 0; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(dev, "cannot find device data\n"); + return -EINVAL; + } + + keymap_data = pdata->keymap_data; + if (!keymap_data) { + dev_err(dev, "cannot find keymap data\n"); + return -EINVAL; + } + + kp = kzalloc(sizeof(struct keypad_data), GFP_KERNEL); + if (!kp) { + dev_err(dev, "cannot allocate device info\n"); + return -ENOMEM; + } + + kp->dev = dev; + kp->rows = pdata->num_row_gpios; + kp->cols = pdata->num_col_gpios; + kp->row_shift = get_count_order(kp->cols); + platform_set_drvdata(pdev, kp); + + sz = (kp->rows << kp->row_shift) * sizeof(*kp->keycodes); + kp->keycodes = kzalloc(sz, GFP_KERNEL); + if (!kp->keycodes) { + dev_err(dev, "cannot allocate keymap info\n"); + error = -ENOMEM; + goto error; + } + + kp->irq_press = platform_get_irq_byname(pdev, "press"); + kp->irq_release = platform_get_irq_byname(pdev, "release"); + if (kp->irq_press < 0 || kp->irq_release < 0) { + dev_err(dev, "cannot determine device interrupts\n"); + error = -ENODEV; + goto error; + } + + kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!kp->res) { + dev_err(dev, "cannot determine register area\n"); + error = -ENODEV; + goto error; + } + + if (!request_mem_region(kp->res->start, resource_size(kp->res), + pdev->name)) { + dev_err(dev, "cannot claim register memory\n"); + kp->res = NULL; + error = -EINVAL; + goto error; + } + + kp->regs = ioremap(kp->res->start, resource_size(kp->res)); + if (!kp->regs) { + dev_err(dev, "cannot map register memory\n"); + error = -ENOMEM; + goto error; + } + + kp->clk = clk_get(dev, NULL); + if (!kp->clk) { + dev_err(dev, "cannot claim device clock\n"); + error = -EINVAL; + goto error; + } + + kp->input_dev = input_allocate_device(); + if (!kp->input_dev) { + dev_err(dev, "cannot allocate input device\n"); + error = -ENOMEM; + goto error; + } + input_set_drvdata(kp->input_dev, kp); + + kp->input_dev->name = pdev->name; + kp->input_dev->dev.parent = &pdev->dev; + kp->input_dev->open = keypad_start; + kp->input_dev->close = keypad_stop; + kp->input_dev->evbit[0] = BIT_MASK(EV_KEY); + if (!pdata->no_autorepeat) + kp->input_dev->evbit[0] |= BIT_MASK(EV_REP); + + clk_enable(kp->clk); + rev = keypad_read(kp, rev); + kp->input_dev->id.bustype = BUS_HOST; + kp->input_dev->id.product = ((rev >> 8) & 0x07); + kp->input_dev->id.version = ((rev >> 16) & 0xfff); + clk_disable(kp->clk); + + kp->input_dev->keycode = kp->keycodes; + kp->input_dev->keycodesize = sizeof(*kp->keycodes); + kp->input_dev->keycodemax = kp->rows << kp->row_shift; + + matrix_keypad_build_keymap(keymap_data, kp->row_shift, kp->keycodes, + kp->input_dev->keybit); + + input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN); + + error = input_register_device(kp->input_dev); + if (error < 0) { + dev_err(dev, "Could not register input device\n"); + goto error; + } + + return 0; + +error: + if (kp->input_dev) + input_free_device(kp->input_dev); + if (kp->clk) + clk_put(kp->clk); + if (kp->regs) + iounmap(kp->regs); + if (kp->res) + release_mem_region(kp->res->start, resource_size(kp->res)); + platform_set_drvdata(pdev, NULL); + kfree(kp->keycodes); + kfree(kp); + return error; +} + +static int __devexit keypad_remove(struct platform_device *pdev) +{ + struct keypad_data *kp = platform_get_drvdata(pdev); + + input_unregister_device(kp->input_dev); + clk_put(kp->clk); + iounmap(kp->regs); + release_mem_region(kp->res->start, resource_size(kp->res)); + platform_set_drvdata(pdev, NULL); + kfree(kp->keycodes); + kfree(kp); + + return 0; +} + +static struct platform_driver keypad_driver = { + .probe = keypad_probe, + .remove = keypad_remove, + .driver.name = "tnetv107x-keypad", + .driver.owner = THIS_MODULE, +}; + +static int __init keypad_init(void) +{ + return platform_driver_register(&keypad_driver); +} + +static void __exit keypad_exit(void) +{ + platform_driver_unregister(&keypad_driver); +} + +module_init(keypad_init); +module_exit(keypad_exit); + +MODULE_AUTHOR("Cyril Chemparathy"); +MODULE_DESCRIPTION("TNETV107X Keypad Driver"); +MODULE_ALIAS("platform: tnetv107x-keypad"); +MODULE_LICENSE("GPL"); -- 1.7.0.4 From cyril at ti.com Thu Sep 16 14:54:39 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 16 Sep 2010 15:54:39 -0400 Subject: [PATCH v2 0/5] add tnetv107x input drivers Message-ID: <1284666884-10374-1-git-send-email-cyril@ti.com> Texas Instruments' TNETV107X is an ARM1176 based SoC, with on-chip touchscreen and keypad controllers. This patch series adds drivers for these controllers. Changes between v1 and v2: 1. Cleaned up platform data needs by reusing matrix keypad pdata 2. Eliminated calibration code from touch driver 3. Relocated h/w init code to open and close 4. Other minor cleanups Cyril Chemparathy (5): input: add driver for tnetv107x on-chip keypad controller davinci: add tnetv107x keypad platform device davinci: add keypad config for tnetv107x evm board input: add driver for tnetv107x touchscreen controller davinci: add tnetv107x touchscreen platform device arch/arm/mach-davinci/board-tnetv107x-evm.c | 56 ++++ arch/arm/mach-davinci/devices-tnetv107x.c | 50 +++ arch/arm/mach-davinci/include/mach/tnetv107x.h | 3 + drivers/input/keyboard/Kconfig | 9 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/tnetv107x-keypad.c | 329 +++++++++++++++++++ drivers/input/touchscreen/Kconfig | 9 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/tnetv107x-ts.c | 401 ++++++++++++++++++++++++ 9 files changed, 859 insertions(+), 0 deletions(-) create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c From cyril at ti.com Thu Sep 16 14:54:42 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 16 Sep 2010 15:54:42 -0400 Subject: [PATCH v2 3/5] davinci: add keypad config for tnetv107x evm board In-Reply-To: <1284666884-10374-1-git-send-email-cyril@ti.com> References: <1284666884-10374-1-git-send-email-cyril@ti.com> Message-ID: <1284666884-10374-4-git-send-email-cyril@ti.com> This patch adds evm board specific keymap definitions and controller configuration data for on-chip keypad controller on tnetv107x silicon. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/board-tnetv107x-evm.c | 56 +++++++++++++++++++++++++++ 1 files changed, 56 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c index fe2a9d9..5afa8fc 100644 --- a/arch/arm/mach-davinci/board-tnetv107x-evm.c +++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c @@ -23,6 +23,9 @@ #include #include #include +#include +#include + #include #include @@ -141,10 +144,63 @@ static struct davinci_uart_config serial_config __initconst = { .enabled_uarts = BIT(1), }; +static const uint32_t keymap[] = { + KEY(0, 0, KEY_NUMERIC_1), + KEY(0, 1, KEY_NUMERIC_2), + KEY(0, 2, KEY_NUMERIC_3), + KEY(0, 3, KEY_FN_F1), + KEY(0, 4, KEY_MENU), + + KEY(1, 0, KEY_NUMERIC_4), + KEY(1, 1, KEY_NUMERIC_5), + KEY(1, 2, KEY_NUMERIC_6), + KEY(1, 3, KEY_UP), + KEY(1, 4, KEY_FN_F2), + + KEY(2, 0, KEY_NUMERIC_7), + KEY(2, 1, KEY_NUMERIC_8), + KEY(2, 2, KEY_NUMERIC_9), + KEY(2, 3, KEY_LEFT), + KEY(2, 4, KEY_ENTER), + + KEY(3, 0, KEY_NUMERIC_STAR), + KEY(3, 1, KEY_NUMERIC_0), + KEY(3, 2, KEY_NUMERIC_POUND), + KEY(3, 3, KEY_DOWN), + KEY(3, 4, KEY_RIGHT), + + KEY(4, 0, KEY_FN_F3), + KEY(4, 1, KEY_FN_F4), + KEY(4, 2, KEY_MUTE), + KEY(4, 3, KEY_HOME), + KEY(4, 4, KEY_BACK), + + KEY(5, 0, KEY_VOLUMEDOWN), + KEY(5, 1, KEY_VOLUMEUP), + KEY(5, 2, KEY_F1), + KEY(5, 3, KEY_F2), + KEY(5, 4, KEY_F3), +}; + +static const struct matrix_keymap_data keymap_data = { + .keymap = keymap, + .keymap_size = ARRAY_SIZE(keymap), +}; + +static struct matrix_keypad_platform_data keypad_config = { + .keymap_data = &keymap_data, + .num_row_gpios = 6, + .num_col_gpios = 5, + .debounce_ms = 0, /* minimum */ + .active_low = 0, /* pull up realization */ + .no_autorepeat = 0, +}; + static struct tnetv107x_device_info evm_device_info __initconst = { .serial_config = &serial_config, .mmc_config[1] = &mmc_config, /* controller 1 */ .nand_config[0] = &nand_config, /* chip select 0 */ + .keypad_config = &keypad_config, }; static __init void tnetv107x_evm_board_init(void) -- 1.7.0.4 From cyril at ti.com Thu Sep 16 14:54:41 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 16 Sep 2010 15:54:41 -0400 Subject: [PATCH v2 2/5] davinci: add tnetv107x keypad platform device In-Reply-To: <1284666884-10374-1-git-send-email-cyril@ti.com> References: <1284666884-10374-1-git-send-email-cyril@ti.com> Message-ID: <1284666884-10374-3-git-send-email-cyril@ti.com> This patch adds a platform device definition for tnetv107x's keypad controller. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/devices-tnetv107x.c | 30 ++++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/tnetv107x.h | 3 ++ 2 files changed, 33 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c index 2718a3a..086269f 100644 --- a/arch/arm/mach-davinci/devices-tnetv107x.c +++ b/arch/arm/mach-davinci/devices-tnetv107x.c @@ -33,6 +33,7 @@ #define TNETV107X_WDOG_BASE 0x08086700 #define TNETV107X_SDIO0_BASE 0x08088700 #define TNETV107X_SDIO1_BASE 0x08088800 +#define TNETV107X_KEYPAD_BASE 0x08088a00 #define TNETV107X_ASYNC_EMIF_CNTRL_BASE 0x08200000 #define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE 0x30000000 #define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE 0x40000000 @@ -298,6 +299,30 @@ static int __init nand_init(int chipsel, struct davinci_nand_pdata *data) return platform_device_register(pdev); } +static struct resource keypad_resources[] = { + { + .start = TNETV107X_KEYPAD_BASE, + .end = TNETV107X_KEYPAD_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_TNETV107X_KEYPAD, + .flags = IORESOURCE_IRQ, + .name = "press", + }, + { + .start = IRQ_TNETV107X_KEYPAD_FREE, + .flags = IORESOURCE_IRQ, + .name = "release", + }, +}; + +static struct platform_device keypad_device = { + .name = "tnetv107x-keypad", + .num_resources = ARRAY_SIZE(keypad_resources), + .resource = keypad_resources, +}; + void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) { int i; @@ -317,4 +342,9 @@ void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) for (i = 0; i < 4; i++) if (info->nand_config[i]) nand_init(i, info->nand_config[i]); + + if (info->keypad_config) { + keypad_device.dev.platform_data = info->keypad_config; + platform_device_register(&keypad_device); + } } diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h index c720647..5a681d8 100644 --- a/arch/arm/mach-davinci/include/mach/tnetv107x.h +++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h @@ -33,6 +33,8 @@ #ifndef __ASSEMBLY__ #include +#include + #include #include #include @@ -41,6 +43,7 @@ struct tnetv107x_device_info { struct davinci_uart_config *serial_config; struct davinci_mmc_config *mmc_config[2]; /* 2 controllers */ struct davinci_nand_pdata *nand_config[4]; /* 4 chipsels */ + struct matrix_keypad_platform_data *keypad_config; }; extern struct platform_device tnetv107x_wdt_device; -- 1.7.0.4 From cyril at ti.com Thu Sep 16 14:54:44 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 16 Sep 2010 15:54:44 -0400 Subject: [PATCH v2 5/5] davinci: add tnetv107x touchscreen platform device In-Reply-To: <1284666884-10374-1-git-send-email-cyril@ti.com> References: <1284666884-10374-1-git-send-email-cyril@ti.com> Message-ID: <1284666884-10374-6-git-send-email-cyril@ti.com> This patch adds a platform device definition for tnetv107x's touchscreen controller. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/devices-tnetv107x.c | 20 ++++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c index 086269f..c9a86d8 100644 --- a/arch/arm/mach-davinci/devices-tnetv107x.c +++ b/arch/arm/mach-davinci/devices-tnetv107x.c @@ -31,6 +31,7 @@ #define TNETV107X_TPTC0_BASE 0x01c10000 #define TNETV107X_TPTC1_BASE 0x01c10400 #define TNETV107X_WDOG_BASE 0x08086700 +#define TNETV107X_TSC_BASE 0x08088500 #define TNETV107X_SDIO0_BASE 0x08088700 #define TNETV107X_SDIO1_BASE 0x08088800 #define TNETV107X_KEYPAD_BASE 0x08088a00 @@ -323,12 +324,31 @@ static struct platform_device keypad_device = { .resource = keypad_resources, }; +static struct resource tsc_resources[] = { + { + .start = TNETV107X_TSC_BASE, + .end = TNETV107X_TSC_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_TNETV107X_TSC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device tsc_device = { + .name = "tnetv107x-ts", + .num_resources = ARRAY_SIZE(tsc_resources), + .resource = tsc_resources, +}; + void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) { int i; platform_device_register(&edma_device); platform_device_register(&tnetv107x_wdt_device); + platform_device_register(&tsc_device); if (info->serial_config) davinci_serial_init(info->serial_config); -- 1.7.0.4 From cyril at ti.com Thu Sep 16 14:54:43 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Thu, 16 Sep 2010 15:54:43 -0400 Subject: [PATCH v2 4/5] input: add driver for tnetv107x touchscreen controller In-Reply-To: <1284666884-10374-1-git-send-email-cyril@ti.com> References: <1284666884-10374-1-git-send-email-cyril@ti.com> Message-ID: <1284666884-10374-5-git-send-email-cyril@ti.com> This patch adds support for tnetv107x's on-chip touchscreen controller. Signed-off-by: Cyril Chemparathy --- drivers/input/touchscreen/Kconfig | 9 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/tnetv107x-ts.c | 401 ++++++++++++++++++++++++++++++ 3 files changed, 411 insertions(+), 0 deletions(-) create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 0069d97..8d32028 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -328,6 +328,15 @@ config TOUCHSCREEN_MIGOR To compile this driver as a module, choose M here: the module will be called migor_ts. +config TOUCHSCREEN_TNETV107X + tristate "TI TNETV107X touchscreen support" + depends on ARCH_DAVINCI_TNETV107X + help + Say Y here if you want to use the TNETV107X touchscreen. + + To compile this driver as a module, choose M here: the + module will be called tnetv107x-ts. + config TOUCHSCREEN_TOUCHRIGHT tristate "Touchright serial touchscreen" select SERIO diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 28217e1..d41a964 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o +obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c new file mode 100644 index 0000000..0d4dbc4 --- /dev/null +++ b/drivers/input/touchscreen/tnetv107x-ts.c @@ -0,0 +1,401 @@ +/* + * Texas Instruments TNETV107X Touchscreen Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define TSC_PENUP_POLL (HZ / 5) +#define IDLE_TIMEOUT 100 /* msec */ + +/* + * The first and last samples of a touch interval are usually garbage and need + * to be filtered out with these devices. The following definitions control + * the number of samples skipped. + */ +#define TSC_HEAD_SKIP 1 +#define TSC_TAIL_SKIP 1 +#define TSC_SKIP (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1) +#define TSC_SAMPLES (TSC_SKIP + 1) + +/* Register Offsets */ +struct tsc_regs { + u32 rev; + u32 tscm; + u32 bwcm; + u32 swc; + u32 adcchnl; + u32 adcdata; + u32 chval[4]; +}; + +/* TSC Mode Configuration Register (tscm) bits */ +#define WMODE BIT(0) +#define TSKIND BIT(1) +#define ZMEASURE_EN BIT(2) +#define IDLE BIT(3) +#define TSC_EN BIT(4) +#define STOP BIT(5) +#define ONE_SHOT BIT(6) +#define SINGLE BIT(7) +#define AVG BIT(8) +#define AVGNUM(x) (((x) & 0x03) << 9) +#define PVSTC(x) (((x) & 0x07) << 11) +#define PON BIT(14) +#define PONBG BIT(15) +#define AFERST BIT(16) + +/* ADC DATA Capture Register bits */ +#define DATA_VALID BIT(16) + +/* Register Access Macros */ +#define tsc_read(ts, reg) __raw_readl(&(ts)->regs->reg) +#define tsc_write(ts, reg, val) __raw_writel(val, &(ts)->regs->reg); +#define tsc_set_bits(ts, reg, val) \ + tsc_write(ts, reg, tsc_read(ts, reg) | (val)) +#define tsc_clr_bits(ts, reg, val) \ + tsc_write(ts, reg, tsc_read(ts, reg) & ~(val)) + +struct sample { + int x, y, p; +}; + +struct tsc_data { + struct input_dev *input_dev; + struct resource *res; + struct tsc_regs __iomem *regs; + struct timer_list timer; + spinlock_t lock; + struct clk *clk; + struct device *dev; + int sample_count; + struct sample samples[TSC_SAMPLES]; + int tsc_irq; +}; + +static int tsc_read_sample(struct tsc_data *ts, struct sample* sample) +{ + int x, y, z1, z2, t, p = 0; + u32 val; + + val = tsc_read(ts, chval[0]); + if (val & DATA_VALID) + x = val & 0xffff; + else + return -EINVAL; + + y = tsc_read(ts, chval[1]) & 0xffff; + z1 = tsc_read(ts, chval[2]) & 0xffff; + z2 = tsc_read(ts, chval[3]) & 0xffff; + + if (z1) { + t = ((600 * x) * (z2 - z1)); + p = t / (u32) (z1 << 12); + if (p < 0) + p = 0; + } + + sample->x = x; + sample->y = y; + sample->p = p; + + return 0; +} + +static void tsc_poll(unsigned long data) +{ + struct tsc_data *ts = (struct tsc_data *)data; + unsigned long flags; + int i, val, x, y, p; + + spin_lock_irqsave(&ts->lock, flags); + + if (ts->sample_count >= TSC_SKIP) { + input_report_abs(ts->input_dev, ABS_PRESSURE, 0); + input_report_key(ts->input_dev, BTN_TOUCH, 0); + input_sync(ts->input_dev); + } else if (ts->sample_count > 0) { + /* + * A touch event lasted less than our skip count. Salvage and + * report anyway. + */ + for (i = 0, val = 0; i < ts->sample_count; i++) + val += ts->samples[i].x; + x = val / ts->sample_count; + + for (i = 0, val = 0; i < ts->sample_count; i++) + val += ts->samples[i].y; + y = val / ts->sample_count; + + for (i = 0, val = 0; i < ts->sample_count; i++) + val += ts->samples[i].p; + p = val / ts->sample_count; + + input_report_abs(ts->input_dev, ABS_X, x); + input_report_abs(ts->input_dev, ABS_Y, y); + input_report_abs(ts->input_dev, ABS_PRESSURE, p); + input_report_key(ts->input_dev, BTN_TOUCH, 1); + input_sync(ts->input_dev); + } + + ts->sample_count = 0; + + spin_unlock_irqrestore(&ts->lock, flags); +} + +static irqreturn_t tsc_irq(int irq, void *dev_id) +{ + struct tsc_data *ts = (struct tsc_data *)dev_id; + struct sample *sample; + int index; + + spin_lock(&ts->lock); + + index = ts->sample_count % TSC_SAMPLES; + sample = &ts->samples[index]; + if (tsc_read_sample(ts, sample) >= 0) { + ++ts->sample_count; + + if (ts->sample_count < TSC_SKIP) + goto done; + + index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES; + sample = &ts->samples[index]; + + input_report_abs(ts->input_dev, ABS_X, sample->x); + input_report_abs(ts->input_dev, ABS_Y, sample->y); + input_report_abs(ts->input_dev, ABS_PRESSURE, sample->p); + if (ts->sample_count == TSC_SKIP) + input_report_key(ts->input_dev, BTN_TOUCH, 1); + input_sync(ts->input_dev); +done: + mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL); + } + + spin_unlock(&ts->lock); + return IRQ_HANDLED; +} + +static int tsc_start(struct input_dev *dev) +{ + struct tsc_data *ts = input_get_drvdata(dev); + unsigned long timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT); + u32 val; + int error; + + clk_enable(ts->clk); + + /* Go to idle mode, before any initialization */ + while (time_after(timeout, jiffies)) { + if (tsc_read(ts, tscm) & IDLE) + break; + } + + if (time_before(timeout, jiffies)) { + dev_warn(ts->dev, "timeout waiting for idle\n"); + clk_disable(ts->clk); + return -EIO; + } + + /* Configure TSC Control register*/ + val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN); + tsc_write(ts, tscm, val); + + /* Bring TSC out of reset: Clear AFE reset bit */ + val &= ~(AFERST); + tsc_write(ts, tscm, val); + udelay(10); + + /* Configure all pins for hardware control*/ + tsc_write(ts, bwcm, 0); + + /* Finally enable the TSC */ + tsc_set_bits(ts, tscm, TSC_EN); + + error = request_irq(ts->tsc_irq, tsc_irq, 0, "tnetv107x-ts", ts); + if (error < 0) { + dev_err(ts->dev, "Could not allocate ts irq\n"); + clk_disable(ts->clk); + return error; + } + + return 0; +} + +static void tsc_stop(struct input_dev *dev) +{ + struct tsc_data *ts = input_get_drvdata(dev); + + tsc_clr_bits(ts, tscm, TSC_EN); + del_timer_sync(&ts->timer); + free_irq(ts->tsc_irq, ts); + clk_disable(ts->clk); +} + +static int __devinit tsc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tsc_data *ts; + int error = 0; + u32 rev = 0; + + ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL); + if (!ts) { + dev_err(dev, "cannot allocate device info\n"); + return -ENOMEM; + } + + ts->dev = dev; + spin_lock_init(&ts->lock); + setup_timer(&ts->timer, tsc_poll, (unsigned long)ts); + platform_set_drvdata(pdev, ts); + + ts->tsc_irq = platform_get_irq(pdev, 0); + if (ts->tsc_irq < 0) { + dev_err(dev, "cannot determine device interrupt\n"); + error = -ENODEV; + goto error; + } + + ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!ts->res) { + dev_err(dev, "cannot determine register area\n"); + error = -ENODEV; + goto error; + } + + if (!request_mem_region(ts->res->start, resource_size(ts->res), + pdev->name)) { + dev_err(dev, "cannot claim register memory\n"); + ts->res = NULL; + error = -EINVAL; + goto error; + } + + ts->regs = ioremap(ts->res->start, resource_size(ts->res)); + if (!ts->regs) { + dev_err(dev, "cannot map register memory\n"); + error = -ENOMEM; + goto error; + } + + ts->clk = clk_get(dev, NULL); + if (!ts->clk) { + dev_err(dev, "cannot claim device clock\n"); + error = -EINVAL; + goto error; + } + + ts->input_dev = input_allocate_device(); + if (!ts->input_dev) { + dev_err(dev, "cannot allocate input device\n"); + error = -ENOMEM; + goto error; + } + input_set_drvdata(ts->input_dev, ts); + + ts->input_dev->name = pdev->name; + ts->input_dev->id.bustype = BUS_HOST; + ts->input_dev->dev.parent = &pdev->dev; + ts->input_dev->open = tsc_start; + ts->input_dev->close = tsc_stop; + + clk_enable(ts->clk); + rev = tsc_read(ts, rev); + ts->input_dev->id.product = ((rev >> 8) & 0x07); + ts->input_dev->id.version = ((rev >> 16) & 0xfff); + clk_disable(ts->clk); + + set_bit(EV_KEY, ts->input_dev->evbit); + set_bit(EV_ABS, ts->input_dev->evbit); + set_bit(BTN_TOUCH, ts->input_dev->keybit); + set_bit(ABS_X, ts->input_dev->absbit); + set_bit(ABS_Y, ts->input_dev->absbit); + set_bit(ABS_PRESSURE, ts->input_dev->absbit); + + input_set_abs_params(ts->input_dev, ABS_X, 0, 0xffff, 5, 0); + input_set_abs_params(ts->input_dev, ABS_Y, 0, 0xffff, 5, 0); + input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0); + + error = input_register_device(ts->input_dev); + if (error < 0) { + dev_err(dev, "failed input device registration\n"); + goto error; + } + + return 0; + +error: + if (ts->clk) + clk_put(ts->clk); + if (ts->regs) + iounmap(ts->regs); + if (ts->res) + release_mem_region(ts->res->start, resource_size(ts->res)); + if (ts->input_dev) + input_free_device(ts->input_dev); + platform_set_drvdata(pdev, NULL); + kfree(ts); + + return error; +} + +static int __devexit tsc_remove(struct platform_device *pdev) +{ + struct tsc_data *ts = platform_get_drvdata(pdev); + + input_unregister_device(ts->input_dev); + clk_put(ts->clk); + iounmap(ts->regs); + release_mem_region(ts->res->start, resource_size(ts->res)); + platform_set_drvdata(pdev, NULL); + kfree(ts); + + return 0; +} + +static struct platform_driver tsc_driver = { + .probe = tsc_probe, + .remove = tsc_remove, + .driver.name = "tnetv107x-ts", + .driver.owner = THIS_MODULE, +}; + +static int __init tsc_init(void) +{ + return platform_driver_register(&tsc_driver); +} + +static void __exit tsc_exit(void) +{ + platform_driver_unregister(&tsc_driver); +} + +module_init(tsc_init); +module_exit(tsc_exit); + +MODULE_AUTHOR("Cyril Chemparathy"); +MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); +MODULE_ALIAS("platform: tnetv107x-ts"); +MODULE_LICENSE("GPL"); -- 1.7.0.4 From troy.kisky at boundarydevices.com Thu Sep 16 15:28:50 2010 From: troy.kisky at boundarydevices.com (Troy Kisky) Date: Thu, 16 Sep 2010 13:28:50 -0700 Subject: [PATCH] i2c: davinci: Fix race when setting up for TX In-Reply-To: <87pqwda8ub.fsf@deeprootsystems.com> References: <1284632480-24035-1-git-send-email-jon.povey@racelogic.co.uk> <87pqwda8ub.fsf@deeprootsystems.com> Message-ID: <4C927E02.10905@boundarydevices.com> On 9/16/2010 10:37 AM, Kevin Hilman wrote: > Jon Povey writes: > >> When setting up to transmit, a race exists between the ISR and >> i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. >> This is mostly visible for transmits > 1 byte long. >> >> The ISR may run at any time after the mode register has been set. >> While we are setting up and loading the first byte, protect this critical >> section from the ISR with a spinlock. >> >> The RX path or zero-length transmits do not need this locking. >> >> Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 >> >> Signed-off-by: Jon Povey > > This looks like a good fix. > > Anyone else care to test on other platforms and add a 'Tested-by'? > > Thanks, > > Kevin > >> --- >> I suspect this hasn't shown up for others using single-byte transmits as the >> interrupt tends to either run entirely before or entirely after this block >> in i2c_davinci_xfer_msg(): >> >> /* >> * First byte should be set here, not after interrupt, >> * because transmit-data-ready interrupt can come before >> * NACK-interrupt during sending of previous message and >> * ICDXR may have wrong data >> */ >> if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { >> davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); >> dev->buf_len--; >> } >> >> Often the entire message would be sent before that test was executed >> (observed with LED wiggling and a logic analyser), so dev->buf_len would >> be untrue and things merrily went on their way. That seems to be counter >> to the intent in the comment. >> >> I tried some fiddling around reordering the register loads but couldn't >> get things reliable so stuck in a spinlock. Better solutions welcome. >> >> P.S.: Having run into the the bus reset code a lot during testing, I >> am pretty sure that that generic_i2c_clock_pulse() does NOTHING due to >> pinmuxing, at least on DM355, it is misleading and may be better >> replaced with a comment saying "It would be great to toggle SCL here". >> >> drivers/i2c/busses/i2c-davinci.c | 21 ++++++++++++++++++++- >> 1 files changed, 20 insertions(+), 1 deletions(-) >> >> diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c >> index 2222c87..43aa55d 100644 >> --- a/drivers/i2c/busses/i2c-davinci.c >> +++ b/drivers/i2c/busses/i2c-davinci.c >> @@ -107,6 +107,7 @@ struct davinci_i2c_dev { >> u8 *buf; >> size_t buf_len; >> int irq; >> + spinlock_t lock; >> int stop; >> u8 terminate; >> struct i2c_adapter adapter; >> @@ -312,6 +313,8 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) >> u32 flag; >> u16 w; >> int r; >> + unsigned long flags; >> + int preload = 0; >> >> if (!pdata) >> pdata = &davinci_i2c_platform_data_default; >> @@ -347,6 +350,15 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) >> flag &= ~DAVINCI_I2C_MDR_STP; >> } >> >> + /* >> + * When transmitting, lock ISR out to avoid it racing on the buffer and >> + * DXR register before we are done >> + */ >> + if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { >> + preload = 1; >> + spin_lock_irqsave(&dev->lock, flags); >> + } >> + >> /* Enable receive or transmit interrupts */ >> w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); Maybe you can write 0 to IMR here, and move this interrupt enable (IMR) write to after the DXR write. That would seem a better patch. >> if (msg->flags & I2C_M_RD) >> @@ -366,13 +378,15 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) >> * NACK-interrupt during sending of previous message and >> * ICDXR may have wrong data >> */ >> - if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { >> + if (preload) { >> davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); >> dev->buf_len--; >> + spin_unlock_irqrestore(&dev->lock, flags); >> } >> >> r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, >> dev->adapter.timeout); >> + >> if (r == 0) { >> dev_err(dev->dev, "controller timed out\n"); >> i2c_recover_bus(dev); >> @@ -490,6 +504,8 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) >> int count = 0; >> u16 w; >> >> + spin_lock(&dev->lock); >> + >> while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) { >> dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat); >> if (count++ == 100) { >> @@ -579,6 +595,8 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) >> } >> } >> >> + spin_unlock(&dev->lock); >> + >> return count ? IRQ_HANDLED : IRQ_NONE; >> } >> >> @@ -662,6 +680,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) >> goto err_release_region; >> } >> >> + spin_lock_init(&dev->lock); >> init_completion(&dev->cmd_complete); >> #ifdef CONFIG_CPU_FREQ >> init_completion(&dev->xfr_complete); > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source at linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source > From michael.williamson at criticallink.com Thu Sep 16 16:48:36 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Thu, 16 Sep 2010 17:48:36 -0400 Subject: [PATCH v2] davinci: MityDSP-L138/MityARM-1808 read MAC address from I2C Prom Message-ID: <1284673716-4848-1-git-send-email-michael.williamson@criticallink.com> For the MityDSP-L138/MityARM-1808 SOMS, read the factory assigned MAC address from the onboard I2C EPROM and assign it to the emac device during platform initialization. Signed-off-by: Michael Williamson --- Patch is against e90c3a5344683351c7a37f097f1e17d50ee2063c of linux-davinci tree. Changes since v1: 1) updated sdtint types to kernel types per comments 2) Added prefix to warning/info messages 3) Sanity check MAC address and issue warning if bad 4) replace hardcoded 6 with ETH_ALEN in memcpy arch/arm/mach-davinci/board-mityomapl138.c | 62 ++++++++++++++++++++++++++++ 1 files changed, 62 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index 6f12a18..1fff0bb 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -25,6 +27,65 @@ #include #define MITYOMAPL138_PHY_ID "0:03" + +#define FACTORY_CONFIG_MAGIC 0x012C0138 +#define FACTORY_CONFIG_VERSION 0x00010001 + +/* Data Held in On-Board I2C device */ +struct factory_config { + u32 magic; + u32 version; + u8 mac[6]; + u32 fpga_type; + u32 spare; + u32 serialnumber; + char partnum[32]; +}; + +static struct factory_config factory_config; + +static void read_factory_config(struct memory_accessor *a, void *context) +{ + int ret; + struct davinci_soc_info *soc_info = &davinci_soc_info; + + ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config)); + if (ret != sizeof(struct factory_config)) { + pr_warning("MityOMAPL138: Read Factory Config Failed: %d\n", + ret); + return; + } + + if (factory_config.magic != FACTORY_CONFIG_MAGIC) { + pr_warning("MityOMAPL138: Factory Config Magic Wrong (%X)\n", + factory_config.magic); + return; + } + + if (factory_config.version != FACTORY_CONFIG_VERSION) { + pr_warning("MityOMAPL138: Factory Config Version Wrong (%X)\n", + factory_config.version); + return; + } + + pr_info("MityOMAPL138: Found MAC = %pM\n", factory_config.mac); + pr_info("MityOMAPL138: Part Number = %s\n", factory_config.partnum); + if (is_valid_ether_addr(factory_config.mac)) + memcpy(&soc_info->emac_pdata->mac_addr[0], + &factory_config.mac[0], ETH_ALEN); + else + pr_warning("MityOMAPL138: Invalid MAC found " + "in factory config block\n"); +} + +static struct at24_platform_data mityomapl138_fd_chip = { + .byte_len = 256, + .page_size = 8, + .flags = AT24_FLAG_READONLY | AT24_FLAG_IRUGO, + .setup = read_factory_config, + .context = NULL, +}; + static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = { .bus_freq = 100, /* kHz */ .bus_delay = 0, /* usec */ @@ -151,6 +212,7 @@ static struct i2c_board_info __initdata mityomap_tps65023_info[] = { }, { I2C_BOARD_INFO("24c02", 0x50), + .platform_data = &mityomapl138_fd_chip, }, }; -- 1.7.0.4 From jon.povey at racelogic.co.uk Thu Sep 16 21:46:47 2010 From: jon.povey at racelogic.co.uk (Jon Povey) Date: Fri, 17 Sep 2010 11:46:47 +0900 Subject: [PATCH v2] i2c: davinci: Fix race when setting up for TX Message-ID: <1284691607-9697-1-git-send-email-jon.povey@racelogic.co.uk> When setting up to transmit, a race exists between the ISR and i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. This is mostly visible for transmits > 1 byte long. The hardware starts sending immediately that MDR is loaded. IMR trickery doesn't work because if we start sending, finish the first byte and an XRDY event occurs before we load IMR to unmask it, we never get an interrupt, and we timeout. Move the MDR load after DXR,IMR loads to avoid this race without locking. Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 Signed-off-by: Jon Povey --- Troy, thanks for the input. I tried reordering the IMR load before but got occasional timeouts. Went back to the logic analyser today and worked out why, see above comment in the commit message. Moving the MDR load seems to fix things without locking, much neater and tiny patch. As I understand it we can be confident inside i2c_davinci_xfer_msg() that the peripheral is not busy sending or receiving something else, I had a look at the other interrupt sources in the datasheet and this seems safe enough. I'm not sure what the correct thing to do for followup message IDs here.. My original email? Troy's? Clues welcome for next time. drivers/i2c/busses/i2c-davinci.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 72df4af..baa5209 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -349,9 +349,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) dev->terminate = 0; - /* write the data into mode register */ - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); - /* * First byte should be set here, not after interrupt, * because transmit-data-ready interrupt can come before @@ -371,6 +368,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) w |= DAVINCI_I2C_IMR_XRDY; davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w); + /* write the data into mode register; start transmitting */ + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); + r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, dev->adapter.timeout); if (r == 0) { -- 1.6.3.3 From jon.povey at racelogic.co.uk Thu Sep 16 22:02:11 2010 From: jon.povey at racelogic.co.uk (Jon Povey) Date: Fri, 17 Sep 2010 12:02:11 +0900 Subject: [PATCH v3] i2c: davinci: Fix race when setting up for TX In-Reply-To: <1284691607-9697-1-git-send-email-jon.povey@racelogic.co.uk> References: <1284691607-9697-1-git-send-email-jon.povey@racelogic.co.uk> Message-ID: <1284692531-10100-1-git-send-email-jon.povey@racelogic.co.uk> When setting up to transmit, a race exists between the ISR and i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. This is mostly visible for transmits > 1 byte long. The hardware starts sending immediately that MDR is loaded. IMR trickery doesn't work because if we start sending, finish the first byte and an XRDY event occurs before we load IMR to unmask it, we never get an interrupt, and we timeout. Move the MDR load after DXR,IMR loads to avoid this race without locking. Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 Signed-off-by: Jon Povey --- Oops, v2 was based on the wrong version. Rebased so this should apply against mainline. Troy, thanks for the input. I tried reordering the IMR load before but got occasional timeouts. Went back to the logic analyser today and worked out why, see above comment in the commit message. Moving the MDR load seems to fix things without locking, much neater and tiny patch. As I understand it we can be confident inside i2c_davinci_xfer_msg() that the peripheral is not busy sending or receiving something else, I had a look at the other interrupt sources in the datasheet and this seems safe enough. I'm not sure what the correct thing to do for followup message IDs here.. My original email? Troy's? Clues welcome for next time. drivers/i2c/busses/i2c-davinci.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 2222c87..b8feac5 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -357,9 +357,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) dev->terminate = 0; - /* write the data into mode register */ - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); - /* * First byte should be set here, not after interrupt, * because transmit-data-ready interrupt can come before @@ -371,6 +368,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) dev->buf_len--; } + /* write the data into mode register; start transmitting */ + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); + r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, dev->adapter.timeout); if (r == 0) { -- 1.6.3.3 From sugumar at ti.com Fri Sep 17 07:43:27 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Fri, 17 Sep 2010 18:13:27 +0530 Subject: [PATCH v4 1/2] davinci: Add generic PWM support for PWM control In-Reply-To: <1284028849-16680-1-git-send-email-sugumar@ti.com> References: <1284028849-16680-1-git-send-email-sugumar@ti.com> Message-ID: <00e401cb5665$f5c00980$e1401c80$@com> On Thu, Sep 09, 2010 at 16:10:49, Sugumar Natarajan wrote: > This patch adds generic PWM support where it maintains the list of PWM control devices that can be added or removed. > > The interface provides a list of functions that can be accessed by the PWM control driver module and the generic PWM driver. > > The PWM control driver module such as eCAP uses the interface to register and add itself to the list as a PWM control device. > The generic PWM driver uses the interface to search for a PWM control device and if present, uses the device for PWM control. > > Signed-off-by: Sugumar Natarajan > --- Kevin, I have implemented the eHRPWM driver and the basic pwm infrastructure has undergone some changes. So please don't merge these changes. I will send the updated patch soon. > Changes since v2: > a) pwm_config_device callback is made more flexible. > b) pwm_request function code has been made more cleaner. > c) Sanity-check/warn has been included. > > arch/arm/mach-davinci/Makefile | 3 + > arch/arm/mach-davinci/davinci_pwm.c | 130 ++++++++++++++++++++++ > arch/arm/mach-davinci/include/mach/davinci_pwm.h | 32 ++++++ > 3 files changed, 165 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/davinci_pwm.c > create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h > > diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index a7a70d1..90ca821 100644 > --- a/arch/arm/mach-davinci/Makefile > +++ b/arch/arm/mach-davinci/Makefile > @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o > obj-$(CONFIG_CPU_FREQ) += cpufreq.o > obj-$(CONFIG_CPU_IDLE) += cpuidle.o > obj-$(CONFIG_SUSPEND) += pm.o sleep.o > + > +# Generic PWM control support > +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o > diff --git a/arch/arm/mach-davinci/davinci_pwm.c b/arch/arm/mach-davinci/davinci_pwm.c > new file mode 100644 > index 0000000..c2b8b9a > --- /dev/null > +++ b/arch/arm/mach-davinci/davinci_pwm.c > @@ -0,0 +1,130 @@ > +/* > + * Copyright (C) 2010 Texas Instruments Incorporated - > +http://www.ti.com/ > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed .as is. WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) { > + unsigned int clock_freq; > + unsigned int period_cycles; > + unsigned int duty_cycle; > + int ret = 0; > + > + if (WARN_ON(!pwm)) > + return -EINVAL; > + > + if (pwm->pwm_config_device) { > + if (!period_ns || duty_ns > period_ns) > + return -EINVAL; > + > + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; > + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; > + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; > + ret = pwm->pwm_config_device(pwm, period_cycles, duty_cycle); > + } > + > + return ret; > +} > +EXPORT_SYMBOL(pwm_config); > + > +int pwm_enable(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return -EINVAL; > + > + return clk_enable(pwm->clk); > +} > +EXPORT_SYMBOL(pwm_enable); > + > +void pwm_disable(struct pwm_device *pwm) { > + if (WARN_ON(!pwm)) > + return; > + > + clk_disable(pwm->clk); > +} > +EXPORT_SYMBOL(pwm_disable); > + > +static DEFINE_MUTEX(pwm_lock); > +static LIST_HEAD(pwm_list); > + > +struct pwm_device *pwm_request(int pwm_id, const char *label) { > + struct pwm_device *pwm, *tmp_pwm = ERR_PTR(-ENOENT); > + > + mutex_lock(&pwm_lock); > + > + list_for_each_entry(pwm, &pwm_list, node) { > + if (pwm->pwm_id == pwm_id) { > + if (pwm->use_count == 0) { > + pwm->use_count++; > + pwm->label = label; > + } else { > + pwm = ERR_PTR(-EBUSY); > + } > + tmp_pwm = pwm; > + break; > + } > + } > + > + mutex_unlock(&pwm_lock); > + return tmp_pwm; > +} > +EXPORT_SYMBOL(pwm_request); > + > +void pwm_free(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return; > + > + mutex_lock(&pwm_lock); > + > + if (pwm->use_count) { > + pwm->use_count--; > + pwm->label = NULL; > + } else { > + dev_warn(&pwm->pdev->dev, "PWM device already freed\n"); > + } > + > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(pwm_free); > + > +void pwm_add(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return; > + > + mutex_lock(&pwm_lock); > + list_add_tail(&pwm->node, &pwm_list); > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(pwm_add); > + > +void pwm_remove(struct pwm_device *pwm) { > + if (WARN_ON(!pwm)) > + return; > + > + mutex_lock(&pwm_lock); > + list_del(&pwm->node); > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(pwm_remove); > diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h > new file mode 100644 > index 0000000..3b7a3c8 > --- /dev/null > +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h > @@ -0,0 +1,32 @@ > +/* > + * Copyright (C) 2010 Texas Instruments Incorporated - > +http://www.ti.com/ > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed .as is. WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + */ > + > +#ifndef __DAVINCI_PWM_H > +#define __DAVINCI_PWM_H > + > +struct pwm_device { > + struct list_head node; > + struct platform_device *pdev; > + int (*pwm_config_device)(struct pwm_device *pwm, > + unsigned int period, unsigned int dutycycle); > + const char *label; > + struct clk *clk; > + unsigned int use_count; > + unsigned int pwm_id; > +}; > + > +void pwm_add(struct pwm_device *pwm); > +void pwm_remove(struct pwm_device *pwm); > + > +#endif > -- > 1.5.6 > From sugumar at ti.com Fri Sep 17 07:46:46 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Fri, 17 Sep 2010 18:16:46 +0530 Subject: [PATCH v4 1/2] davinci: Add generic PWM support for PWM control In-Reply-To: <1284028849-16680-1-git-send-email-sugumar@ti.com> References: <1284028849-16680-1-git-send-email-sugumar@ti.com> Message-ID: <00e501cb5666$6cedfc60$46c9f520$@com> -----Original Message----- From: Sugumar Natarajan [mailto:sugumar at ti.com] Sent: Thursday, September 09, 2010 4:11 PM To: davinci-linux-open-source at linux.davincidsp.com Cc: Sugumar Natarajan Subject: [PATCH v4 1/2] davinci: Add generic PWM support for PWM control This patch adds generic PWM support where it maintains the list of PWM control devices that can be added or removed. The interface provides a list of functions that can be accessed by the PWM control driver module and the generic PWM driver. The PWM control driver module such as eCAP uses the interface to register and add itself to the list as a PWM control device. The generic PWM driver uses the interface to search for a PWM control device and if present, uses the device for PWM control. Signed-off-by: Sugumar Natarajan --- Kevin, I have implemented the eHRPWM driver and the basic pwm infrastructure has undergone some changes. So please don't merge these changes. I will send the updated patch soon. Regards, N.Sugumar. Changes since v2: a) pwm_config_device callback is made more flexible. b) pwm_request function code has been made more cleaner. c) Sanity-check/warn has been included. arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/davinci_pwm.c | 130 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 32 ++++++ 3 files changed, 165 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/davinci_pwm.c create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index a7a70d1..90ca821 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_SUSPEND) += pm.o sleep.o + +# Generic PWM control support +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o diff --git a/arch/arm/mach-davinci/davinci_pwm.c b/arch/arm/mach-davinci/davinci_pwm.c new file mode 100644 index 0000000..c2b8b9a --- /dev/null +++ b/arch/arm/mach-davinci/davinci_pwm.c @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + unsigned int clock_freq; + unsigned int period_cycles; + unsigned int duty_cycle; + int ret = 0; + + if (WARN_ON(!pwm)) + return -EINVAL; + + if (pwm->pwm_config_device) { + if (!period_ns || duty_ns > period_ns) + return -EINVAL; + + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; + ret = pwm->pwm_config_device(pwm, period_cycles, duty_cycle); + } + + return ret; +} +EXPORT_SYMBOL(pwm_config); + +int pwm_enable(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return -EINVAL; + + return clk_enable(pwm->clk); +} +EXPORT_SYMBOL(pwm_enable); + +void pwm_disable(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + clk_disable(pwm->clk); +} +EXPORT_SYMBOL(pwm_disable); + +static DEFINE_MUTEX(pwm_lock); +static LIST_HEAD(pwm_list); + +struct pwm_device *pwm_request(int pwm_id, const char *label) +{ + struct pwm_device *pwm, *tmp_pwm = ERR_PTR(-ENOENT); + + mutex_lock(&pwm_lock); + + list_for_each_entry(pwm, &pwm_list, node) { + if (pwm->pwm_id == pwm_id) { + if (pwm->use_count == 0) { + pwm->use_count++; + pwm->label = label; + } else { + pwm = ERR_PTR(-EBUSY); + } + tmp_pwm = pwm; + break; + } + } + + mutex_unlock(&pwm_lock); + return tmp_pwm; +} +EXPORT_SYMBOL(pwm_request); + +void pwm_free(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + mutex_lock(&pwm_lock); + + if (pwm->use_count) { + pwm->use_count--; + pwm->label = NULL; + } else { + dev_warn(&pwm->pdev->dev, "PWM device already freed\n"); + } + + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_free); + +void pwm_add(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + mutex_lock(&pwm_lock); + list_add_tail(&pwm->node, &pwm_list); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_add); + +void pwm_remove(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + mutex_lock(&pwm_lock); + list_del(&pwm->node); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_remove); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h new file mode 100644 index 0000000..3b7a3c8 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __DAVINCI_PWM_H +#define __DAVINCI_PWM_H + +struct pwm_device { + struct list_head node; + struct platform_device *pdev; + int (*pwm_config_device)(struct pwm_device *pwm, + unsigned int period, unsigned int dutycycle); + const char *label; + struct clk *clk; + unsigned int use_count; + unsigned int pwm_id; +}; + +void pwm_add(struct pwm_device *pwm); +void pwm_remove(struct pwm_device *pwm); + +#endif -- 1.5.6 From sudhakar.raj at ti.com Fri Sep 17 08:09:56 2010 From: sudhakar.raj at ti.com (Sudhakar Rajashekhara) Date: Fri, 17 Sep 2010 18:39:56 +0530 Subject: [PATCH v3] i2c: davinci: Fix race when setting up for TX In-Reply-To: <1284692531-10100-1-git-send-email-jon.povey@racelogic.co.uk> References: <1284691607-9697-1-git-send-email-jon.povey@racelogic.co.uk> <1284692531-10100-1-git-send-email-jon.povey@racelogic.co.uk> Message-ID: <001201cb5669$a0200940$e0601bc0$@raj@ti.com> Hi, On Fri, Sep 17, 2010 at 08:32:11, Jon Povey wrote: > When setting up to transmit, a race exists between the ISR and > i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. > This is mostly visible for transmits > 1 byte long. > > The hardware starts sending immediately that MDR is loaded. IMR trickery > doesn't work because if we start sending, finish the first byte and an > XRDY event occurs before we load IMR to unmask it, we never get an > interrupt, and we timeout. > > Move the MDR load after DXR,IMR loads to avoid this race without locking. > > Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 > I remember I had some issues on OMAP-L138 with this fix, that's when I reverted to configuring ICMDR before writing to DXR (Please see here: https://patchwork.kernel.org/patch/75262/). I checked the BIOS I2C driver code for OMAP-L138 and there also we are configuring MDR before accessing DXR. Regards, Sudhakar From sshtylyov at mvista.com Fri Sep 17 08:34:34 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Fri, 17 Sep 2010 17:34:34 +0400 Subject: [PATCH v2] davinci: MityDSP-L138/MityARM-1808 read MAC address from I2C Prom In-Reply-To: <1284673716-4848-1-git-send-email-michael.williamson@criticallink.com> References: <1284673716-4848-1-git-send-email-michael.williamson@criticallink.com> Message-ID: <4C936E6A.2040701@mvista.com> Hello. Michael Williamson wrote: > For the MityDSP-L138/MityARM-1808 SOMS, read the factory assigned > MAC address from the onboard I2C EPROM and assign it to the emac > device during platform initialization. > Signed-off-by: Michael Williamson [...] > diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c > index 6f12a18..1fff0bb 100644 > --- a/arch/arm/mach-davinci/board-mityomapl138.c > +++ b/arch/arm/mach-davinci/board-mityomapl138.c > @@ -15,6 +15,8 @@ [...] > +static void read_factory_config(struct memory_accessor *a, void *context) > +{ [...] > + if (is_valid_ether_addr(factory_config.mac)) > + memcpy(&soc_info->emac_pdata->mac_addr[0], & and [0] are not needed. > + &factory_config.mac[0], ETH_ALEN); Same here. WBR, Sergei From michael.williamson at criticallink.com Fri Sep 17 08:56:06 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Fri, 17 Sep 2010 09:56:06 -0400 Subject: [PATCH v3] davinci: MityDSP-L138/MityARM-1808 read MAC address from I2C Prom Message-ID: <1284731766-2751-1-git-send-email-michael.williamson@criticallink.com> For the MityDSP-L138/MityARM-1808 SOMS, read the factory assigned MAC address from the onboard I2C EPROM and assign it to the emac device during platform initialization. Signed-off-by: Michael Williamson --- Patch is against e90c3a5344683351c7a37f097f1e17d50ee2063c of linux-davinci tree. Changes since v2: 1) removed 8 bytes of &'s and [0]'s from &foo[0]'s per comments arch/arm/mach-davinci/board-mityomapl138.c | 62 ++++++++++++++++++++++++++++ 1 files changed, 62 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index 6f12a18..65f7501 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -25,6 +27,65 @@ #include #define MITYOMAPL138_PHY_ID "0:03" + +#define FACTORY_CONFIG_MAGIC 0x012C0138 +#define FACTORY_CONFIG_VERSION 0x00010001 + +/* Data Held in On-Board I2C device */ +struct factory_config { + u32 magic; + u32 version; + u8 mac[6]; + u32 fpga_type; + u32 spare; + u32 serialnumber; + char partnum[32]; +}; + +static struct factory_config factory_config; + +static void read_factory_config(struct memory_accessor *a, void *context) +{ + int ret; + struct davinci_soc_info *soc_info = &davinci_soc_info; + + ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config)); + if (ret != sizeof(struct factory_config)) { + pr_warning("MityOMAPL138: Read Factory Config Failed: %d\n", + ret); + return; + } + + if (factory_config.magic != FACTORY_CONFIG_MAGIC) { + pr_warning("MityOMAPL138: Factory Config Magic Wrong (%X)\n", + factory_config.magic); + return; + } + + if (factory_config.version != FACTORY_CONFIG_VERSION) { + pr_warning("MityOMAPL138: Factory Config Version Wrong (%X)\n", + factory_config.version); + return; + } + + pr_info("MityOMAPL138: Found MAC = %pM\n", factory_config.mac); + pr_info("MityOMAPL138: Part Number = %s\n", factory_config.partnum); + if (is_valid_ether_addr(factory_config.mac)) + memcpy(soc_info->emac_pdata->mac_addr, + factory_config.mac, ETH_ALEN); + else + pr_warning("MityOMAPL138: Invalid MAC found " + "in factory config block\n"); +} + +static struct at24_platform_data mityomapl138_fd_chip = { + .byte_len = 256, + .page_size = 8, + .flags = AT24_FLAG_READONLY | AT24_FLAG_IRUGO, + .setup = read_factory_config, + .context = NULL, +}; + static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = { .bus_freq = 100, /* kHz */ .bus_delay = 0, /* usec */ @@ -151,6 +212,7 @@ static struct i2c_board_info __initdata mityomap_tps65023_info[] = { }, { I2C_BOARD_INFO("24c02", 0x50), + .platform_data = &mityomapl138_fd_chip, }, }; -- 1.7.0.4 From nick.thompson at ge.com Fri Sep 17 10:06:25 2010 From: nick.thompson at ge.com (Nick Thompson) Date: Fri, 17 Sep 2010 16:06:25 +0100 Subject: Prefered web server fo Davinci In-Reply-To: <20100915140340.GA9279@dei.unipd.it> References: <70E876B0EA86DD4BAF101844BC814DFE0903E89713@Cloud.RL.local> <1284557718.16883.11.camel@mdeneen.sdc.saucontech.com> <20100915140340.GA9279@dei.unipd.it> Message-ID: <4C9383F1.9000807@ge.com> On 15/09/10 15:03, Ottavio Campana wrote: > if the task is just serving a few pages also busybox comes with a minimal webserver. > > You can do cgi with it, but you need to write shell scripts. I write most of my CGI for busybox in C or C++, but I guess you could wrap up more or less any language. You don't get built-in support similar to mod_php or mod_perl of course. Nick. From krunal.patil at einfochips.com Fri Sep 17 12:15:13 2010 From: krunal.patil at einfochips.com (Krunal Patil) Date: Fri, 17 Sep 2010 22:45:13 +0530 (IST) Subject: Alpha blending on captured video with DM365. Message-ID: <1409287678.94489.1284743713604.JavaMail.root@ahm.einfochips.com> Hi, I need to display timestamps with transparent background (Capture date/time) on the captured video on DM365. In DM6467 VDCE is the one which can do alpha blending. Can anyone suggest me something on this how can I achieve this on DM365 with minimal efforts ? My processing chain will be: Capture -> Timestamp Blending - > Encode -> Store. Thanks in advance!!! -- Regards, Krunal -------------- next part -------------- An HTML attachment was scrubbed... URL: From troy.kisky at boundarydevices.com Fri Sep 17 14:15:39 2010 From: troy.kisky at boundarydevices.com (Troy Kisky) Date: Fri, 17 Sep 2010 12:15:39 -0700 Subject: [PATCH v3] i2c: davinci: Fix race when setting up for TX In-Reply-To: <001201cb5669$a0200940$e0601bc0$@raj@ti.com> References: <1284691607-9697-1-git-send-email-jon.povey@racelogic.co.uk> <1284692531-10100-1-git-send-email-jon.povey@racelogic.co.uk> <001201cb5669$a0200940$e0601bc0$@raj@ti.com> Message-ID: <4C93BE5B.6090701@boundarydevices.com> On 9/17/2010 6:09 AM, Sudhakar Rajashekhara wrote: > Hi, > > On Fri, Sep 17, 2010 at 08:32:11, Jon Povey wrote: >> When setting up to transmit, a race exists between the ISR and >> i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. >> This is mostly visible for transmits > 1 byte long. >> >> The hardware starts sending immediately that MDR is loaded. IMR trickery >> doesn't work because if we start sending, finish the first byte and an >> XRDY event occurs before we load IMR to unmask it, we never get an >> interrupt, and we timeout. >> >> Move the MDR load after DXR,IMR loads to avoid this race without locking. >> >> Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 >> > > I remember I had some issues on OMAP-L138 with this fix, that's when I > reverted to configuring ICMDR before writing to DXR (Please see here: > https://patchwork.kernel.org/patch/75262/). I checked the BIOS I2C > driver code for OMAP-L138 and there also we are configuring MDR before > accessing DXR. > > Regards, > Sudhakar How about killing the lines from commit c6c7c729a22bfeb8e63eafce48dbaeea20e68703 ------------------------------- /* * First byte should be set here, not after interrupt, * because transmit-data-ready interrupt can come before * NACK-interrupt during sending of previous message and * ICDXR may have wrong data */ if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); dev->buf_len--; } ---------------------- and resetting the i2c upon a NAK interrupt (after the stop) to clear the bad fifo data? From bbolen at extron.com Fri Sep 17 15:27:25 2010 From: bbolen at extron.com (Brett Bolen) Date: Fri, 17 Sep 2010 13:27:25 -0700 Subject: CMemK.ko driver for recent git kernels Message-ID: <7E5F99BC557C0B42B6F3BB7BED701D4E2E6841F2@EXCH-USA.extron.com> I've download DVSDK 4.0.0.17 beta for my DM365 development board, and having the dma overruns in davinci-pcm.c ( I2S capture ). There is a fix in the later kernel which uses ARM Internal Ram as a bounce buffer. Unfortnately, when I tried to move to it the device drivers won't compile ( CMemk.ko) due to an ioctl prototype change. Where can I find an update to this device driver? It looks like it just drops the inode parameter and a name change, but somebody must have tried this already. I've posted to the ti forums, but they have been slow to respond. More info here: http://e2e.ti.com/support/embedded/f/354/p/63280/233185.aspx#233185 http://e2e.ti.com/support/embedded/f/354/p/64522/232585.aspx#232585 Does anybody have a way to run video+audio capture ( 'arecord -f dat -t wav -d 10 > cap.wav' and 'encode -y 3 -v ab.264 -t 5') with a recent git kernel? A way to do the same with gstreamer? Brett Statement Of Confidentiality: This electronic message transmission, and all attachments, contains information from Extron Electronics which is confidential and privileged. The information is for the exclusive viewing or use of the intended recipient. If you are not the intended recipient, be aware that any disclosure, copying, distribution or use of the contents of this information is prohibited. If you have received this electronic transmission in error, please notify the sender immediately by a "reply to sender only" message and destroy all electronic and hard copies of the communication, including attachments. -------------- next part -------------- An HTML attachment was scrubbed... URL: From michael.williamson at criticallink.com Sat Sep 18 08:08:13 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Sat, 18 Sep 2010 09:08:13 -0400 Subject: [PATCH v5 1/1] davinci: spi: replace existing driver In-Reply-To: References: <1280355490-11878-1-git-send-email-bniebuhr@efjohnson.com> <4C8EB795.1080607@criticallink.com> <201009140904.59555.caglarakyuz@gmail.com> <4C8F7460.6050006@criticallink.com> Message-ID: <4C94B9BD.4010606@criticallink.com> On 09/14/2010 09:26 AM, Nori, Sekhar wrote: > Hi Mike, > > On Tue, Sep 14, 2010 at 18:40:56, Michael Williamson wrote: >> On 9/14/2010 3:14 AM, Nori, Sekhar wrote: >> >>> On Tue, Sep 14, 2010 at 11:34:59, Caglar Akyuz wrote: >>> >>>> Yes, your patches seems ok and mostly complete. I'm waiting for hardware to >>>> test those, will let you know when I do some testing. >>> >>> Thanks! To save time, I haven't tested these patches myself. I have only made >>> sure individual patches don't break the build. Was planning to test after >>> the complete series is ready. >>> >> >> >> If it would help, If there are portions of the patch set that can be tested >> with DMA disabled or something, I'd be willing to kick the tires. I have >> da850 hardware available. > > Thanks for being brave and offering to help! Yes, interrupt and polled mode > can be tried. Since a lot of testing has already happened on the original patch, > I was planning to test the series only after it is complete. Any issues found can > be narrowed down to the differences (which I hope will be justifiable). > > Thanks, > Sekhar So I am testing with a configuration which is pretty much the same as the da850 EVM; a SPI-NOR flash on the first chip select of SPI1. Both poll and interrupt modes work. So far so good, and Brian's work really sorted out a bunch of questions I had looking at the original spi code. Nice work, Nori, for break the patch into logical blocks. I do have a couple of comments: * I'm not sure I understand why there is a "intr_line" field in the platform data and then a possibility to configure an "io_type" as interrupt or polled at the chip select level. I got burned by setting the "io_type" to SPI_IO_TYPE_INTR and not setting "intr_line" to non-zero. The probe just hung because it was trying to use interrupts but never setting SPILVL register. These fields aren't mutually exclusive. Is the intent to support a configuration with one chip select running in polled mode and another in interrupt mode? If so, then it seems the SPILVL register logic needs some attention during each transfer. * As a (novice) user, I'd really like to see some comments / hints added to the ../mach-davinci/include/mach/spi.h file to describe how all of the platform fields should be set. Some of the fields aren't very obvious as to how to initialize them without having a data sheet on one screen and plowing through the driver on another. This might have cleaned up my confusion on the first item. Looking forward to seeing this moving into the mainline. Thanks! -Mike From michael.williamson at criticallink.com Sat Sep 18 08:16:06 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Sat, 18 Sep 2010 09:16:06 -0400 Subject: [PATCH v5 1/1] davinci: spi: replace existing driver In-Reply-To: <4C94B9BD.4010606@criticallink.com> References: <1280355490-11878-1-git-send-email-bniebuhr@efjohnson.com> <4C8EB795.1080607@criticallink.com> <201009140904.59555.caglarakyuz@gmail.com> <4C8F7460.6050006@criticallink.com> <4C94B9BD.4010606@criticallink.com> Message-ID: <4C94BB96.6040103@criticallink.com> [...] > I had looking at the original spi code. Nice work, Nori, for break the patch s/Nori/Sekhar Sorry about that, Sekhar. -Mike From Jon.Povey at racelogic.co.uk Sun Sep 19 22:59:27 2010 From: Jon.Povey at racelogic.co.uk (Jon Povey) Date: Mon, 20 Sep 2010 04:59:27 +0100 Subject: Alpha blending on captured video with DM365. In-Reply-To: <1409287678.94489.1284743713604.JavaMail.root@ahm.einfochips.com> Message-ID: <70E876B0EA86DD4BAF101844BC814DFE093ED5F50D@Cloud.RL.local> davinci-linux-open-source-bounces at linux.davincidsp.com wrote: > Hi, > > I need to display timestamps with transparent background > (Capture date/time) on the captured video on DM365. You can't use the hardware OSD to do this alpha blending before encoding, the frame is blended before being output, there is no path back to RAM for the blended frame. Your options are to blend graphics onto the frame using software, or use external hardware to either do the blending or encoding. The DM365 can't do both in hardware. -- Jon Povey jon.povey at racelogic.co.uk Racelogic is a limited company registered in England. Registered number 2743719 . Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB . The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network From Jon.Povey at racelogic.co.uk Sun Sep 19 23:40:51 2010 From: Jon.Povey at racelogic.co.uk (Jon Povey) Date: Mon, 20 Sep 2010 05:40:51 +0100 Subject: [PATCH v3] i2c: davinci: Fix race when setting up for TX In-Reply-To: <4C93BE5B.6090701@boundarydevices.com> Message-ID: <70E876B0EA86DD4BAF101844BC814DFE093ED5F50E@Cloud.RL.local> Troy Kisky wrote: > On 9/17/2010 6:09 AM, Sudhakar Rajashekhara wrote: >> Hi, Seems I didn't get Sudhakar's email.. I wonder why? >> On Fri, Sep 17, 2010 at 08:32:11, Jon Povey wrote: >>> Move the MDR load after DXR,IMR loads to avoid this race without >>> locking. >> >> I remember I had some issues on OMAP-L138 with this fix, that's when >> I reverted to configuring ICMDR before writing to DXR (Please see >> here: https://patchwork.kernel.org/patch/75262/). I checked the BIOS >> I2C driver code for OMAP-L138 and there also we are configuring MDR >> before accessing DXR. Ah :/ > How about killing the lines from commit > c6c7c729a22bfeb8e63eafce48dbaeea20e68703 > ------------------------------- > /* > * First byte should be set here, not after interrupt, > * because transmit-data-ready interrupt can come before > * NACK-interrupt during sending of previous message and > * ICDXR may have wrong data > */ > if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { > davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); > dev->buf_len--; } > ---------------------- > > and resetting the i2c upon a NAK interrupt (after the stop) > to clear the bad fifo data? I can't really comment on how valid that would be and can't easily test it. However preloading DXR does save one interrupt on transmit so the whole operation is faster and more efficient. Maybe v1 of my patch, with locking, is the best option? -- Jon Povey jon.povey at racelogic.co.uk Racelogic is a limited company registered in England. Registered number 2743719 . Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB . The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network From sugumar at ti.com Mon Sep 20 02:39:46 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Mon, 20 Sep 2010 13:09:46 +0530 Subject: [PATCH v5 1/4] davinci: Add generic PWM support for PWM control Message-ID: <1284968386-16898-1-git-send-email-sugumar@ti.com> This patch adds generic PWM support where it maintains the list of PWM control devices that can be added or removed. The interface provides a list of functions that can be accessed by the PWM control driver module and the generic PWM driver. The PWM control driver module such as eCAP uses the interface to register and add itself to the list as a PWM control device. The generic PWM driver uses the interface to search for a PWM control device and if present, uses the device for PWM control. Signed-off-by: Sugumar Natarajan --- Changes since v4: a) pwm_enable and pwm_disable function implementation have been modified, such that the actual implementation is done by the corresponding driver, and these functions would just make a callback. arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/davinci_pwm.c | 135 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 34 ++++++ 3 files changed, 172 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/davinci_pwm.c create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index a7a70d1..90ca821 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_SUSPEND) += pm.o sleep.o + +# Generic PWM control support +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o diff --git a/arch/arm/mach-davinci/davinci_pwm.c b/arch/arm/mach-davinci/davinci_pwm.c new file mode 100644 index 0000000..8f3e8ad --- /dev/null +++ b/arch/arm/mach-davinci/davinci_pwm.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + unsigned int clock_freq; + unsigned int period_cycles; + unsigned int duty_cycle; + int ret = 0; + + if (WARN_ON(!pwm)) + return -EINVAL; + + if (pwm->pwm_config_device) { + if (!period_ns || duty_ns > period_ns) + return -EINVAL; + + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; + + ret = pwm->pwm_config_device(pwm, period_cycles, duty_cycle); + } + + return ret; +} +EXPORT_SYMBOL(pwm_config); + +int pwm_enable(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return -EINVAL; + + if (pwm->pwm_enable) + return pwm->pwm_enable(pwm); + + return 0; +} +EXPORT_SYMBOL(pwm_enable); + +void pwm_disable(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + if (pwm->pwm_disable) + pwm->pwm_disable(pwm); +} +EXPORT_SYMBOL(pwm_disable); + +static DEFINE_MUTEX(pwm_lock); +static LIST_HEAD(pwm_list); + +struct pwm_device *pwm_request(int pwm_id, const char *label) +{ + struct pwm_device *pwm, *tmp_pwm = ERR_PTR(-ENOENT); + + mutex_lock(&pwm_lock); + + list_for_each_entry(pwm, &pwm_list, node) { + if (pwm->pwm_id == pwm_id) { + if (pwm->use_count == 0) { + pwm->use_count++; + pwm->label = label; + } else { + pwm = ERR_PTR(-EBUSY); + } + tmp_pwm = pwm; + break; + } + } + + mutex_unlock(&pwm_lock); + return tmp_pwm; +} +EXPORT_SYMBOL(pwm_request); + +void pwm_free(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + mutex_lock(&pwm_lock); + + if (pwm->use_count) { + pwm->use_count--; + pwm->label = NULL; + } else { + dev_warn(&pwm->pdev->dev, "PWM device already freed\n"); + } + + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_free); + +void pwm_add(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + mutex_lock(&pwm_lock); + list_add_tail(&pwm->node, &pwm_list); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_add); + +void pwm_remove(struct pwm_device *pwm) +{ + if (WARN_ON(!pwm)) + return; + + mutex_lock(&pwm_lock); + list_del(&pwm->node); + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_remove); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h new file mode 100644 index 0000000..5762881 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __DAVINCI_PWM_H +#define __DAVINCI_PWM_H + +struct pwm_device { + struct list_head node; + struct platform_device *pdev; + int (*pwm_enable)(struct pwm_device *pwm); + void (*pwm_disable)(struct pwm_device *pwm); + int (*pwm_config_device)(struct pwm_device *pwm, + unsigned int period, unsigned int dutycycle); + const char *label; + struct clk *clk; + unsigned int use_count; + unsigned int pwm_id; +}; + +void pwm_add(struct pwm_device *pwm); +void pwm_remove(struct pwm_device *pwm); + +#endif -- 1.5.6 From sugumar at ti.com Mon Sep 20 02:41:00 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Mon, 20 Sep 2010 13:11:00 +0530 Subject: [PATCH v5 2/4] davinci: da8xx: eCAP driver for PWM signal generation Message-ID: <1284968460-17013-1-git-send-email-sugumar@ti.com> OMAPL138/DA850 contains three instances of eCAP module. Each eCAP module has one dedicated pin that can be used either in capture mode(input) or in PWM mode. For more information on eCAP module operation, please refer to the following url. http://focus.ti.com/lit/ug/sprufl2a/sprufl2a.pdf This patch adds eCAP driver support for PWM signal generation. Signed-off-by: Sugumar Natarajan --- Changes since v4: a) ecap_pwm_enable and ecap_pwm_disable function have been included. arch/arm/mach-davinci/Kconfig | 8 + arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/ecap.c | 181 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 2 + 4 files changed, 194 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/ecap.c diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 9aca60c..c9634c7 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -230,6 +230,14 @@ config DAVINCI_RESET_CLOCKS probably do not want this option enabled until your device drivers work properly. +config DAVINCI_ECAP_PWM + bool "eCAP driver support for PWM control" + depends on ARCH_DAVINCI_DA8XX + depends on HAVE_PWM + default n + help + Say Y to select the eCAP module for PWM control. + endmenu endif diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 90ca821..90bd88e 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -42,3 +42,6 @@ obj-$(CONFIG_SUSPEND) += pm.o sleep.o # Generic PWM control support obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o + +# eCAP driver support for PWM +obj-$(CONFIG_DAVINCI_ECAP_PWM) += ecap.o diff --git a/arch/arm/mach-davinci/ecap.c b/arch/arm/mach-davinci/ecap.c new file mode 100644 index 0000000..daab87f --- /dev/null +++ b/arch/arm/mach-davinci/ecap.c @@ -0,0 +1,181 @@ +/* + * DA850/OMAP-L138 eCAP driver for PWM output generation + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CAPTURE_3_REG 0x10 +#define CAPTURE_4_REG 0x14 +#define CAPTURE_CTRL2_REG 0x2A + +#define ECAPCTRL2_MODESL_ECAP BIT(9) +#define ECAPCTRL2_SYNCOSEL_DISABLE (0x3 << 6) +#define ECAPCTRL2_TSCTRSTOP_FREERUN BIT(4) + +static struct private { + int duty_val; +} pv_data; + +/* + * ecap_pwm_config - configures the eCAP Module for the PWM output with given + * period and duty cycle. + */ + +static int ecap_pwm_config(struct pwm_device *pwm, unsigned int period_cycles, + unsigned int duty_cycle) +{ + + struct private *private_data = (struct private *)(pwm->private); + + __raw_writew(ECAPCTRL2_MODESL_ECAP | ECAPCTRL2_SYNCOSEL_DISABLE + | ECAPCTRL2_TSCTRSTOP_FREERUN, pwm->mmio_base + + CAPTURE_CTRL2_REG); + __raw_writel(period_cycles, pwm->mmio_base + CAPTURE_3_REG); + + /* + * 100% duty cycle is obtained when the duty cycle value is one + * greater than period ie duty cycle = period + 1 + */ + if (duty_cycle == period_cycles) + duty_cycle = duty_cycle + 1; + + private_data->duty_val = duty_cycle; + return 0; +} + +int ecap_pwm_enable(struct pwm_device *pwm) +{ + struct private *private_data = (struct private *)(pwm->private); + + __raw_writel(private_data->duty_val, pwm->mmio_base + + CAPTURE_4_REG); + return 0; +} + +void ecap_pwm_disable(struct pwm_device *pwm) +{ + __raw_writel(0, pwm->mmio_base + CAPTURE_4_REG); +} + +static int __devinit ecap_probe(struct platform_device *pdev) +{ + struct pwm_device *pwm = NULL; + struct resource *r; + int ret = 0; + + pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); + if (!pwm) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + pwm->clk = clk_get(&pdev->dev, "ecap"); + if (IS_ERR(pwm->clk)) { + ret = PTR_ERR(pwm->clk); + goto err_free; + } + + pwm->pwm_id = pdev->id; + pwm->pdev = pdev; + pwm->pwm_config_device = ecap_pwm_config; + pwm->pwm_enable = ecap_pwm_enable; + pwm->pwm_disable = ecap_pwm_disable; + pwm->private = &pv_data; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "no memory resource defined\n"); + ret = -ENODEV; + goto err_free_clk; + } + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) { + dev_err(&pdev->dev, "failed to request memory resource\n"); + ret = -EBUSY; + goto err_free_clk; + } + + pwm->mmio_base = ioremap(r->start, resource_size(r)); + if (!pwm->mmio_base) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + ret = -ENODEV; + goto err_free_mem; + } + + pwm_add(pwm); + platform_set_drvdata(pdev, pwm); + clk_enable(pwm->clk); + return 0; + +err_free_mem: + release_mem_region(r->start, resource_size(r)); +err_free_clk: + clk_put(pwm->clk); +err_free: + kfree(pwm); + return ret; +} + +static int __devexit ecap_remove(struct platform_device *pdev) +{ + struct pwm_device *pwm; + struct resource *r; + + pwm = platform_get_drvdata(pdev); + if (!pwm) + return -ENODEV; + + pwm_remove(pwm); + iounmap(pwm->mmio_base); + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(r->start, resource_size(r)); + clk_disable(pwm->clk); + clk_put(pwm->clk); + kfree(pwm); + + return 0; +} + +static struct platform_driver ecap_driver = { + .driver = { + .name = "ecap", + .owner = THIS_MODULE, + }, + .probe = ecap_probe, + .remove = __devexit_p(ecap_remove), +}; + +static int __init ecap_init(void) +{ + return platform_driver_register(&ecap_driver); +} + +static void __exit ecap_exit(void) +{ + platform_driver_unregister(&ecap_driver); +} + +module_init(ecap_init); +module_exit(ecap_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h index 5762881..e6db614 100644 --- a/arch/arm/mach-davinci/include/mach/davinci_pwm.h +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -18,12 +18,14 @@ struct pwm_device { struct list_head node; struct platform_device *pdev; + void *private; int (*pwm_enable)(struct pwm_device *pwm); void (*pwm_disable)(struct pwm_device *pwm); int (*pwm_config_device)(struct pwm_device *pwm, unsigned int period, unsigned int dutycycle); const char *label; struct clk *clk; + void __iomem *mmio_base; unsigned int use_count; unsigned int pwm_id; }; -- 1.5.6 From sugumar at ti.com Mon Sep 20 02:41:54 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Mon, 20 Sep 2010 13:11:54 +0530 Subject: [PATCH 3/4] davinci: da850/omap-l138: Add platform specific support for eCAP driver Message-ID: <1284968514-17065-1-git-send-email-sugumar@ti.com> On DA850/OMAPL138 EVM, eCAP module is used to control the LCD backlight. This patch registers the eCAP driver as platform device and configures the corresponding pins for eCAP PWM output Signed-off-by: Sugumar Natarajan --- This patch is submitted for the first time and hence the verison has not been included arch/arm/mach-davinci/Kconfig | 1 + arch/arm/mach-davinci/da850.c | 32 ++++++++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/da8xx.h | 1 + arch/arm/mach-davinci/include/mach/mux.h | 3 ++ 4 files changed, 37 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index c9634c7..8192866 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -40,6 +40,7 @@ config ARCH_DAVINCI_DA850 select CP_INTC select ARCH_DAVINCI_DA8XX select ARCH_HAS_CPUFREQ + select HAVE_PWM config ARCH_DAVINCI_DA8XX select CPU_ARM926T diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 63916b9..7bc51f1 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -345,6 +345,13 @@ static struct clk aemif_clk = { .flags = ALWAYS_ENABLED, }; +static struct clk ecap_clk = { + .name = "ecap", + .parent = &pll0_sysclk2, + .lpsc = DA8XX_LPSC1_ECAP, + .gpsc = 1, +}; + static struct clk_lookup da850_clks[] = { CLK(NULL, "ref", &ref_clk), CLK(NULL, "pll0", &pll0_clk), @@ -387,6 +394,7 @@ static struct clk_lookup da850_clks[] = { CLK("davinci_mmc.0", NULL, &mmcsd0_clk), CLK("davinci_mmc.1", NULL, &mmcsd1_clk), CLK(NULL, "aemif", &aemif_clk), + CLK(NULL, "ecap", &ecap_clk), CLK(NULL, NULL, NULL), }; @@ -549,6 +557,7 @@ static const struct mux_config da850_pins[] = { MUX_CFG(DA850, GPIO4_0, 10, 28, 15, 8, false) MUX_CFG(DA850, GPIO4_1, 10, 24, 15, 8, false) MUX_CFG(DA850, RTC_ALARM, 0, 28, 15, 2, false) + MUX_CFG(DA850, ECAP2_APWM2, 1, 0, 15, 4, false) #endif }; @@ -1006,6 +1015,29 @@ static int da850_round_armrate(struct clk *clk, unsigned long rate) } #endif + +#define DA8XX_ECAP2_BASE 0x01F08000 + +static struct resource da850_ecap_resource[] = { + { + .start = DA8XX_ECAP2_BASE, + .end = DA8XX_ECAP2_BASE + 0xfff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device da850_ecap_dev = { + .name = "ecap", + .id = 0, + .resource = da850_ecap_resource, + .num_resources = ARRAY_SIZE(da850_ecap_resource), +}; + +int __init da850_register_ecap(void) +{ + return platform_device_register(&da850_ecap_dev); +} + int da850_register_pm(struct platform_device *pdev) { int ret; diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index 4247b3f..3b6e399 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -83,6 +83,7 @@ int da850_register_cpufreq(char *async_clk); int da8xx_register_cpuidle(void); void __iomem * __init da8xx_get_mem_ctlr(void); int da850_register_pm(struct platform_device *pdev); +int __init da850_register_ecap(void); extern struct platform_device da8xx_serial_device; extern struct emac_platform_data da8xx_emac_pdata; diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h index de11aac..b3c23ee 100644 --- a/arch/arm/mach-davinci/include/mach/mux.h +++ b/arch/arm/mach-davinci/include/mach/mux.h @@ -914,6 +914,9 @@ enum davinci_da850_index { DA850_GPIO4_0, DA850_GPIO4_1, DA850_RTC_ALARM, + + /* eCAP Module */ + DA850_ECAP2_APWM2, }; enum davinci_tnetv107x_index { -- 1.5.6 From sugumar at ti.com Mon Sep 20 02:42:26 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Mon, 20 Sep 2010 13:12:26 +0530 Subject: [PATCH 4/4] davinci: da850/omapl138 evm: Platform support for PWM based backlight driver Message-ID: <1284968546-17107-1-git-send-email-sugumar@ti.com> This patch registers the backlight device as platform device and sets the backlight specific data such as period, maximum intensity and default brightness. Signed-off-by: Sugumar Natarajan #include #include +#include #include #include @@ -106,6 +107,24 @@ static struct platform_device da850_pm_device = { .id = -1, }; +#define DAVINCI_BACKLIGHT_MAX_BRIGHTNESS 255 +#define DAVINVI_BACKLIGHT_DEFAULT_BRIGHTNESS 255 +#define DAVINCI_PWM_PERIOD_NANO_SECONDS (1000000 * 10) + +static struct platform_pwm_backlight_data da850evm_backlight_data = { + .pwm_id = 0, + .max_brightness = DAVINCI_BACKLIGHT_MAX_BRIGHTNESS, + .dft_brightness = DAVINVI_BACKLIGHT_DEFAULT_BRIGHTNESS, + .pwm_period_ns = DAVINCI_PWM_PERIOD_NANO_SECONDS, +}; + +static struct platform_device da850evm_backlight = { + .name = "pwm-backlight", + .dev = { + .platform_data = &da850evm_backlight_data, + }, +}; + /* DA850/OMAP-L138 EVM includes a 512 MByte large-page NAND flash * (128K blocks). It may be used instead of the (default) SPI flash * to boot, using TI's tools to install the secondary boot loader @@ -840,6 +859,19 @@ static __init void da850_evm_init(void) if (ret) pr_warning("da850_evm_init: rtc setup failed: %d\n", ret); + ret = davinci_cfg_reg(DA850_ECAP2_APWM2); + if (ret) + pr_warning("da850_evm_init:ecap mux failed ""%d\n", ret); + + ret = da850_register_ecap(); + if (ret) + pr_warning("da850_evm_init: ECAP registration failed:" + "%d\n", ret); + + ret = platform_device_register(&da850evm_backlight); + if (ret) + pr_warning("da850evm_register_backlight_failed:""%d\n", ret); + ret = da850_register_cpufreq("pll0_sysclk3"); if (ret) pr_warning("da850_evm_init: cpufreq registration failed: %d\n", -- 1.5.6 From sugumar at ti.com Mon Sep 20 02:44:47 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Mon, 20 Sep 2010 13:14:47 +0530 Subject: [PATCH 1/2] davinci: da8xx: eHRPWM driver for simple PWM output control Message-ID: <1284968687-17228-1-git-send-email-sugumar@ti.com> OMAPL138/DA850 contains two enhanced PWM modules. Each module has two output pins EPWMxA and EPWMxB. The eHRPWM module is used to generate complex pulse width waveforms. For more information on eHRPWM please refer the following url http://focus.ti.com/lit/ug/sprufl3b/sprufl3b.pdf This patch adds eHRPWM driver support for simple PWM output control Signed-off-by: Sugumar Natarajan --- arch/arm/mach-davinci/Kconfig | 8 + arch/arm/mach-davinci/Makefile | 3 + arch/arm/mach-davinci/ehrpwm.c | 302 ++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/davinci_pwm.h | 1 + 4 files changed, 314 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/ehrpwm.c diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 8192866..6d588ed 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -239,6 +239,14 @@ config DAVINCI_ECAP_PWM help Say Y to select the eCAP module for PWM control. +config DAVINCI_EHRPWM + bool "eHRPWM driver support for simple PWM control" + depends on ARCH_DAVINCI_DA8XX + depends on HAVE_PWM + default n + help + Say Y to select the eHRPWM driver + endmenu endif diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 90bd88e..3d567ca 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -45,3 +45,6 @@ obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o # eCAP driver support for PWM obj-$(CONFIG_DAVINCI_ECAP_PWM) += ecap.o + +# eHRPWM driver for simple PWM control +obj-$(CONFIG_DAVINCI_EHRPWM) += ehrpwm.o diff --git a/arch/arm/mach-davinci/ehrpwm.c b/arch/arm/mach-davinci/ehrpwm.c new file mode 100644 index 0000000..5166370 --- /dev/null +++ b/arch/arm/mach-davinci/ehrpwm.c @@ -0,0 +1,302 @@ +/* + * DA850/OMAP-L138 eHRPWM driver for simple PWM output generation + * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TBCTL_REG 0x0 +#define TBPRD_REG 0xA +#define CMPA_REG 0x12 +#define CMPB_REG 0x14 +#define AQCTLA_REG 0x16 +#define AQCTLB_REG 0x18 + +#define TBCTL_FREERUN_FREE 0x2 +#define TBCTL_SYNCOSEL_DISABLE 0x3 + +#define ACTCTLA_CTREQCMP_LOW 0x1 +#define ACTCTLA_CTREQPRD_HIGH 0x2 + +#define NUMBER_OF_PWM_OUTPUTS 2 + +static struct private { + int duty_val; +} pv_data[NUMBER_OF_PWM_OUTPUTS]; + +struct pwm_device *pwm_dev[NUMBER_OF_PWM_OUTPUTS]; + +struct freq_divider_table { + unsigned char clkdiv_val; + unsigned char hspclkdiv_val; + unsigned int resulting_div; +}; + +/* + * The table shows all the combinations of CLKDIV and HSPCLKDIV that + * are available, and the resulting divider. + * resulting divider = CLKDIV * HSPCLKDIV + */ + +static struct freq_divider_table frqtable[] = { + {0, 0, 1}, + {0, 1, 2}, + {0, 2, 4}, + {0, 3, 6}, + {0, 4, 8}, + {0, 5, 10}, + {0, 6, 12}, + {0, 7, 14}, + {1, 4, 16}, + {1, 5, 20}, + {1, 6, 24}, + {1, 7, 28}, + {2, 4, 32}, + {2, 5, 40}, + {2, 6, 48}, + {2, 7, 56}, + {3, 4, 64}, + {3, 5, 80}, + {3, 6, 96}, + {3, 7, 112}, + {4, 4, 128}, + {4, 5, 160}, + {4, 6, 192}, + {4, 7, 224}, + {5, 4, 256}, + {5, 5, 320}, + {5, 6, 384}, + {5, 7, 448}, + {6, 4, 512}, + {6, 5, 640}, + {6, 6, 768}, + {6, 7, 896}, + {7, 4, 1024}, + {7, 5, 1280}, + {7, 6, 1536}, + {7, 7, 1792}, +}; + +/* + * ehrpwm_config_pwm - configures the ehrpwm module for the PWM output with + * given period and duty cycle. + */ + +static int ehrpwm_pwm_config(struct pwm_device *pwm, unsigned int + period_cycles, unsigned int duty_cycle) +{ + int tb_div_val = 0; + int desired_ps_val = 0; + int available_ps_val = 0; + int i; + struct private *private_data = (struct private *)(pwm->private); + + /* + * Prescaler is used when the period_cycles value exceeds the maximum + * value of the period register. + * We always look for minimum prescaler value as it would result in wide + * range of duty cycle control. + */ + + if (period_cycles > 65535) { + desired_ps_val = period_cycles / 65535 + 1; + for (i = 0; i < (sizeof(frqtable) / sizeof(frqtable[0])); i++) { + if (frqtable[i].resulting_div >= desired_ps_val) { + available_ps_val = frqtable[i].resulting_div; + tb_div_val = frqtable[i].clkdiv_val << 10 + | frqtable[i].hspclkdiv_val << 7; + break; + } + } + + period_cycles = period_cycles / available_ps_val; + duty_cycle = duty_cycle / available_ps_val; + } + + __raw_writew((TBCTL_FREERUN_FREE << 14) | (TBCTL_SYNCOSEL_DISABLE << 4) + | tb_div_val , pwm->mmio_base + TBCTL_REG); + __raw_writew((unsigned short)period_cycles, pwm->mmio_base + + TBPRD_REG); + + /* + * 100% duty cycle is obtained when the duty_cycle value is 1 greater + * than period_cycles value ie duty_cycle = period_cycles + 1. + */ + + if (duty_cycle == period_cycles) + duty_cycle = period_cycles + 1; + + private_data->duty_val = duty_cycle; + return 0; +} + +int ehrpwm_pwm_enable(struct pwm_device *pwm) +{ + struct private *private_data = (struct private *)(pwm->private); + + if (!pwm->output_number) { + __raw_writew((unsigned short)private_data->duty_val, + pwm->mmio_base + CMPA_REG); + __raw_writew((ACTCTLA_CTREQCMP_LOW << 4) + | (ACTCTLA_CTREQPRD_HIGH << 2), + pwm->mmio_base + AQCTLA_REG); + } else { + __raw_writew((unsigned short)private_data->duty_val, + pwm->mmio_base + CMPB_REG); + __raw_writew((ACTCTLA_CTREQCMP_LOW << 8) + | (ACTCTLA_CTREQPRD_HIGH << 2), + pwm->mmio_base + AQCTLB_REG); + } + + return 0; +} + +void ehrpwm_pwm_disable(struct pwm_device *pwm) +{ + if (!pwm->output_number) { + __raw_writew(0, pwm->mmio_base + + CMPA_REG); + __raw_writew((ACTCTLA_CTREQCMP_LOW << 4) + | (ACTCTLA_CTREQPRD_HIGH << 2), + pwm->mmio_base + AQCTLA_REG); + } else { + __raw_writew(0 , pwm->mmio_base + + CMPB_REG); + __raw_writew((ACTCTLA_CTREQCMP_LOW << 8) + | (ACTCTLA_CTREQPRD_HIGH << 2), + pwm->mmio_base + AQCTLB_REG); + } +} + +static int __devinit ehrpwm_probe(struct platform_device *pdev) +{ + struct pwm_device **pwm = NULL; + struct resource *r; + int ret = 0; + int i = 0; + + pwm = &pwm_dev[0]; + + for (i = 0; i < NUMBER_OF_PWM_OUTPUTS; i++) { + pwm[i] = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); + if (!pwm[i]) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + goto err_free_device; + return -ENOMEM; + } + } + + pwm[0]->clk = clk_get(&pdev->dev, "ehrpwm"); + if (IS_ERR(pwm[0]->clk)) { + ret = PTR_ERR(pwm[0]->clk); + goto err_free_device; + } + + pwm[0]->pdev = pdev; + pwm[0]->pwm_config_device = ehrpwm_pwm_config; + pwm[0]->pwm_enable = ehrpwm_pwm_enable; + pwm[0]->pwm_disable = ehrpwm_pwm_disable; + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "no memory resource defined\n"); + ret = -ENODEV; + goto err_free_clk; + } + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (!r) { + dev_err(&pdev->dev, "failed to request memory resource\n"); + ret = -EBUSY; + goto err_free_clk; + } + + pwm[0]->mmio_base = ioremap(r->start, resource_size(r)); + if (!pwm[0]->mmio_base) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + ret = -ENODEV; + goto err_free_mem; + } + + for (i = 0; i < NUMBER_OF_PWM_OUTPUTS; i++) { + *pwm[i] = *pwm[0]; + pwm[i]->pwm_id = pdev->id + i; + pwm[i]->output_number = i; + pwm[i]->private = &pv_data[i]; + + pwm_add(pwm[i]); + } + + platform_set_drvdata(pdev, pwm); + + clk_enable(pwm[0]->clk); + return 0; + +err_free_mem: + release_mem_region(r->start, resource_size(r)); +err_free_clk: + clk_put(pwm[0]->clk); +err_free_device: + for (i = 0; i < NUMBER_OF_PWM_OUTPUTS; i++) + kfree(pwm[i]); + return ret; +} + +static int __devexit ehrpwm_remove(struct platform_device *pdev) +{ + struct pwm_device **pwm; + struct resource *r; + int i = 0; + + pwm = platform_get_drvdata(pdev); + iounmap(pwm[0]->mmio_base); + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(r->start, resource_size(r)); + clk_disable(pwm[0]->clk); + clk_put(pwm[0]->clk); + for (i = 0; i < NUMBER_OF_PWM_OUTPUTS; i++) + pwm_remove(pwm[i]); + + return 0; +} + +static struct platform_driver ehrpwm_driver = { + .driver = { + .name = "ehrpwm", + .owner = THIS_MODULE, + }, + .probe = ehrpwm_probe, + .remove = __devexit_p(ehrpwm_remove), +}; + +static int __init ehrpwm_init(void) +{ + return platform_driver_register(&ehrpwm_driver); +} + +static void __exit ehrpwm_exit(void) +{ + platform_driver_unregister(&ehrpwm_driver); +} + +module_init(ehrpwm_init); +module_exit(ehrpwm_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h index e6db614..2090fed 100644 --- a/arch/arm/mach-davinci/include/mach/davinci_pwm.h +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h @@ -27,6 +27,7 @@ struct pwm_device { struct clk *clk; void __iomem *mmio_base; unsigned int use_count; + unsigned char output_number; unsigned int pwm_id; }; -- 1.5.6 From sugumar at ti.com Mon Sep 20 02:45:15 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Mon, 20 Sep 2010 13:15:15 +0530 Subject: [PATCH 2/2] davinci: Add platform specific support for eHRPWM driver Message-ID: <1284968715-17272-1-git-send-email-sugumar@ti.com> This patch registers the eHRPWM module as a platform device and also configures the pin for PWM output --- arch/arm/mach-davinci/da850.c | 34 ++++++++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/da8xx.h | 2 + arch/arm/mach-davinci/include/mach/mux.h | 2 + 3 files changed, 38 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 7bc51f1..ab1758e 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -352,6 +352,13 @@ static struct clk ecap_clk = { .gpsc = 1, }; +static struct clk ehrpwm_clk = { + .name = "ehrpwm", + .parent = &pll0_sysclk2, + .lpsc = DA8XX_LPSC1_PWM, + .gpsc = 1, +}; + static struct clk_lookup da850_clks[] = { CLK(NULL, "ref", &ref_clk), CLK(NULL, "pll0", &pll0_clk), @@ -395,6 +402,7 @@ static struct clk_lookup da850_clks[] = { CLK("davinci_mmc.1", NULL, &mmcsd1_clk), CLK(NULL, "aemif", &aemif_clk), CLK(NULL, "ecap", &ecap_clk), + CLK(NULL, "ehrpwm", &ehrpwm_clk), CLK(NULL, NULL, NULL), }; @@ -558,6 +566,7 @@ static const struct mux_config da850_pins[] = { MUX_CFG(DA850, GPIO4_1, 10, 24, 15, 8, false) MUX_CFG(DA850, RTC_ALARM, 0, 28, 15, 2, false) MUX_CFG(DA850, ECAP2_APWM2, 1, 0, 15, 4, false) + MUX_CFG(DA850, EHRPWM1_A, 5, 0, 15, 2, false) #endif }; @@ -1015,6 +1024,22 @@ static int da850_round_armrate(struct clk *clk, unsigned long rate) } #endif +#define DA8XX_EHRPWM1_BASE 0x01F02000 + +static struct resource da850_ehrpwm_resource[] = { + { + .start = DA8XX_EHRPWM1_BASE, + .end = DA8XX_EHRPWM1_BASE + 0xfff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device da850_ehrpwm_dev = { + .name = "ehrpwm", + .id = 1, + .resource = da850_ehrpwm_resource, + .num_resources = ARRAY_SIZE(da850_ehrpwm_resource), +}; #define DA8XX_ECAP2_BASE 0x01F08000 @@ -1038,6 +1063,15 @@ int __init da850_register_ecap(void) return platform_device_register(&da850_ecap_dev); } + +#define DA8XX_CHIPCFG1 DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP1_REG) + +int __init da850_register_ehrpwm(void) +{ + __raw_writew(__raw_readw(DA8XX_CHIPCFG1) | BIT(12), DA8XX_CHIPCFG1); + return platform_device_register(&da850_ehrpwm_dev); +} + int da850_register_pm(struct platform_device *pdev) { int ret; diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index 3b6e399..2ccfa85 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -42,6 +42,7 @@ extern void __iomem *da8xx_syscfg1_base; #define DA8XX_SYSCFG0_VIRT(x) (da8xx_syscfg0_base + (x)) #define DA8XX_JTAG_ID_REG 0x18 #define DA8XX_CFGCHIP0_REG 0x17c +#define DA8XX_CFGCHIP1_REG 0x180 #define DA8XX_CFGCHIP2_REG 0x184 #define DA8XX_CFGCHIP3_REG 0x188 @@ -84,6 +85,7 @@ int da8xx_register_cpuidle(void); void __iomem * __init da8xx_get_mem_ctlr(void); int da850_register_pm(struct platform_device *pdev); int __init da850_register_ecap(void); +int __init da850_register_ehrpwm(void); extern struct platform_device da8xx_serial_device; extern struct emac_platform_data da8xx_emac_pdata; diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h index b3c23ee..416d935 100644 --- a/arch/arm/mach-davinci/include/mach/mux.h +++ b/arch/arm/mach-davinci/include/mach/mux.h @@ -917,6 +917,8 @@ enum davinci_da850_index { /* eCAP Module */ DA850_ECAP2_APWM2, + /* eHRPWM Module */ + DA850_EHRPWM1_A, }; enum davinci_tnetv107x_index { -- 1.5.6 From sshtylyov at mvista.com Mon Sep 20 03:43:15 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Mon, 20 Sep 2010 12:43:15 +0400 Subject: [PATCH 2/2] davinci: Add platform specific support for eHRPWM driver In-Reply-To: <1284968715-17272-1-git-send-email-sugumar@ti.com> References: <1284968715-17272-1-git-send-email-sugumar@ti.com> Message-ID: <4C971EA3.4080402@mvista.com> Hello. On 20-09-2010 11:45, Sugumar Natarajan wrote: > This patch registers the eHRPWM module as a platform device > and also configures the pin for PWM output [...] > diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c > index 7bc51f1..ab1758e 100644 > --- a/arch/arm/mach-davinci/da850.c > +++ b/arch/arm/mach-davinci/da850.c [...] > +static struct platform_device da850_ehrpwm_dev = { > + .name = "ehrpwm", > + .id = 1, Why not -1? Isn't this the only device? WBR, Sergei From sshtylyov at mvista.com Mon Sep 20 03:44:56 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Mon, 20 Sep 2010 12:44:56 +0400 Subject: [PATCH 3/4] davinci: da850/omap-l138: Add platform specific support for eCAP driver In-Reply-To: <1284968514-17065-1-git-send-email-sugumar@ti.com> References: <1284968514-17065-1-git-send-email-sugumar@ti.com> Message-ID: <4C971F08.8000100@mvista.com> Hello. On 20-09-2010 11:41, Sugumar Natarajan wrote: > On DA850/OMAPL138 EVM, eCAP module is used to control the LCD > backlight. This patch registers the eCAP driver as platform device > and configures the corresponding pins for eCAP PWM output > Signed-off-by: Sugumar Natarajan [...] > diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c > index 63916b9..7bc51f1 100644 > --- a/arch/arm/mach-davinci/da850.c > +++ b/arch/arm/mach-davinci/da850.c [...] > @@ -1006,6 +1015,29 @@ static int da850_round_armrate(struct clk *clk, unsigned long rate) > } > #endif > > + > +#define DA8XX_ECAP2_BASE 0x01F08000 > + > +static struct resource da850_ecap_resource[] = { > + { > + .start = DA8XX_ECAP2_BASE, > + .end = DA8XX_ECAP2_BASE + 0xfff, > + .flags = IORESOURCE_MEM, > + }, > +}; > + > +static struct platform_device da850_ecap_dev = { > + .name = "ecap", > + .id = 0, Why not -1? Isn't this the only device? WBR, Sergei From cyril at ti.com Mon Sep 20 10:07:27 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 20 Sep 2010 11:07:27 -0400 Subject: [PATCH v3 0/5] add tnetv107x input drivers Message-ID: <1284995252-23337-1-git-send-email-cyril@ti.com> Texas Instruments' TNETV107X is an ARM1176 based SoC, with on-chip touchscreen and keypad controllers. This patch series adds drivers for these controllers. Changes between v1 and v2: 1. Cleaned up platform data needs by reusing matrix keypad pdata 2. Eliminated calibration code from touch driver 3. Relocated h/w init code to open and close 4. Other minor cleanups Changes between v2 and v3: 1. Merged keycodes alloc into keypad data 2. Moved irq hookup to probe from open 3. Other minor cleanups Cyril Chemparathy (5): input: add driver for tnetv107x on-chip keypad controller davinci: add tnetv107x keypad platform device davinci: add keypad config for tnetv107x evm board input: add driver for tnetv107x touchscreen controller davinci: add tnetv107x touchscreen platform device arch/arm/mach-davinci/board-tnetv107x-evm.c | 56 ++++ arch/arm/mach-davinci/devices-tnetv107x.c | 50 +++ arch/arm/mach-davinci/include/mach/tnetv107x.h | 3 + drivers/input/keyboard/Kconfig | 9 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/tnetv107x-keypad.c | 328 ++++++++++++++++++++ drivers/input/touchscreen/Kconfig | 9 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/tnetv107x-ts.c | 396 ++++++++++++++++++++++++ 9 files changed, 853 insertions(+), 0 deletions(-) create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c From cyril at ti.com Mon Sep 20 10:07:28 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 20 Sep 2010 11:07:28 -0400 Subject: [PATCH v3 1/5] input: add driver for tnetv107x on-chip keypad controller In-Reply-To: <1284995252-23337-1-git-send-email-cyril@ti.com> References: <1284995252-23337-1-git-send-email-cyril@ti.com> Message-ID: <1284995252-23337-2-git-send-email-cyril@ti.com> This patch adds support for tnetv107x's on-chip keypad controller. Signed-off-by: Cyril Chemparathy --- drivers/input/keyboard/Kconfig | 9 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/tnetv107x-keypad.c | 328 +++++++++++++++++++++++++++++ 3 files changed, 338 insertions(+), 0 deletions(-) create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 9cc488d..df1facb 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -424,6 +424,15 @@ config KEYBOARD_OMAP To compile this driver as a module, choose M here: the module will be called omap-keypad. +config KEYBOARD_TNETV107X + tristate "TI TNETV107X keypad support" + depends on ARCH_DAVINCI_TNETV107X + help + Say Y here if you want to use the TNETV107X keypad. + + To compile this driver as a module, choose M here: the + module will be called tnetv107x-keypad. + config KEYBOARD_TWL4030 tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" depends on TWL4030_CORE diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 504b591..dc04518 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o +obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c new file mode 100644 index 0000000..c704302 --- /dev/null +++ b/drivers/input/keyboard/tnetv107x-keypad.c @@ -0,0 +1,328 @@ +/* + * Texas Instruments TNETV107X Keypad Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BITS(x) (BIT(x) - 1) + +#define KEYPAD_ROWS 9 +#define KEYPAD_COLS 9 + +#define DEBOUNCE_MIN 0x400ul +#define DEBOUNCE_MAX 0x3ffffffful + +struct keypad_regs { + u32 rev; + u32 mode; + u32 mask; + u32 pol; + u32 dclock; + u32 rclock; + u32 stable_cnt; + u32 in_en; + u32 out; + u32 out_en; + u32 in; + u32 lock; + u32 pres[3]; +}; + +#define keypad_read(kp, reg) __raw_readl(&(kp)->regs->reg) +#define keypad_write(kp, reg, val) __raw_writel(val, &(kp)->regs->reg) + +struct keypad_data { + struct input_dev *input_dev; + struct resource *res; + struct keypad_regs __iomem *regs; + struct clk *clk; + struct device *dev; + u32 irq_press; + u32 irq_release; + int rows, cols, row_shift; + int debounce_ms, active_low; + u32 prev_keys[3]; + unsigned short keycodes[]; +}; + +static irqreturn_t keypad_irq(int irq, void *data) +{ + struct keypad_data *kp = data; + int i, bit, val, row, col, code; + u32 curr_keys[3]; + u32 change; + + memset(curr_keys, 0, sizeof(curr_keys)); + if (irq == kp->irq_press) + for (i = 0; i < 3; i++) + curr_keys[i] = keypad_read(kp, pres[i]); + + for (i = 0; i < 3; i++) { + change = curr_keys[i] ^ kp->prev_keys[i]; + + while (change) { + bit = fls(change) - 1; + change ^= BIT(bit); + val = curr_keys[i] & BIT(bit); + bit += i * 32; + row = bit / KEYPAD_COLS; + col = bit % KEYPAD_COLS; + + code = MATRIX_SCAN_CODE(row, col, kp->row_shift); + input_event(kp->input_dev, EV_MSC, MSC_SCAN, code); + input_report_key(kp->input_dev, kp->keycodes[code], + val); + } + } + input_sync(kp->input_dev); + memcpy(kp->prev_keys, curr_keys, sizeof(curr_keys)); + + if (irq == kp->irq_press) + keypad_write(kp, lock, 0); /* Allow hardware updates */ + + return IRQ_HANDLED; +} + +static int keypad_start(struct input_dev *dev) +{ + struct keypad_data *kp = input_get_drvdata(dev); + unsigned long mask, debounce, clk_rate_khz; + + clk_enable(kp->clk); + clk_rate_khz = clk_get_rate(kp->clk) / 1000; + + /* Initialize device registers */ + keypad_write(kp, mode, 0); + + mask = BITS(kp->rows) << KEYPAD_COLS; + mask |= BITS(kp->cols); + keypad_write(kp, mask, ~mask); + + keypad_write(kp, pol, kp->active_low ? 0 : 0x3ffff); + keypad_write(kp, stable_cnt, 3); + + debounce = kp->debounce_ms * clk_rate_khz; + debounce = clamp(debounce, DEBOUNCE_MIN, DEBOUNCE_MAX); + keypad_write(kp, dclock, debounce); + keypad_write(kp, rclock, 4 * debounce); + + keypad_write(kp, in_en, 1); + + return 0; +} + +static void keypad_stop(struct input_dev *dev) +{ + struct keypad_data *kp = input_get_drvdata(dev); + + synchronize_irq(kp->irq_press); + synchronize_irq(kp->irq_release); + clk_disable(kp->clk); +} + +static int __devinit keypad_probe(struct platform_device *pdev) +{ + const struct matrix_keypad_platform_data *pdata; + const struct matrix_keymap_data *keymap_data; + struct device *dev = &pdev->dev; + struct keypad_data *kp; + int error = 0, sz, row_shift; + u32 rev = 0; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(dev, "cannot find device data\n"); + return -EINVAL; + } + + keymap_data = pdata->keymap_data; + if (!keymap_data) { + dev_err(dev, "cannot find keymap data\n"); + return -EINVAL; + } + + row_shift = get_count_order(pdata->num_col_gpios); + sz = offsetof(struct keypad_data, keycodes); + sz += (pdata->num_row_gpios << row_shift) * sizeof(kp->keycodes[0]); + kp = kzalloc(sz, GFP_KERNEL); + if (!kp) { + dev_err(dev, "cannot allocate device info\n"); + return -ENOMEM; + } + + kp->dev = dev; + kp->rows = pdata->num_row_gpios; + kp->cols = pdata->num_col_gpios; + kp->row_shift = row_shift; + platform_set_drvdata(pdev, kp); + + kp->irq_press = platform_get_irq_byname(pdev, "press"); + kp->irq_release = platform_get_irq_byname(pdev, "release"); + if (kp->irq_press < 0 || kp->irq_release < 0) { + dev_err(dev, "cannot determine device interrupts\n"); + error = -ENODEV; + goto error_res; + } + + kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!kp->res) { + dev_err(dev, "cannot determine register area\n"); + error = -ENODEV; + goto error_res; + } + + if (!request_mem_region(kp->res->start, resource_size(kp->res), + pdev->name)) { + dev_err(dev, "cannot claim register memory\n"); + kp->res = NULL; + error = -EINVAL; + goto error_res; + } + + kp->regs = ioremap(kp->res->start, resource_size(kp->res)); + if (!kp->regs) { + dev_err(dev, "cannot map register memory\n"); + error = -ENOMEM; + goto error_map; + } + + kp->clk = clk_get(dev, NULL); + if (!kp->clk) { + dev_err(dev, "cannot claim device clock\n"); + error = -EINVAL; + goto error_clk; + } + + error = request_threaded_irq(kp->irq_press, NULL, keypad_irq, 0, + dev_name(dev), kp); + if (error < 0) { + dev_err(kp->dev, "Could not allocate keypad press key irq\n"); + goto error_irq_press; + } + + error = request_threaded_irq(kp->irq_release, NULL, keypad_irq, 0, + dev_name(dev), kp); + if (error < 0) { + dev_err(kp->dev, "Could not allocate keypad release key irq\n"); + goto error_irq_release; + } + + kp->input_dev = input_allocate_device(); + if (!kp->input_dev) { + dev_err(dev, "cannot allocate input device\n"); + error = -ENOMEM; + goto error_input; + } + input_set_drvdata(kp->input_dev, kp); + + kp->input_dev->name = pdev->name; + kp->input_dev->dev.parent = &pdev->dev; + kp->input_dev->open = keypad_start; + kp->input_dev->close = keypad_stop; + kp->input_dev->evbit[0] = BIT_MASK(EV_KEY); + if (!pdata->no_autorepeat) + kp->input_dev->evbit[0] |= BIT_MASK(EV_REP); + + clk_enable(kp->clk); + rev = keypad_read(kp, rev); + kp->input_dev->id.bustype = BUS_HOST; + kp->input_dev->id.product = ((rev >> 8) & 0x07); + kp->input_dev->id.version = ((rev >> 16) & 0xfff); + clk_disable(kp->clk); + + kp->input_dev->keycode = kp->keycodes; + kp->input_dev->keycodesize = sizeof(kp->keycodes[0]); + kp->input_dev->keycodemax = kp->rows << kp->row_shift; + + matrix_keypad_build_keymap(keymap_data, kp->row_shift, kp->keycodes, + kp->input_dev->keybit); + + input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN); + + error = input_register_device(kp->input_dev); + if (error < 0) { + dev_err(dev, "Could not register input device\n"); + goto error_reg; + } + + return 0; + + +error_reg: + input_free_device(kp->input_dev); +error_input: + free_irq(kp->irq_release, kp); +error_irq_release: + free_irq(kp->irq_press, kp); +error_irq_press: + clk_put(kp->clk); +error_clk: + iounmap(kp->regs); +error_map: + release_mem_region(kp->res->start, resource_size(kp->res)); +error_res: + platform_set_drvdata(pdev, NULL); + kfree(kp); + return error; +} + +static int __devexit keypad_remove(struct platform_device *pdev) +{ + struct keypad_data *kp = platform_get_drvdata(pdev); + + free_irq(kp->irq_press, kp); + free_irq(kp->irq_release, kp); + input_unregister_device(kp->input_dev); + clk_put(kp->clk); + iounmap(kp->regs); + release_mem_region(kp->res->start, resource_size(kp->res)); + platform_set_drvdata(pdev, NULL); + kfree(kp); + + return 0; +} + +static struct platform_driver keypad_driver = { + .probe = keypad_probe, + .remove = __devexit_p(keypad_remove), + .driver.name = "tnetv107x-keypad", + .driver.owner = THIS_MODULE, +}; + +static int __init keypad_init(void) +{ + return platform_driver_register(&keypad_driver); +} + +static void __exit keypad_exit(void) +{ + platform_driver_unregister(&keypad_driver); +} + +module_init(keypad_init); +module_exit(keypad_exit); + +MODULE_AUTHOR("Cyril Chemparathy"); +MODULE_DESCRIPTION("TNETV107X Keypad Driver"); +MODULE_ALIAS("platform: tnetv107x-keypad"); +MODULE_LICENSE("GPL"); -- 1.7.0.4 From cyril at ti.com Mon Sep 20 10:07:32 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 20 Sep 2010 11:07:32 -0400 Subject: [PATCH v3 5/5] davinci: add tnetv107x touchscreen platform device In-Reply-To: <1284995252-23337-1-git-send-email-cyril@ti.com> References: <1284995252-23337-1-git-send-email-cyril@ti.com> Message-ID: <1284995252-23337-6-git-send-email-cyril@ti.com> This patch adds a platform device definition for tnetv107x's touchscreen controller. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/devices-tnetv107x.c | 20 ++++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c index 086269f..c9a86d8 100644 --- a/arch/arm/mach-davinci/devices-tnetv107x.c +++ b/arch/arm/mach-davinci/devices-tnetv107x.c @@ -31,6 +31,7 @@ #define TNETV107X_TPTC0_BASE 0x01c10000 #define TNETV107X_TPTC1_BASE 0x01c10400 #define TNETV107X_WDOG_BASE 0x08086700 +#define TNETV107X_TSC_BASE 0x08088500 #define TNETV107X_SDIO0_BASE 0x08088700 #define TNETV107X_SDIO1_BASE 0x08088800 #define TNETV107X_KEYPAD_BASE 0x08088a00 @@ -323,12 +324,31 @@ static struct platform_device keypad_device = { .resource = keypad_resources, }; +static struct resource tsc_resources[] = { + { + .start = TNETV107X_TSC_BASE, + .end = TNETV107X_TSC_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_TNETV107X_TSC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device tsc_device = { + .name = "tnetv107x-ts", + .num_resources = ARRAY_SIZE(tsc_resources), + .resource = tsc_resources, +}; + void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) { int i; platform_device_register(&edma_device); platform_device_register(&tnetv107x_wdt_device); + platform_device_register(&tsc_device); if (info->serial_config) davinci_serial_init(info->serial_config); -- 1.7.0.4 From cyril at ti.com Mon Sep 20 10:07:31 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 20 Sep 2010 11:07:31 -0400 Subject: [PATCH v3 4/5] input: add driver for tnetv107x touchscreen controller In-Reply-To: <1284995252-23337-1-git-send-email-cyril@ti.com> References: <1284995252-23337-1-git-send-email-cyril@ti.com> Message-ID: <1284995252-23337-5-git-send-email-cyril@ti.com> This patch adds support for tnetv107x's on-chip touchscreen controller. Signed-off-by: Cyril Chemparathy --- drivers/input/touchscreen/Kconfig | 9 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/tnetv107x-ts.c | 396 ++++++++++++++++++++++++++++++ 3 files changed, 406 insertions(+), 0 deletions(-) create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 0069d97..8d32028 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -328,6 +328,15 @@ config TOUCHSCREEN_MIGOR To compile this driver as a module, choose M here: the module will be called migor_ts. +config TOUCHSCREEN_TNETV107X + tristate "TI TNETV107X touchscreen support" + depends on ARCH_DAVINCI_TNETV107X + help + Say Y here if you want to use the TNETV107X touchscreen. + + To compile this driver as a module, choose M here: the + module will be called tnetv107x-ts. + config TOUCHSCREEN_TOUCHRIGHT tristate "Touchright serial touchscreen" select SERIO diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 28217e1..d41a964 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o +obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c new file mode 100644 index 0000000..cf1dba2 --- /dev/null +++ b/drivers/input/touchscreen/tnetv107x-ts.c @@ -0,0 +1,396 @@ +/* + * Texas Instruments TNETV107X Touchscreen Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define TSC_PENUP_POLL (HZ / 5) +#define IDLE_TIMEOUT 100 /* msec */ + +/* + * The first and last samples of a touch interval are usually garbage and need + * to be filtered out with these devices. The following definitions control + * the number of samples skipped. + */ +#define TSC_HEAD_SKIP 1 +#define TSC_TAIL_SKIP 1 +#define TSC_SKIP (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1) +#define TSC_SAMPLES (TSC_SKIP + 1) + +/* Register Offsets */ +struct tsc_regs { + u32 rev; + u32 tscm; + u32 bwcm; + u32 swc; + u32 adcchnl; + u32 adcdata; + u32 chval[4]; +}; + +/* TSC Mode Configuration Register (tscm) bits */ +#define WMODE BIT(0) +#define TSKIND BIT(1) +#define ZMEASURE_EN BIT(2) +#define IDLE BIT(3) +#define TSC_EN BIT(4) +#define STOP BIT(5) +#define ONE_SHOT BIT(6) +#define SINGLE BIT(7) +#define AVG BIT(8) +#define AVGNUM(x) (((x) & 0x03) << 9) +#define PVSTC(x) (((x) & 0x07) << 11) +#define PON BIT(14) +#define PONBG BIT(15) +#define AFERST BIT(16) + +/* ADC DATA Capture Register bits */ +#define DATA_VALID BIT(16) + +/* Register Access Macros */ +#define tsc_read(ts, reg) __raw_readl(&(ts)->regs->reg) +#define tsc_write(ts, reg, val) __raw_writel(val, &(ts)->regs->reg); +#define tsc_set_bits(ts, reg, val) \ + tsc_write(ts, reg, tsc_read(ts, reg) | (val)) +#define tsc_clr_bits(ts, reg, val) \ + tsc_write(ts, reg, tsc_read(ts, reg) & ~(val)) + +struct sample { + int x, y, p; +}; + +struct tsc_data { + struct input_dev *input_dev; + struct resource *res; + struct tsc_regs __iomem *regs; + struct timer_list timer; + spinlock_t lock; + struct clk *clk; + struct device *dev; + int sample_count; + struct sample samples[TSC_SAMPLES]; + int tsc_irq; +}; + +static int tsc_read_sample(struct tsc_data *ts, struct sample* sample) +{ + int x, y, z1, z2, t, p = 0; + u32 val; + + val = tsc_read(ts, chval[0]); + if (val & DATA_VALID) + x = val & 0xffff; + else + return -EINVAL; + + y = tsc_read(ts, chval[1]) & 0xffff; + z1 = tsc_read(ts, chval[2]) & 0xffff; + z2 = tsc_read(ts, chval[3]) & 0xffff; + + if (z1) { + t = ((600 * x) * (z2 - z1)); + p = t / (u32) (z1 << 12); + if (p < 0) + p = 0; + } + + sample->x = x; + sample->y = y; + sample->p = p; + + return 0; +} + +static void tsc_poll(unsigned long data) +{ + struct tsc_data *ts = (struct tsc_data *)data; + unsigned long flags; + int i, val, x, y, p; + + spin_lock_irqsave(&ts->lock, flags); + + if (ts->sample_count >= TSC_SKIP) { + input_report_abs(ts->input_dev, ABS_PRESSURE, 0); + input_report_key(ts->input_dev, BTN_TOUCH, 0); + input_sync(ts->input_dev); + } else if (ts->sample_count > 0) { + /* + * A touch event lasted less than our skip count. Salvage and + * report anyway. + */ + for (i = 0, val = 0; i < ts->sample_count; i++) + val += ts->samples[i].x; + x = val / ts->sample_count; + + for (i = 0, val = 0; i < ts->sample_count; i++) + val += ts->samples[i].y; + y = val / ts->sample_count; + + for (i = 0, val = 0; i < ts->sample_count; i++) + val += ts->samples[i].p; + p = val / ts->sample_count; + + input_report_abs(ts->input_dev, ABS_X, x); + input_report_abs(ts->input_dev, ABS_Y, y); + input_report_abs(ts->input_dev, ABS_PRESSURE, p); + input_report_key(ts->input_dev, BTN_TOUCH, 1); + input_sync(ts->input_dev); + } + + ts->sample_count = 0; + + spin_unlock_irqrestore(&ts->lock, flags); +} + +static irqreturn_t tsc_irq(int irq, void *dev_id) +{ + struct tsc_data *ts = (struct tsc_data *)dev_id; + struct sample *sample; + int index; + + spin_lock(&ts->lock); + + index = ts->sample_count % TSC_SAMPLES; + sample = &ts->samples[index]; + if (tsc_read_sample(ts, sample) < 0) + goto out; + + if (++ts->sample_count >= TSC_SKIP) { + index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES; + sample = &ts->samples[index]; + + input_report_abs(ts->input_dev, ABS_X, sample->x); + input_report_abs(ts->input_dev, ABS_Y, sample->y); + input_report_abs(ts->input_dev, ABS_PRESSURE, sample->p); + if (ts->sample_count == TSC_SKIP) + input_report_key(ts->input_dev, BTN_TOUCH, 1); + input_sync(ts->input_dev); + } + mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL); +out: + spin_unlock(&ts->lock); + return IRQ_HANDLED; +} + +static int tsc_start(struct input_dev *dev) +{ + struct tsc_data *ts = input_get_drvdata(dev); + unsigned long timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT); + u32 val; + + clk_enable(ts->clk); + + /* Go to idle mode, before any initialization */ + while (time_after(timeout, jiffies)) { + if (tsc_read(ts, tscm) & IDLE) + break; + } + + if (time_before(timeout, jiffies)) { + dev_warn(ts->dev, "timeout waiting for idle\n"); + clk_disable(ts->clk); + return -EIO; + } + + /* Configure TSC Control register*/ + val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN); + tsc_write(ts, tscm, val); + + /* Bring TSC out of reset: Clear AFE reset bit */ + val &= ~(AFERST); + tsc_write(ts, tscm, val); + + /* Configure all pins for hardware control*/ + tsc_write(ts, bwcm, 0); + + /* Finally enable the TSC */ + tsc_set_bits(ts, tscm, TSC_EN); + + return 0; +} + +static void tsc_stop(struct input_dev *dev) +{ + struct tsc_data *ts = input_get_drvdata(dev); + + tsc_clr_bits(ts, tscm, TSC_EN); + synchronize_irq(ts->tsc_irq); + del_timer_sync(&ts->timer); + clk_disable(ts->clk); +} + +static int __devinit tsc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tsc_data *ts; + int error = 0; + u32 rev = 0; + + ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL); + if (!ts) { + dev_err(dev, "cannot allocate device info\n"); + return -ENOMEM; + } + + ts->dev = dev; + spin_lock_init(&ts->lock); + setup_timer(&ts->timer, tsc_poll, (unsigned long)ts); + platform_set_drvdata(pdev, ts); + + ts->tsc_irq = platform_get_irq(pdev, 0); + if (ts->tsc_irq < 0) { + dev_err(dev, "cannot determine device interrupt\n"); + error = -ENODEV; + goto error_res; + } + + ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!ts->res) { + dev_err(dev, "cannot determine register area\n"); + error = -ENODEV; + goto error_res; + } + + if (!request_mem_region(ts->res->start, resource_size(ts->res), + pdev->name)) { + dev_err(dev, "cannot claim register memory\n"); + ts->res = NULL; + error = -EINVAL; + goto error_res; + } + + ts->regs = ioremap(ts->res->start, resource_size(ts->res)); + if (!ts->regs) { + dev_err(dev, "cannot map register memory\n"); + error = -ENOMEM; + goto error_map; + } + + ts->clk = clk_get(dev, NULL); + if (!ts->clk) { + dev_err(dev, "cannot claim device clock\n"); + error = -EINVAL; + goto error_clk; + } + + error = request_threaded_irq(ts->tsc_irq, NULL, tsc_irq, 0, + dev_name(dev), ts); + if (error < 0) { + dev_err(ts->dev, "Could not allocate ts irq\n"); + goto error_irq; + } + + ts->input_dev = input_allocate_device(); + if (!ts->input_dev) { + dev_err(dev, "cannot allocate input device\n"); + error = -ENOMEM; + goto error_input; + } + input_set_drvdata(ts->input_dev, ts); + + ts->input_dev->name = pdev->name; + ts->input_dev->id.bustype = BUS_HOST; + ts->input_dev->dev.parent = &pdev->dev; + ts->input_dev->open = tsc_start; + ts->input_dev->close = tsc_stop; + + clk_enable(ts->clk); + rev = tsc_read(ts, rev); + ts->input_dev->id.product = ((rev >> 8) & 0x07); + ts->input_dev->id.version = ((rev >> 16) & 0xfff); + clk_disable(ts->clk); + + __set_bit(EV_KEY, ts->input_dev->evbit); + __set_bit(EV_ABS, ts->input_dev->evbit); + __set_bit(BTN_TOUCH, ts->input_dev->keybit); + + input_set_abs_params(ts->input_dev, ABS_X, 0, 0xffff, 5, 0); + input_set_abs_params(ts->input_dev, ABS_Y, 0, 0xffff, 5, 0); + input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0); + + error = input_register_device(ts->input_dev); + if (error < 0) { + dev_err(dev, "failed input device registration\n"); + goto error_reg; + } + + return 0; + +error_reg: + input_free_device(ts->input_dev); +error_input: + free_irq(ts->tsc_irq, ts); +error_irq: + clk_put(ts->clk); +error_clk: + iounmap(ts->regs); +error_map: + release_mem_region(ts->res->start, resource_size(ts->res)); +error_res: + platform_set_drvdata(pdev, NULL); + kfree(ts); + + return error; +} + +static int __devexit tsc_remove(struct platform_device *pdev) +{ + struct tsc_data *ts = platform_get_drvdata(pdev); + + input_unregister_device(ts->input_dev); + free_irq(ts->tsc_irq, ts); + clk_put(ts->clk); + iounmap(ts->regs); + release_mem_region(ts->res->start, resource_size(ts->res)); + platform_set_drvdata(pdev, NULL); + kfree(ts); + + return 0; +} + +static struct platform_driver tsc_driver = { + .probe = tsc_probe, + .remove = __devexit_p(tsc_remove), + .driver.name = "tnetv107x-ts", + .driver.owner = THIS_MODULE, +}; + +static int __init tsc_init(void) +{ + return platform_driver_register(&tsc_driver); +} + +static void __exit tsc_exit(void) +{ + platform_driver_unregister(&tsc_driver); +} + +module_init(tsc_init); +module_exit(tsc_exit); + +MODULE_AUTHOR("Cyril Chemparathy"); +MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); +MODULE_ALIAS("platform: tnetv107x-ts"); +MODULE_LICENSE("GPL"); -- 1.7.0.4 From cyril at ti.com Mon Sep 20 10:07:30 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 20 Sep 2010 11:07:30 -0400 Subject: [PATCH v3 3/5] davinci: add keypad config for tnetv107x evm board In-Reply-To: <1284995252-23337-1-git-send-email-cyril@ti.com> References: <1284995252-23337-1-git-send-email-cyril@ti.com> Message-ID: <1284995252-23337-4-git-send-email-cyril@ti.com> This patch adds evm board specific keymap definitions and controller configuration data for on-chip keypad controller on tnetv107x silicon. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/board-tnetv107x-evm.c | 56 +++++++++++++++++++++++++++ 1 files changed, 56 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c index fe2a9d9..5afa8fc 100644 --- a/arch/arm/mach-davinci/board-tnetv107x-evm.c +++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c @@ -23,6 +23,9 @@ #include #include #include +#include +#include + #include #include @@ -141,10 +144,63 @@ static struct davinci_uart_config serial_config __initconst = { .enabled_uarts = BIT(1), }; +static const uint32_t keymap[] = { + KEY(0, 0, KEY_NUMERIC_1), + KEY(0, 1, KEY_NUMERIC_2), + KEY(0, 2, KEY_NUMERIC_3), + KEY(0, 3, KEY_FN_F1), + KEY(0, 4, KEY_MENU), + + KEY(1, 0, KEY_NUMERIC_4), + KEY(1, 1, KEY_NUMERIC_5), + KEY(1, 2, KEY_NUMERIC_6), + KEY(1, 3, KEY_UP), + KEY(1, 4, KEY_FN_F2), + + KEY(2, 0, KEY_NUMERIC_7), + KEY(2, 1, KEY_NUMERIC_8), + KEY(2, 2, KEY_NUMERIC_9), + KEY(2, 3, KEY_LEFT), + KEY(2, 4, KEY_ENTER), + + KEY(3, 0, KEY_NUMERIC_STAR), + KEY(3, 1, KEY_NUMERIC_0), + KEY(3, 2, KEY_NUMERIC_POUND), + KEY(3, 3, KEY_DOWN), + KEY(3, 4, KEY_RIGHT), + + KEY(4, 0, KEY_FN_F3), + KEY(4, 1, KEY_FN_F4), + KEY(4, 2, KEY_MUTE), + KEY(4, 3, KEY_HOME), + KEY(4, 4, KEY_BACK), + + KEY(5, 0, KEY_VOLUMEDOWN), + KEY(5, 1, KEY_VOLUMEUP), + KEY(5, 2, KEY_F1), + KEY(5, 3, KEY_F2), + KEY(5, 4, KEY_F3), +}; + +static const struct matrix_keymap_data keymap_data = { + .keymap = keymap, + .keymap_size = ARRAY_SIZE(keymap), +}; + +static struct matrix_keypad_platform_data keypad_config = { + .keymap_data = &keymap_data, + .num_row_gpios = 6, + .num_col_gpios = 5, + .debounce_ms = 0, /* minimum */ + .active_low = 0, /* pull up realization */ + .no_autorepeat = 0, +}; + static struct tnetv107x_device_info evm_device_info __initconst = { .serial_config = &serial_config, .mmc_config[1] = &mmc_config, /* controller 1 */ .nand_config[0] = &nand_config, /* chip select 0 */ + .keypad_config = &keypad_config, }; static __init void tnetv107x_evm_board_init(void) -- 1.7.0.4 From cyril at ti.com Mon Sep 20 10:07:29 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 20 Sep 2010 11:07:29 -0400 Subject: [PATCH v3 2/5] davinci: add tnetv107x keypad platform device In-Reply-To: <1284995252-23337-1-git-send-email-cyril@ti.com> References: <1284995252-23337-1-git-send-email-cyril@ti.com> Message-ID: <1284995252-23337-3-git-send-email-cyril@ti.com> This patch adds a platform device definition for tnetv107x's keypad controller. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/devices-tnetv107x.c | 30 ++++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/tnetv107x.h | 3 ++ 2 files changed, 33 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c index 2718a3a..086269f 100644 --- a/arch/arm/mach-davinci/devices-tnetv107x.c +++ b/arch/arm/mach-davinci/devices-tnetv107x.c @@ -33,6 +33,7 @@ #define TNETV107X_WDOG_BASE 0x08086700 #define TNETV107X_SDIO0_BASE 0x08088700 #define TNETV107X_SDIO1_BASE 0x08088800 +#define TNETV107X_KEYPAD_BASE 0x08088a00 #define TNETV107X_ASYNC_EMIF_CNTRL_BASE 0x08200000 #define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE 0x30000000 #define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE 0x40000000 @@ -298,6 +299,30 @@ static int __init nand_init(int chipsel, struct davinci_nand_pdata *data) return platform_device_register(pdev); } +static struct resource keypad_resources[] = { + { + .start = TNETV107X_KEYPAD_BASE, + .end = TNETV107X_KEYPAD_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_TNETV107X_KEYPAD, + .flags = IORESOURCE_IRQ, + .name = "press", + }, + { + .start = IRQ_TNETV107X_KEYPAD_FREE, + .flags = IORESOURCE_IRQ, + .name = "release", + }, +}; + +static struct platform_device keypad_device = { + .name = "tnetv107x-keypad", + .num_resources = ARRAY_SIZE(keypad_resources), + .resource = keypad_resources, +}; + void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) { int i; @@ -317,4 +342,9 @@ void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) for (i = 0; i < 4; i++) if (info->nand_config[i]) nand_init(i, info->nand_config[i]); + + if (info->keypad_config) { + keypad_device.dev.platform_data = info->keypad_config; + platform_device_register(&keypad_device); + } } diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h index c720647..5a681d8 100644 --- a/arch/arm/mach-davinci/include/mach/tnetv107x.h +++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h @@ -33,6 +33,8 @@ #ifndef __ASSEMBLY__ #include +#include + #include #include #include @@ -41,6 +43,7 @@ struct tnetv107x_device_info { struct davinci_uart_config *serial_config; struct davinci_mmc_config *mmc_config[2]; /* 2 controllers */ struct davinci_nand_pdata *nand_config[4]; /* 4 chipsels */ + struct matrix_keypad_platform_data *keypad_config; }; extern struct platform_device tnetv107x_wdt_device; -- 1.7.0.4 From nsekhar at ti.com Mon Sep 20 10:08:00 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Mon, 20 Sep 2010 20:38:00 +0530 Subject: [PATCH v5 1/1] davinci: spi: replace existing driver In-Reply-To: <4C94B9BD.4010606@criticallink.com> References: <1280355490-11878-1-git-send-email-bniebuhr@efjohnson.com> <4C8EB795.1080607@criticallink.com> <201009140904.59555.caglarakyuz@gmail.com> <4C8F7460.6050006@criticallink.com> <4C94B9BD.4010606@criticallink.com> Message-ID: Hi Michael, On Sat, Sep 18, 2010 at 18:38:13, Michael Williamson wrote: > On 09/14/2010 09:26 AM, Nori, Sekhar wrote: > > Hi Mike, > > > > On Tue, Sep 14, 2010 at 18:40:56, Michael Williamson wrote: > >> On 9/14/2010 3:14 AM, Nori, Sekhar wrote: > >> > >>> On Tue, Sep 14, 2010 at 11:34:59, Caglar Akyuz wrote: > >>> > >>>> Yes, your patches seems ok and mostly complete. I'm waiting for hardware to > >>>> test those, will let you know when I do some testing. > >>> > >>> Thanks! To save time, I haven't tested these patches myself. I have only made > >>> sure individual patches don't break the build. Was planning to test after > >>> the complete series is ready. > >>> > >> > >> > >> If it would help, If there are portions of the patch set that can be tested > >> with DMA disabled or something, I'd be willing to kick the tires. I have > >> da850 hardware available. > > > > Thanks for being brave and offering to help! Yes, interrupt and polled mode > > can be tried. Since a lot of testing has already happened on the original patch, > > I was planning to test the series only after it is complete. Any issues found can > > be narrowed down to the differences (which I hope will be justifiable). > > > > Thanks, > > Sekhar > > So I am testing with a configuration which is pretty much the same as the da850 EVM; > a SPI-NOR flash on the first chip select of SPI1. Both poll and interrupt modes > work. So far so good, and Brian's work really sorted out a bunch of questions > I had looking at the original spi code. Nice work, Nori, for break the patch > into logical blocks. I do have a couple of comments: Really?? Just worked? Wooohooo... > > * I'm not sure I understand why there is a "intr_line" field in the platform > data and then a possibility to configure an "io_type" as interrupt or polled at > the chip select level. I got burned by setting the "io_type" to SPI_IO_TYPE_INTR > and not setting "intr_line" to non-zero. The probe just hung because it was > trying to use interrupts but never setting SPILVL register. These fields aren't > mutually exclusive. Is the intent to support a configuration with one chip select > running in polled mode and another in interrupt mode? If so, then it seems the SPILVL > register logic needs some attention during each transfer. The intr_line to be set is constant for the SoC. So, irrespective of what the individual devices on a given board choose to operate (interrupted, polled or DMA) the SoC code (da850.c) should setup the intr_line according to how the SPI interrupt is wired within the SoC. Can you clarify what you mean by "needs some attention during each transfer"? > > * As a (novice) user, I'd really like to see some comments / hints added to the > ../mach-davinci/include/mach/spi.h file to describe how all of the platform fields > should be set. Some of the fields aren't very obvious as to how to initialize > them without having a data sheet on one screen and plowing through the > driver on another. This might have cleaned up my confusion on the first item. Good point. Will ensure this. Thanks, Sekhar From cyril at ti.com Mon Sep 20 11:26:39 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 20 Sep 2010 12:26:39 -0400 Subject: [PATCH v4 0/5] add tnetv107x input drivers Message-ID: <1285000004-9464-1-git-send-email-cyril@ti.com> Texas Instruments' TNETV107X is an ARM1176 based SoC, with on-chip touchscreen and keypad controllers. This patch series adds drivers for these controllers. Changes between v1 and v2: 1. Cleaned up platform data needs by reusing matrix keypad pdata 2. Eliminated calibration code from touch driver 3. Relocated h/w init code to open and close 4. Other minor cleanups Changes between v2 and v3: 1. Merged keycodes alloc into keypad data 2. Moved irq hookup to probe from open 3. Other minor cleanups Changes between v3 and v4: 1. Locking between hardirqs for keypad driver Cyril Chemparathy (5): input: add driver for tnetv107x on-chip keypad controller davinci: add tnetv107x keypad platform device davinci: add keypad config for tnetv107x evm board input: add driver for tnetv107x touchscreen controller davinci: add tnetv107x touchscreen platform device arch/arm/mach-davinci/board-tnetv107x-evm.c | 56 ++++ arch/arm/mach-davinci/devices-tnetv107x.c | 50 +++ arch/arm/mach-davinci/include/mach/tnetv107x.h | 3 + drivers/input/keyboard/Kconfig | 9 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/tnetv107x-keypad.c | 340 ++++++++++++++++++++ drivers/input/touchscreen/Kconfig | 9 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/tnetv107x-ts.c | 396 ++++++++++++++++++++++++ 9 files changed, 865 insertions(+), 0 deletions(-) create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c From cyril at ti.com Mon Sep 20 11:26:41 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 20 Sep 2010 12:26:41 -0400 Subject: [PATCH v4 2/5] davinci: add tnetv107x keypad platform device In-Reply-To: <1285000004-9464-1-git-send-email-cyril@ti.com> References: <1285000004-9464-1-git-send-email-cyril@ti.com> Message-ID: <1285000004-9464-3-git-send-email-cyril@ti.com> This patch adds a platform device definition for tnetv107x's keypad controller. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/devices-tnetv107x.c | 30 ++++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/tnetv107x.h | 3 ++ 2 files changed, 33 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c index 2718a3a..086269f 100644 --- a/arch/arm/mach-davinci/devices-tnetv107x.c +++ b/arch/arm/mach-davinci/devices-tnetv107x.c @@ -33,6 +33,7 @@ #define TNETV107X_WDOG_BASE 0x08086700 #define TNETV107X_SDIO0_BASE 0x08088700 #define TNETV107X_SDIO1_BASE 0x08088800 +#define TNETV107X_KEYPAD_BASE 0x08088a00 #define TNETV107X_ASYNC_EMIF_CNTRL_BASE 0x08200000 #define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE 0x30000000 #define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE 0x40000000 @@ -298,6 +299,30 @@ static int __init nand_init(int chipsel, struct davinci_nand_pdata *data) return platform_device_register(pdev); } +static struct resource keypad_resources[] = { + { + .start = TNETV107X_KEYPAD_BASE, + .end = TNETV107X_KEYPAD_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_TNETV107X_KEYPAD, + .flags = IORESOURCE_IRQ, + .name = "press", + }, + { + .start = IRQ_TNETV107X_KEYPAD_FREE, + .flags = IORESOURCE_IRQ, + .name = "release", + }, +}; + +static struct platform_device keypad_device = { + .name = "tnetv107x-keypad", + .num_resources = ARRAY_SIZE(keypad_resources), + .resource = keypad_resources, +}; + void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) { int i; @@ -317,4 +342,9 @@ void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) for (i = 0; i < 4; i++) if (info->nand_config[i]) nand_init(i, info->nand_config[i]); + + if (info->keypad_config) { + keypad_device.dev.platform_data = info->keypad_config; + platform_device_register(&keypad_device); + } } diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h index c720647..5a681d8 100644 --- a/arch/arm/mach-davinci/include/mach/tnetv107x.h +++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h @@ -33,6 +33,8 @@ #ifndef __ASSEMBLY__ #include +#include + #include #include #include @@ -41,6 +43,7 @@ struct tnetv107x_device_info { struct davinci_uart_config *serial_config; struct davinci_mmc_config *mmc_config[2]; /* 2 controllers */ struct davinci_nand_pdata *nand_config[4]; /* 4 chipsels */ + struct matrix_keypad_platform_data *keypad_config; }; extern struct platform_device tnetv107x_wdt_device; -- 1.7.0.4 From cyril at ti.com Mon Sep 20 11:26:40 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 20 Sep 2010 12:26:40 -0400 Subject: [PATCH v4 1/5] input: add driver for tnetv107x on-chip keypad controller In-Reply-To: <1285000004-9464-1-git-send-email-cyril@ti.com> References: <1285000004-9464-1-git-send-email-cyril@ti.com> Message-ID: <1285000004-9464-2-git-send-email-cyril@ti.com> This patch adds support for tnetv107x's on-chip keypad controller. Signed-off-by: Cyril Chemparathy Acked-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 9 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/tnetv107x-keypad.c | 340 +++++++++++++++++++++++++++++ 3 files changed, 350 insertions(+), 0 deletions(-) create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 9cc488d..df1facb 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -424,6 +424,15 @@ config KEYBOARD_OMAP To compile this driver as a module, choose M here: the module will be called omap-keypad. +config KEYBOARD_TNETV107X + tristate "TI TNETV107X keypad support" + depends on ARCH_DAVINCI_TNETV107X + help + Say Y here if you want to use the TNETV107X keypad. + + To compile this driver as a module, choose M here: the + module will be called tnetv107x-keypad. + config KEYBOARD_TWL4030 tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" depends on TWL4030_CORE diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 504b591..dc04518 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o +obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c new file mode 100644 index 0000000..b4a81eb --- /dev/null +++ b/drivers/input/keyboard/tnetv107x-keypad.c @@ -0,0 +1,340 @@ +/* + * Texas Instruments TNETV107X Keypad Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BITS(x) (BIT(x) - 1) + +#define KEYPAD_ROWS 9 +#define KEYPAD_COLS 9 + +#define DEBOUNCE_MIN 0x400ul +#define DEBOUNCE_MAX 0x3ffffffful + +struct keypad_regs { + u32 rev; + u32 mode; + u32 mask; + u32 pol; + u32 dclock; + u32 rclock; + u32 stable_cnt; + u32 in_en; + u32 out; + u32 out_en; + u32 in; + u32 lock; + u32 pres[3]; +}; + +#define keypad_read(kp, reg) __raw_readl(&(kp)->regs->reg) +#define keypad_write(kp, reg, val) __raw_writel(val, &(kp)->regs->reg) + +struct keypad_data { + struct input_dev *input_dev; + struct resource *res; + struct keypad_regs __iomem *regs; + struct clk *clk; + struct device *dev; + spinlock_t lock; + u32 irq_press; + u32 irq_release; + int rows, cols, row_shift; + int debounce_ms, active_low; + u32 prev_keys[3]; + unsigned short keycodes[]; +}; + +static irqreturn_t keypad_irq(int irq, void *data) +{ + struct keypad_data *kp = data; + int i, bit, val, row, col, code; + unsigned long flags; + u32 curr_keys[3]; + u32 change; + + spin_lock_irqsave(&kp->lock, flags); + + memset(curr_keys, 0, sizeof(curr_keys)); + if (irq == kp->irq_press) + for (i = 0; i < 3; i++) + curr_keys[i] = keypad_read(kp, pres[i]); + + for (i = 0; i < 3; i++) { + change = curr_keys[i] ^ kp->prev_keys[i]; + + while (change) { + bit = fls(change) - 1; + change ^= BIT(bit); + val = curr_keys[i] & BIT(bit); + bit += i * 32; + row = bit / KEYPAD_COLS; + col = bit % KEYPAD_COLS; + + code = MATRIX_SCAN_CODE(row, col, kp->row_shift); + input_event(kp->input_dev, EV_MSC, MSC_SCAN, code); + input_report_key(kp->input_dev, kp->keycodes[code], + val); + } + } + input_sync(kp->input_dev); + memcpy(kp->prev_keys, curr_keys, sizeof(curr_keys)); + + if (irq == kp->irq_press) + keypad_write(kp, lock, 0); /* Allow hardware updates */ + + spin_unlock_irqrestore(&kp->lock, flags); + + return IRQ_HANDLED; +} + +static int keypad_start(struct input_dev *dev) +{ + struct keypad_data *kp = input_get_drvdata(dev); + unsigned long mask, debounce, clk_rate_khz; + unsigned long flags; + + clk_enable(kp->clk); + clk_rate_khz = clk_get_rate(kp->clk) / 1000; + + spin_lock_irqsave(&kp->lock, flags); + + /* Initialize device registers */ + keypad_write(kp, mode, 0); + + mask = BITS(kp->rows) << KEYPAD_COLS; + mask |= BITS(kp->cols); + keypad_write(kp, mask, ~mask); + + keypad_write(kp, pol, kp->active_low ? 0 : 0x3ffff); + keypad_write(kp, stable_cnt, 3); + + debounce = kp->debounce_ms * clk_rate_khz; + debounce = clamp(debounce, DEBOUNCE_MIN, DEBOUNCE_MAX); + keypad_write(kp, dclock, debounce); + keypad_write(kp, rclock, 4 * debounce); + + keypad_write(kp, in_en, 1); + + spin_unlock_irqrestore(&kp->lock, flags); + + return 0; +} + +static void keypad_stop(struct input_dev *dev) +{ + struct keypad_data *kp = input_get_drvdata(dev); + + synchronize_irq(kp->irq_press); + synchronize_irq(kp->irq_release); + clk_disable(kp->clk); +} + +static int __devinit keypad_probe(struct platform_device *pdev) +{ + const struct matrix_keypad_platform_data *pdata; + const struct matrix_keymap_data *keymap_data; + struct device *dev = &pdev->dev; + struct keypad_data *kp; + int error = 0, sz, row_shift; + u32 rev = 0; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(dev, "cannot find device data\n"); + return -EINVAL; + } + + keymap_data = pdata->keymap_data; + if (!keymap_data) { + dev_err(dev, "cannot find keymap data\n"); + return -EINVAL; + } + + row_shift = get_count_order(pdata->num_col_gpios); + sz = offsetof(struct keypad_data, keycodes); + sz += (pdata->num_row_gpios << row_shift) * sizeof(kp->keycodes[0]); + kp = kzalloc(sz, GFP_KERNEL); + if (!kp) { + dev_err(dev, "cannot allocate device info\n"); + return -ENOMEM; + } + + kp->dev = dev; + kp->rows = pdata->num_row_gpios; + kp->cols = pdata->num_col_gpios; + kp->row_shift = row_shift; + platform_set_drvdata(pdev, kp); + spin_lock_init(&kp->lock); + + kp->irq_press = platform_get_irq_byname(pdev, "press"); + kp->irq_release = platform_get_irq_byname(pdev, "release"); + if (kp->irq_press < 0 || kp->irq_release < 0) { + dev_err(dev, "cannot determine device interrupts\n"); + error = -ENODEV; + goto error_res; + } + + kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!kp->res) { + dev_err(dev, "cannot determine register area\n"); + error = -ENODEV; + goto error_res; + } + + if (!request_mem_region(kp->res->start, resource_size(kp->res), + pdev->name)) { + dev_err(dev, "cannot claim register memory\n"); + kp->res = NULL; + error = -EINVAL; + goto error_res; + } + + kp->regs = ioremap(kp->res->start, resource_size(kp->res)); + if (!kp->regs) { + dev_err(dev, "cannot map register memory\n"); + error = -ENOMEM; + goto error_map; + } + + kp->clk = clk_get(dev, NULL); + if (!kp->clk) { + dev_err(dev, "cannot claim device clock\n"); + error = -EINVAL; + goto error_clk; + } + + error = request_threaded_irq(kp->irq_press, NULL, keypad_irq, 0, + dev_name(dev), kp); + if (error < 0) { + dev_err(kp->dev, "Could not allocate keypad press key irq\n"); + goto error_irq_press; + } + + error = request_threaded_irq(kp->irq_release, NULL, keypad_irq, 0, + dev_name(dev), kp); + if (error < 0) { + dev_err(kp->dev, "Could not allocate keypad release key irq\n"); + goto error_irq_release; + } + + kp->input_dev = input_allocate_device(); + if (!kp->input_dev) { + dev_err(dev, "cannot allocate input device\n"); + error = -ENOMEM; + goto error_input; + } + input_set_drvdata(kp->input_dev, kp); + + kp->input_dev->name = pdev->name; + kp->input_dev->dev.parent = &pdev->dev; + kp->input_dev->open = keypad_start; + kp->input_dev->close = keypad_stop; + kp->input_dev->evbit[0] = BIT_MASK(EV_KEY); + if (!pdata->no_autorepeat) + kp->input_dev->evbit[0] |= BIT_MASK(EV_REP); + + clk_enable(kp->clk); + rev = keypad_read(kp, rev); + kp->input_dev->id.bustype = BUS_HOST; + kp->input_dev->id.product = ((rev >> 8) & 0x07); + kp->input_dev->id.version = ((rev >> 16) & 0xfff); + clk_disable(kp->clk); + + kp->input_dev->keycode = kp->keycodes; + kp->input_dev->keycodesize = sizeof(kp->keycodes[0]); + kp->input_dev->keycodemax = kp->rows << kp->row_shift; + + matrix_keypad_build_keymap(keymap_data, kp->row_shift, kp->keycodes, + kp->input_dev->keybit); + + input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN); + + error = input_register_device(kp->input_dev); + if (error < 0) { + dev_err(dev, "Could not register input device\n"); + goto error_reg; + } + + return 0; + + +error_reg: + input_free_device(kp->input_dev); +error_input: + free_irq(kp->irq_release, kp); +error_irq_release: + free_irq(kp->irq_press, kp); +error_irq_press: + clk_put(kp->clk); +error_clk: + iounmap(kp->regs); +error_map: + release_mem_region(kp->res->start, resource_size(kp->res)); +error_res: + platform_set_drvdata(pdev, NULL); + kfree(kp); + return error; +} + +static int __devexit keypad_remove(struct platform_device *pdev) +{ + struct keypad_data *kp = platform_get_drvdata(pdev); + + free_irq(kp->irq_press, kp); + free_irq(kp->irq_release, kp); + input_unregister_device(kp->input_dev); + clk_put(kp->clk); + iounmap(kp->regs); + release_mem_region(kp->res->start, resource_size(kp->res)); + platform_set_drvdata(pdev, NULL); + kfree(kp); + + return 0; +} + +static struct platform_driver keypad_driver = { + .probe = keypad_probe, + .remove = __devexit_p(keypad_remove), + .driver.name = "tnetv107x-keypad", + .driver.owner = THIS_MODULE, +}; + +static int __init keypad_init(void) +{ + return platform_driver_register(&keypad_driver); +} + +static void __exit keypad_exit(void) +{ + platform_driver_unregister(&keypad_driver); +} + +module_init(keypad_init); +module_exit(keypad_exit); + +MODULE_AUTHOR("Cyril Chemparathy"); +MODULE_DESCRIPTION("TNETV107X Keypad Driver"); +MODULE_ALIAS("platform: tnetv107x-keypad"); +MODULE_LICENSE("GPL"); -- 1.7.0.4 From cyril at ti.com Mon Sep 20 11:26:44 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 20 Sep 2010 12:26:44 -0400 Subject: [PATCH v4 5/5] davinci: add tnetv107x touchscreen platform device In-Reply-To: <1285000004-9464-1-git-send-email-cyril@ti.com> References: <1285000004-9464-1-git-send-email-cyril@ti.com> Message-ID: <1285000004-9464-6-git-send-email-cyril@ti.com> This patch adds a platform device definition for tnetv107x's touchscreen controller. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/devices-tnetv107x.c | 20 ++++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c index 086269f..c9a86d8 100644 --- a/arch/arm/mach-davinci/devices-tnetv107x.c +++ b/arch/arm/mach-davinci/devices-tnetv107x.c @@ -31,6 +31,7 @@ #define TNETV107X_TPTC0_BASE 0x01c10000 #define TNETV107X_TPTC1_BASE 0x01c10400 #define TNETV107X_WDOG_BASE 0x08086700 +#define TNETV107X_TSC_BASE 0x08088500 #define TNETV107X_SDIO0_BASE 0x08088700 #define TNETV107X_SDIO1_BASE 0x08088800 #define TNETV107X_KEYPAD_BASE 0x08088a00 @@ -323,12 +324,31 @@ static struct platform_device keypad_device = { .resource = keypad_resources, }; +static struct resource tsc_resources[] = { + { + .start = TNETV107X_TSC_BASE, + .end = TNETV107X_TSC_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_TNETV107X_TSC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device tsc_device = { + .name = "tnetv107x-ts", + .num_resources = ARRAY_SIZE(tsc_resources), + .resource = tsc_resources, +}; + void __init tnetv107x_devices_init(struct tnetv107x_device_info *info) { int i; platform_device_register(&edma_device); platform_device_register(&tnetv107x_wdt_device); + platform_device_register(&tsc_device); if (info->serial_config) davinci_serial_init(info->serial_config); -- 1.7.0.4 From cyril at ti.com Mon Sep 20 11:26:42 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 20 Sep 2010 12:26:42 -0400 Subject: [PATCH v4 3/5] davinci: add keypad config for tnetv107x evm board In-Reply-To: <1285000004-9464-1-git-send-email-cyril@ti.com> References: <1285000004-9464-1-git-send-email-cyril@ti.com> Message-ID: <1285000004-9464-4-git-send-email-cyril@ti.com> This patch adds evm board specific keymap definitions and controller configuration data for on-chip keypad controller on tnetv107x silicon. Signed-off-by: Cyril Chemparathy --- arch/arm/mach-davinci/board-tnetv107x-evm.c | 56 +++++++++++++++++++++++++++ 1 files changed, 56 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c index fe2a9d9..5afa8fc 100644 --- a/arch/arm/mach-davinci/board-tnetv107x-evm.c +++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c @@ -23,6 +23,9 @@ #include #include #include +#include +#include + #include #include @@ -141,10 +144,63 @@ static struct davinci_uart_config serial_config __initconst = { .enabled_uarts = BIT(1), }; +static const uint32_t keymap[] = { + KEY(0, 0, KEY_NUMERIC_1), + KEY(0, 1, KEY_NUMERIC_2), + KEY(0, 2, KEY_NUMERIC_3), + KEY(0, 3, KEY_FN_F1), + KEY(0, 4, KEY_MENU), + + KEY(1, 0, KEY_NUMERIC_4), + KEY(1, 1, KEY_NUMERIC_5), + KEY(1, 2, KEY_NUMERIC_6), + KEY(1, 3, KEY_UP), + KEY(1, 4, KEY_FN_F2), + + KEY(2, 0, KEY_NUMERIC_7), + KEY(2, 1, KEY_NUMERIC_8), + KEY(2, 2, KEY_NUMERIC_9), + KEY(2, 3, KEY_LEFT), + KEY(2, 4, KEY_ENTER), + + KEY(3, 0, KEY_NUMERIC_STAR), + KEY(3, 1, KEY_NUMERIC_0), + KEY(3, 2, KEY_NUMERIC_POUND), + KEY(3, 3, KEY_DOWN), + KEY(3, 4, KEY_RIGHT), + + KEY(4, 0, KEY_FN_F3), + KEY(4, 1, KEY_FN_F4), + KEY(4, 2, KEY_MUTE), + KEY(4, 3, KEY_HOME), + KEY(4, 4, KEY_BACK), + + KEY(5, 0, KEY_VOLUMEDOWN), + KEY(5, 1, KEY_VOLUMEUP), + KEY(5, 2, KEY_F1), + KEY(5, 3, KEY_F2), + KEY(5, 4, KEY_F3), +}; + +static const struct matrix_keymap_data keymap_data = { + .keymap = keymap, + .keymap_size = ARRAY_SIZE(keymap), +}; + +static struct matrix_keypad_platform_data keypad_config = { + .keymap_data = &keymap_data, + .num_row_gpios = 6, + .num_col_gpios = 5, + .debounce_ms = 0, /* minimum */ + .active_low = 0, /* pull up realization */ + .no_autorepeat = 0, +}; + static struct tnetv107x_device_info evm_device_info __initconst = { .serial_config = &serial_config, .mmc_config[1] = &mmc_config, /* controller 1 */ .nand_config[0] = &nand_config, /* chip select 0 */ + .keypad_config = &keypad_config, }; static __init void tnetv107x_evm_board_init(void) -- 1.7.0.4 From cyril at ti.com Mon Sep 20 11:26:43 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 20 Sep 2010 12:26:43 -0400 Subject: [PATCH v4 4/5] input: add driver for tnetv107x touchscreen controller In-Reply-To: <1285000004-9464-1-git-send-email-cyril@ti.com> References: <1285000004-9464-1-git-send-email-cyril@ti.com> Message-ID: <1285000004-9464-5-git-send-email-cyril@ti.com> This patch adds support for tnetv107x's on-chip touchscreen controller. Signed-off-by: Cyril Chemparathy Acked-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 9 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/tnetv107x-ts.c | 396 ++++++++++++++++++++++++++++++ 3 files changed, 406 insertions(+), 0 deletions(-) create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 0069d97..8d32028 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -328,6 +328,15 @@ config TOUCHSCREEN_MIGOR To compile this driver as a module, choose M here: the module will be called migor_ts. +config TOUCHSCREEN_TNETV107X + tristate "TI TNETV107X touchscreen support" + depends on ARCH_DAVINCI_TNETV107X + help + Say Y here if you want to use the TNETV107X touchscreen. + + To compile this driver as a module, choose M here: the + module will be called tnetv107x-ts. + config TOUCHSCREEN_TOUCHRIGHT tristate "Touchright serial touchscreen" select SERIO diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 28217e1..d41a964 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o +obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c new file mode 100644 index 0000000..cf1dba2 --- /dev/null +++ b/drivers/input/touchscreen/tnetv107x-ts.c @@ -0,0 +1,396 @@ +/* + * Texas Instruments TNETV107X Touchscreen Driver + * + * Copyright (C) 2010 Texas Instruments + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define TSC_PENUP_POLL (HZ / 5) +#define IDLE_TIMEOUT 100 /* msec */ + +/* + * The first and last samples of a touch interval are usually garbage and need + * to be filtered out with these devices. The following definitions control + * the number of samples skipped. + */ +#define TSC_HEAD_SKIP 1 +#define TSC_TAIL_SKIP 1 +#define TSC_SKIP (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1) +#define TSC_SAMPLES (TSC_SKIP + 1) + +/* Register Offsets */ +struct tsc_regs { + u32 rev; + u32 tscm; + u32 bwcm; + u32 swc; + u32 adcchnl; + u32 adcdata; + u32 chval[4]; +}; + +/* TSC Mode Configuration Register (tscm) bits */ +#define WMODE BIT(0) +#define TSKIND BIT(1) +#define ZMEASURE_EN BIT(2) +#define IDLE BIT(3) +#define TSC_EN BIT(4) +#define STOP BIT(5) +#define ONE_SHOT BIT(6) +#define SINGLE BIT(7) +#define AVG BIT(8) +#define AVGNUM(x) (((x) & 0x03) << 9) +#define PVSTC(x) (((x) & 0x07) << 11) +#define PON BIT(14) +#define PONBG BIT(15) +#define AFERST BIT(16) + +/* ADC DATA Capture Register bits */ +#define DATA_VALID BIT(16) + +/* Register Access Macros */ +#define tsc_read(ts, reg) __raw_readl(&(ts)->regs->reg) +#define tsc_write(ts, reg, val) __raw_writel(val, &(ts)->regs->reg); +#define tsc_set_bits(ts, reg, val) \ + tsc_write(ts, reg, tsc_read(ts, reg) | (val)) +#define tsc_clr_bits(ts, reg, val) \ + tsc_write(ts, reg, tsc_read(ts, reg) & ~(val)) + +struct sample { + int x, y, p; +}; + +struct tsc_data { + struct input_dev *input_dev; + struct resource *res; + struct tsc_regs __iomem *regs; + struct timer_list timer; + spinlock_t lock; + struct clk *clk; + struct device *dev; + int sample_count; + struct sample samples[TSC_SAMPLES]; + int tsc_irq; +}; + +static int tsc_read_sample(struct tsc_data *ts, struct sample* sample) +{ + int x, y, z1, z2, t, p = 0; + u32 val; + + val = tsc_read(ts, chval[0]); + if (val & DATA_VALID) + x = val & 0xffff; + else + return -EINVAL; + + y = tsc_read(ts, chval[1]) & 0xffff; + z1 = tsc_read(ts, chval[2]) & 0xffff; + z2 = tsc_read(ts, chval[3]) & 0xffff; + + if (z1) { + t = ((600 * x) * (z2 - z1)); + p = t / (u32) (z1 << 12); + if (p < 0) + p = 0; + } + + sample->x = x; + sample->y = y; + sample->p = p; + + return 0; +} + +static void tsc_poll(unsigned long data) +{ + struct tsc_data *ts = (struct tsc_data *)data; + unsigned long flags; + int i, val, x, y, p; + + spin_lock_irqsave(&ts->lock, flags); + + if (ts->sample_count >= TSC_SKIP) { + input_report_abs(ts->input_dev, ABS_PRESSURE, 0); + input_report_key(ts->input_dev, BTN_TOUCH, 0); + input_sync(ts->input_dev); + } else if (ts->sample_count > 0) { + /* + * A touch event lasted less than our skip count. Salvage and + * report anyway. + */ + for (i = 0, val = 0; i < ts->sample_count; i++) + val += ts->samples[i].x; + x = val / ts->sample_count; + + for (i = 0, val = 0; i < ts->sample_count; i++) + val += ts->samples[i].y; + y = val / ts->sample_count; + + for (i = 0, val = 0; i < ts->sample_count; i++) + val += ts->samples[i].p; + p = val / ts->sample_count; + + input_report_abs(ts->input_dev, ABS_X, x); + input_report_abs(ts->input_dev, ABS_Y, y); + input_report_abs(ts->input_dev, ABS_PRESSURE, p); + input_report_key(ts->input_dev, BTN_TOUCH, 1); + input_sync(ts->input_dev); + } + + ts->sample_count = 0; + + spin_unlock_irqrestore(&ts->lock, flags); +} + +static irqreturn_t tsc_irq(int irq, void *dev_id) +{ + struct tsc_data *ts = (struct tsc_data *)dev_id; + struct sample *sample; + int index; + + spin_lock(&ts->lock); + + index = ts->sample_count % TSC_SAMPLES; + sample = &ts->samples[index]; + if (tsc_read_sample(ts, sample) < 0) + goto out; + + if (++ts->sample_count >= TSC_SKIP) { + index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES; + sample = &ts->samples[index]; + + input_report_abs(ts->input_dev, ABS_X, sample->x); + input_report_abs(ts->input_dev, ABS_Y, sample->y); + input_report_abs(ts->input_dev, ABS_PRESSURE, sample->p); + if (ts->sample_count == TSC_SKIP) + input_report_key(ts->input_dev, BTN_TOUCH, 1); + input_sync(ts->input_dev); + } + mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL); +out: + spin_unlock(&ts->lock); + return IRQ_HANDLED; +} + +static int tsc_start(struct input_dev *dev) +{ + struct tsc_data *ts = input_get_drvdata(dev); + unsigned long timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT); + u32 val; + + clk_enable(ts->clk); + + /* Go to idle mode, before any initialization */ + while (time_after(timeout, jiffies)) { + if (tsc_read(ts, tscm) & IDLE) + break; + } + + if (time_before(timeout, jiffies)) { + dev_warn(ts->dev, "timeout waiting for idle\n"); + clk_disable(ts->clk); + return -EIO; + } + + /* Configure TSC Control register*/ + val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN); + tsc_write(ts, tscm, val); + + /* Bring TSC out of reset: Clear AFE reset bit */ + val &= ~(AFERST); + tsc_write(ts, tscm, val); + + /* Configure all pins for hardware control*/ + tsc_write(ts, bwcm, 0); + + /* Finally enable the TSC */ + tsc_set_bits(ts, tscm, TSC_EN); + + return 0; +} + +static void tsc_stop(struct input_dev *dev) +{ + struct tsc_data *ts = input_get_drvdata(dev); + + tsc_clr_bits(ts, tscm, TSC_EN); + synchronize_irq(ts->tsc_irq); + del_timer_sync(&ts->timer); + clk_disable(ts->clk); +} + +static int __devinit tsc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tsc_data *ts; + int error = 0; + u32 rev = 0; + + ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL); + if (!ts) { + dev_err(dev, "cannot allocate device info\n"); + return -ENOMEM; + } + + ts->dev = dev; + spin_lock_init(&ts->lock); + setup_timer(&ts->timer, tsc_poll, (unsigned long)ts); + platform_set_drvdata(pdev, ts); + + ts->tsc_irq = platform_get_irq(pdev, 0); + if (ts->tsc_irq < 0) { + dev_err(dev, "cannot determine device interrupt\n"); + error = -ENODEV; + goto error_res; + } + + ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!ts->res) { + dev_err(dev, "cannot determine register area\n"); + error = -ENODEV; + goto error_res; + } + + if (!request_mem_region(ts->res->start, resource_size(ts->res), + pdev->name)) { + dev_err(dev, "cannot claim register memory\n"); + ts->res = NULL; + error = -EINVAL; + goto error_res; + } + + ts->regs = ioremap(ts->res->start, resource_size(ts->res)); + if (!ts->regs) { + dev_err(dev, "cannot map register memory\n"); + error = -ENOMEM; + goto error_map; + } + + ts->clk = clk_get(dev, NULL); + if (!ts->clk) { + dev_err(dev, "cannot claim device clock\n"); + error = -EINVAL; + goto error_clk; + } + + error = request_threaded_irq(ts->tsc_irq, NULL, tsc_irq, 0, + dev_name(dev), ts); + if (error < 0) { + dev_err(ts->dev, "Could not allocate ts irq\n"); + goto error_irq; + } + + ts->input_dev = input_allocate_device(); + if (!ts->input_dev) { + dev_err(dev, "cannot allocate input device\n"); + error = -ENOMEM; + goto error_input; + } + input_set_drvdata(ts->input_dev, ts); + + ts->input_dev->name = pdev->name; + ts->input_dev->id.bustype = BUS_HOST; + ts->input_dev->dev.parent = &pdev->dev; + ts->input_dev->open = tsc_start; + ts->input_dev->close = tsc_stop; + + clk_enable(ts->clk); + rev = tsc_read(ts, rev); + ts->input_dev->id.product = ((rev >> 8) & 0x07); + ts->input_dev->id.version = ((rev >> 16) & 0xfff); + clk_disable(ts->clk); + + __set_bit(EV_KEY, ts->input_dev->evbit); + __set_bit(EV_ABS, ts->input_dev->evbit); + __set_bit(BTN_TOUCH, ts->input_dev->keybit); + + input_set_abs_params(ts->input_dev, ABS_X, 0, 0xffff, 5, 0); + input_set_abs_params(ts->input_dev, ABS_Y, 0, 0xffff, 5, 0); + input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0); + + error = input_register_device(ts->input_dev); + if (error < 0) { + dev_err(dev, "failed input device registration\n"); + goto error_reg; + } + + return 0; + +error_reg: + input_free_device(ts->input_dev); +error_input: + free_irq(ts->tsc_irq, ts); +error_irq: + clk_put(ts->clk); +error_clk: + iounmap(ts->regs); +error_map: + release_mem_region(ts->res->start, resource_size(ts->res)); +error_res: + platform_set_drvdata(pdev, NULL); + kfree(ts); + + return error; +} + +static int __devexit tsc_remove(struct platform_device *pdev) +{ + struct tsc_data *ts = platform_get_drvdata(pdev); + + input_unregister_device(ts->input_dev); + free_irq(ts->tsc_irq, ts); + clk_put(ts->clk); + iounmap(ts->regs); + release_mem_region(ts->res->start, resource_size(ts->res)); + platform_set_drvdata(pdev, NULL); + kfree(ts); + + return 0; +} + +static struct platform_driver tsc_driver = { + .probe = tsc_probe, + .remove = __devexit_p(tsc_remove), + .driver.name = "tnetv107x-ts", + .driver.owner = THIS_MODULE, +}; + +static int __init tsc_init(void) +{ + return platform_driver_register(&tsc_driver); +} + +static void __exit tsc_exit(void) +{ + platform_driver_unregister(&tsc_driver); +} + +module_init(tsc_init); +module_exit(tsc_exit); + +MODULE_AUTHOR("Cyril Chemparathy"); +MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); +MODULE_ALIAS("platform: tnetv107x-ts"); +MODULE_LICENSE("GPL"); -- 1.7.0.4 From khasim at ti.com Mon Sep 20 12:35:19 2010 From: khasim at ti.com (Syed Mohammed, Khasim) Date: Mon, 20 Sep 2010 23:05:19 +0530 Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <1283975491-5984-1-git-send-email-vm.rod25@gmail.com> References: <1283975491-5984-1-git-send-email-vm.rod25@gmail.com> Message-ID: <0680EC522D0CC943BC586913CF3768C003C21EDFC3@dbde02.ent.ti.com> Any update on the patch? Regards, Khasim > -----Original Message----- > From: davinci-linux-open-source-bounces at linux.davincidsp.com [mailto:davinci- > linux-open-source-bounces at linux.davincidsp.com] On Behalf Of Victor Rodriguez > Sent: Thursday, September 09, 2010 1:22 AM > To: davinci-linux-open-source at linux.davincidsp.com > Subject: [PATCH v5] davinci: Initial support for Omapl138-Hawkboard > > This patch adds initial support for the Hawkboard-L138 system > It is under the machine name "omapl138_hawkboard". > This system is based on the da850 davinci CPU architecture. > Information on these system may be found at http://www.hawkboard.org. > Basic support for the UART console is included in this patch. > > Signed-off-by: Victor Rodriguez > --- > Changes since v4: > 1) Disable UART1 because it produces spurious interrupts > 2) Add Watch dog timer function > > Notes: > > This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 > from Kernel development tree for TI DaVinci family of processors. > This patch works with da8xx_omapl_defconfig plus this patch. > Depends on Michael Williamson patches: > http://alturl.com/hha7u and http://alturl.com/qy4cr > > arch/arm/configs/da8xx_omapl_defconfig | 1 + > arch/arm/mach-davinci/Kconfig | 8 +++ > arch/arm/mach-davinci/Makefile | 1 + > arch/arm/mach-davinci/board-da850-hawk.c | 72 > +++++++++++++++++++++++ > arch/arm/mach-davinci/include/mach/uncompress.h | 1 + > 5 files changed, 83 insertions(+), 0 deletions(-) > create mode 100644 arch/arm/mach-davinci/board-da850-hawk.c > > diff --git a/arch/arm/configs/da8xx_omapl_defconfig > b/arch/arm/configs/da8xx_omapl_defconfig > index 3952a4e..d7cb4b8 100644 > --- a/arch/arm/configs/da8xx_omapl_defconfig > +++ b/arch/arm/configs/da8xx_omapl_defconfig > @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y > CONFIG_ARCH_DAVINCI=y > CONFIG_ARCH_DAVINCI_DA830=y > CONFIG_ARCH_DAVINCI_DA850=y > +CONFIG_MACH_OMAPL138_HAWKBOARD=y > CONFIG_DAVINCI_RESET_CLOCKS=y > CONFIG_NO_HZ=y > CONFIG_HIGH_RES_TIMERS=y > diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig > index 2bf03e9..5e5d8a3 100644 > --- a/arch/arm/mach-davinci/Kconfig > +++ b/arch/arm/mach-davinci/Kconfig > @@ -185,6 +185,14 @@ config MACH_TNETV107X > help > Say Y here to select the TI TNETV107X Evaluation Module. > > +config MACH_OMAPL138_HAWKBOARD > + bool "TI AM1808 / OMAPL-138 Hawkboard platform" > + depends on ARCH_DAVINCI_DA850 > + help > + Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard platform . > + Information of this board may be found at > + http://www.hawkboard.org/ > + > config DAVINCI_MUX > bool "DAVINCI multiplexing support" > depends on ARCH_DAVINCI > diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile > index 77a0f71..484071d 100644 > --- a/arch/arm/mach-davinci/Makefile > +++ b/arch/arm/mach-davinci/Makefile > @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365- > evm.o > obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o > obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o > obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o > +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-da850-hawk.o > > # Power Management > obj-$(CONFIG_CPU_FREQ) += cpufreq.o > diff --git a/arch/arm/mach-davinci/board-da850-hawk.c b/arch/arm/mach- > davinci/board-da850-hawk.c > new file mode 100644 > index 0000000..c4596b1 > --- /dev/null > +++ b/arch/arm/mach-davinci/board-da850-hawk.c > @@ -0,0 +1,72 @@ > +/* > + * Hawkboard.org based on TI's OMAP-L138 Platform > + * > + * Initial code: Syed Mohammed Khasim > + * > + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 > +#include > +#include > +#include > + > +#include > +#include > + > +#include > +#include > + > +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { > + .enabled_uarts = 0x7, > +}; > + > +static __init void omapl138_hawk_init(void) > +{ > + int ret; > + > + davinci_serial_init(&omapl138_hawk_uart_config); > + > + /* > + * Shut down UART 1; It shares pins with > + * McASP0 transmit/receive master clock, > + * and it's imposible to access by expancion conector > + * Enable it will produce spurious interrupts > + */ > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > + > + ret = da8xx_register_watchdog(); > + if (ret) > + pr_warning("omapl138_hawk_init: " > + "watchdog registration failed: %d\n", > + ret); > +} > + > +#ifdef CONFIG_SERIAL_8250_CONSOLE > +static int __init omapl138_hawk_console_init(void) > +{ > + if (!machine_is_omapl138_hawkboard()) > + return 0; > + > + return add_preferred_console("ttyS", 2, "115200"); > +} > +console_initcall(omapl138_hawk_console_init); > +#endif > + > +static void __init omapl138_hawk_map_io(void) > +{ > + da850_init(); > +} > + > +MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") > + .phys_io = IO_PHYS, > + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, > + .boot_params = (DA8XX_DDR_BASE + 0x100), > + .map_io = omapl138_hawk_map_io, > + .init_irq = cp_intc_init, > + .timer = &davinci_timer, > + .init_machine = omapl138_hawk_init, > +MACHINE_END > diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach- > davinci/include/mach/uncompress.h > index 15a6192..640f834 100644 > --- a/arch/arm/mach-davinci/include/mach/uncompress.h > +++ b/arch/arm/mach-davinci/include/mach/uncompress.h > @@ -88,6 +88,7 @@ static inline void __arch_decomp_setup(unsigned long > arch_id) > /* DA8xx boards */ > DEBUG_LL_DA8XX(davinci_da830_evm, 2); > DEBUG_LL_DA8XX(davinci_da850_evm, 2); > + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); > > /* TNETV107x boards */ > DEBUG_LL_TNETV107X(tnetv107x, 1); > -- > 1.6.0.5 > > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source at linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source From michael.williamson at criticallink.com Mon Sep 20 12:42:53 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Mon, 20 Sep 2010 13:42:53 -0400 Subject: [PATCH v5 1/1] davinci: spi: replace existing driver In-Reply-To: References: <1280355490-11878-1-git-send-email-bniebuhr@efjohnson.com> <4C8EB795.1080607@criticallink.com> <201009140904.59555.caglarakyuz@gmail.com> <4C8F7460.6050006@criticallink.com> <4C94B9BD.4010606@criticallink.com> Message-ID: <4C979D1D.1070707@criticallink.com> On 9/20/2010 11:08 AM, Nori, Sekhar wrote: > Hi Michael, > > On Sat, Sep 18, 2010 at 18:38:13, Michael Williamson wrote: >> >> * I'm not sure I understand why there is a "intr_line" field in the platform >> data and then a possibility to configure an "io_type" as interrupt or polled at >> the chip select level. I got burned by setting the "io_type" to SPI_IO_TYPE_INTR >> and not setting "intr_line" to non-zero. The probe just hung because it was >> trying to use interrupts but never setting SPILVL register. These fields aren't >> mutually exclusive. Is the intent to support a configuration with one chip select >> running in polled mode and another in interrupt mode? If so, then it seems the SPILVL >> register logic needs some attention during each transfer. > > The intr_line to be set is constant for the SoC. So, irrespective of what the > individual devices on a given board choose to operate (interrupted, polled or DMA) > the SoC code (da850.c) should setup the intr_line according to how the SPI interrupt > is wired within the SoC. Can you clarify what you mean by "needs some attention during > each transfer"? > Ah... OK. Thank you. I now see that the SPILVL can be INT0 or INT1 for other davinci SoCs like the DM644x. For the da850 (OMAP-L138), SPILVL is valid only for INT1. So pretty much, if your using a da850 (at least), intr_line has to be 1. On other platforms, it carries a lot more meaning... Please ignore my ignorance... Let me know if you want testing on the DMA portion of the patch (when your ready, of course). -Mike From khilman at deeprootsystems.com Mon Sep 20 14:35:10 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Mon, 20 Sep 2010 12:35:10 -0700 Subject: [PATCH v4 0/5] add tnetv107x input drivers In-Reply-To: <1285000004-9464-1-git-send-email-cyril@ti.com> (Cyril Chemparathy's message of "Mon, 20 Sep 2010 12:26:39 -0400") References: <1285000004-9464-1-git-send-email-cyril@ti.com> Message-ID: <874odkw6mp.fsf@deeprootsystems.com> Cyril Chemparathy writes: > Texas Instruments' TNETV107X is an ARM1176 based SoC, with on-chip > touchscreen and keypad controllers. This patch series adds drivers for these > controllers. > > Changes between v1 and v2: > 1. Cleaned up platform data needs by reusing matrix keypad pdata > 2. Eliminated calibration code from touch driver > 3. Relocated h/w init code to open and close > 4. Other minor cleanups > > Changes between v2 and v3: > 1. Merged keycodes alloc into keypad data > 2. Moved irq hookup to probe from open > 3. Other minor cleanups > > Changes between v3 and v4: > 1. Locking between hardirqs for keypad driver > > Cyril Chemparathy (5): > input: add driver for tnetv107x on-chip keypad controller > davinci: add tnetv107x keypad platform device > davinci: add keypad config for tnetv107x evm board > input: add driver for tnetv107x touchscreen controller > davinci: add tnetv107x touchscreen platform device Thanks, queuing this series for 2.6.37 in davinci-next. Kevin > arch/arm/mach-davinci/board-tnetv107x-evm.c | 56 ++++ > arch/arm/mach-davinci/devices-tnetv107x.c | 50 +++ > arch/arm/mach-davinci/include/mach/tnetv107x.h | 3 + > drivers/input/keyboard/Kconfig | 9 + > drivers/input/keyboard/Makefile | 1 + > drivers/input/keyboard/tnetv107x-keypad.c | 340 ++++++++++++++++++++ > drivers/input/touchscreen/Kconfig | 9 + > drivers/input/touchscreen/Makefile | 1 + > drivers/input/touchscreen/tnetv107x-ts.c | 396 ++++++++++++++++++++++++ > 9 files changed, 865 insertions(+), 0 deletions(-) > create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c > create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c From khilman at deeprootsystems.com Mon Sep 20 14:43:01 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Mon, 20 Sep 2010 12:43:01 -0700 Subject: [PATCH v6] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <1284045675-4025-1-git-send-email-vm.rod25@gmail.com> (Victor Rodriguez's message of "Thu, 9 Sep 2010 10:21:15 -0500") References: <1284045675-4025-1-git-send-email-vm.rod25@gmail.com> Message-ID: <87vd60urp6.fsf@deeprootsystems.com> Victor Rodriguez writes: > This patch adds initial support for the Hawkboard-L138 system > It is under the machine name "omapl138_hawkboard". > This system is based on the da850 davinci CPU architecture. > Information on these system may be found at http://www.hawkboard.org. > Basic support for the UART console is included in this patch. > > Signed-off-by: Victor Rodriguez Applying and queuing for 2.6.37 in davinci-next. Kevin > --- > Changes since v5: > 1) Change name of board file > 2) Typos > > Notes: > > This patch is checked with 0a50e05b20f3c6af67656303bdb3661a2541ce03 > from Kernel development tree for TI DaVinci family of processors. > This patch works with da8xx_omapl_defconfig plus this patch. > Depends on Michael Williamson patches: > http://alturl.com/hha7u and http://alturl.com/qy4cr > > arch/arm/configs/da8xx_omapl_defconfig | 1 + > arch/arm/mach-davinci/Kconfig | 8 +++ > arch/arm/mach-davinci/Makefile | 1 + > arch/arm/mach-davinci/board-omapl138-hawk.c | 72 +++++++++++++++++++++++ > arch/arm/mach-davinci/include/mach/uncompress.h | 1 + > 5 files changed, 83 insertions(+), 0 deletions(-) > create mode 100644 arch/arm/mach-davinci/board-omapl138-hawk.c > > diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig > index 3952a4e..d7cb4b8 100644 > --- a/arch/arm/configs/da8xx_omapl_defconfig > +++ b/arch/arm/configs/da8xx_omapl_defconfig > @@ -17,6 +17,7 @@ CONFIG_MODVERSIONS=y > CONFIG_ARCH_DAVINCI=y > CONFIG_ARCH_DAVINCI_DA830=y > CONFIG_ARCH_DAVINCI_DA850=y > +CONFIG_MACH_OMAPL138_HAWKBOARD=y > CONFIG_DAVINCI_RESET_CLOCKS=y > CONFIG_NO_HZ=y > CONFIG_HIGH_RES_TIMERS=y > diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig > index 2bf03e9..5e5d8a3 100644 > --- a/arch/arm/mach-davinci/Kconfig > +++ b/arch/arm/mach-davinci/Kconfig > @@ -185,6 +185,14 @@ config MACH_TNETV107X > help > Say Y here to select the TI TNETV107X Evaluation Module. > > +config MACH_OMAPL138_HAWKBOARD > + bool "TI AM1808 / OMAPL-138 Hawkboard platform" > + depends on ARCH_DAVINCI_DA850 > + help > + Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard platform . > + Information of this board may be found at > + http://www.hawkboard.org/ > + > config DAVINCI_MUX > bool "DAVINCI multiplexing support" > depends on ARCH_DAVINCI > diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile > index 77a0f71..fc123b4 100644 > --- a/arch/arm/mach-davinci/Makefile > +++ b/arch/arm/mach-davinci/Makefile > @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o > obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o > obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o > obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o > +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o > > # Power Management > obj-$(CONFIG_CPU_FREQ) += cpufreq.o > diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c > new file mode 100644 > index 0000000..d1f08aa > --- /dev/null > +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c > @@ -0,0 +1,72 @@ > +/* > + * Hawkboard.org based on TI's OMAP-L138 Platform > + * > + * Initial code: Syed Mohammed Khasim > + * > + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 > +#include > +#include > +#include > + > +#include > +#include > + > +#include > +#include > + > +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { > + .enabled_uarts = 0x7, > +}; > + > +static __init void omapl138_hawk_init(void) > +{ > + int ret; > + > + davinci_serial_init(&omapl138_hawk_uart_config); > + > + /* > + * Shut down UART 1; It shares pins with > + * McASP0 transmit/receive master clock, > + * and impossible to access by expansion connector > + * Enable it will produce spurious interrupts > + */ > + __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); > + > + ret = da8xx_register_watchdog(); > + if (ret) > + pr_warning("omapl138_hawk_init: " > + "watchdog registration failed: %d\n", > + ret); > +} > + > +#ifdef CONFIG_SERIAL_8250_CONSOLE > +static int __init omapl138_hawk_console_init(void) > +{ > + if (!machine_is_omapl138_hawkboard()) > + return 0; > + > + return add_preferred_console("ttyS", 2, "115200"); > +} > +console_initcall(omapl138_hawk_console_init); > +#endif > + > +static void __init omapl138_hawk_map_io(void) > +{ > + da850_init(); > +} > + > +MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") > + .phys_io = IO_PHYS, > + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, > + .boot_params = (DA8XX_DDR_BASE + 0x100), > + .map_io = omapl138_hawk_map_io, > + .init_irq = cp_intc_init, > + .timer = &davinci_timer, > + .init_machine = omapl138_hawk_init, > +MACHINE_END > diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h > index 15a6192..640f834 100644 > --- a/arch/arm/mach-davinci/include/mach/uncompress.h > +++ b/arch/arm/mach-davinci/include/mach/uncompress.h > @@ -88,6 +88,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) > /* DA8xx boards */ > DEBUG_LL_DA8XX(davinci_da830_evm, 2); > DEBUG_LL_DA8XX(davinci_da850_evm, 2); > + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); > > /* TNETV107x boards */ > DEBUG_LL_TNETV107X(tnetv107x, 1); From khilman at deeprootsystems.com Mon Sep 20 14:44:50 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Mon, 20 Sep 2010 12:44:50 -0700 Subject: [PATCH v3] davinci: MityDSP-L138/MityARM-1808 read MAC address from I2C Prom In-Reply-To: <1284731766-2751-1-git-send-email-michael.williamson@criticallink.com> (Michael Williamson's message of "Fri, 17 Sep 2010 09:56:06 -0400") References: <1284731766-2751-1-git-send-email-michael.williamson@criticallink.com> Message-ID: <87k4mgurm5.fsf@deeprootsystems.com> Michael Williamson writes: > For the MityDSP-L138/MityARM-1808 SOMS, read the factory assigned > MAC address from the onboard I2C EPROM and assign it to the emac > device during platform initialization. > > Signed-off-by: Michael Williamson > --- > Patch is against e90c3a5344683351c7a37f097f1e17d50ee2063c of linux-davinci > tree. > > Changes since v2: > 1) removed 8 bytes of &'s and [0]'s from &foo[0]'s per comments Thanks. Applying and queuing for 2.6.37 in davinci-next. Kevin From khilman at deeprootsystems.com Mon Sep 20 14:52:51 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Mon, 20 Sep 2010 12:52:51 -0700 Subject: [PATCH v5 1/4] davinci: Add generic PWM support for PWM control In-Reply-To: <1284968386-16898-1-git-send-email-sugumar@ti.com> (Sugumar Natarajan's message of "Mon, 20 Sep 2010 13:09:46 +0530") References: <1284968386-16898-1-git-send-email-sugumar@ti.com> Message-ID: <8762y0ur8s.fsf@deeprootsystems.com> Sugumar Natarajan writes: > This patch adds generic PWM support where it maintains the > list of PWM control devices that can be added or removed. > > The interface provides a list of functions that can be accessed > by the PWM control driver module and the generic PWM driver. > > The PWM control driver module such as eCAP uses the interface to > register and add itself to the list as a PWM control device. > The generic PWM driver uses the interface to search for a PWM control > device and if present, uses the device for PWM control. > > Signed-off-by: Sugumar Natarajan > --- > Changes since v4: > a) pwm_enable and pwm_disable function implementation have been modified, > such that the actual implementation is done by the corresponding driver, > and these functions would just make a callback. Would it make sense for the core to directly manage the clocks if the driver has not provided its own enable/disable hooks? I guess that would slightly simplify simple users. Now that I say that, I noticed the eCAP driver no longer touches the clocks in its own enable/disable hooks. Why? Kevin > arch/arm/mach-davinci/Makefile | 3 + > arch/arm/mach-davinci/davinci_pwm.c | 135 ++++++++++++++++++++++ > arch/arm/mach-davinci/include/mach/davinci_pwm.h | 34 ++++++ > 3 files changed, 172 insertions(+), 0 deletions(-) > create mode 100644 arch/arm/mach-davinci/davinci_pwm.c > create mode 100644 arch/arm/mach-davinci/include/mach/davinci_pwm.h > > diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile > index a7a70d1..90ca821 100644 > --- a/arch/arm/mach-davinci/Makefile > +++ b/arch/arm/mach-davinci/Makefile > @@ -39,3 +39,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o > obj-$(CONFIG_CPU_FREQ) += cpufreq.o > obj-$(CONFIG_CPU_IDLE) += cpuidle.o > obj-$(CONFIG_SUSPEND) += pm.o sleep.o > + > +# Generic PWM control support > +obj-$(CONFIG_HAVE_PWM) += davinci_pwm.o > diff --git a/arch/arm/mach-davinci/davinci_pwm.c b/arch/arm/mach-davinci/davinci_pwm.c > new file mode 100644 > index 0000000..8f3e8ad > --- /dev/null > +++ b/arch/arm/mach-davinci/davinci_pwm.c > @@ -0,0 +1,135 @@ > +/* > + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed .as is. WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) > +{ > + unsigned int clock_freq; > + unsigned int period_cycles; > + unsigned int duty_cycle; > + int ret = 0; > + > + if (WARN_ON(!pwm)) > + return -EINVAL; > + > + if (pwm->pwm_config_device) { > + if (!period_ns || duty_ns > period_ns) > + return -EINVAL; > + > + clock_freq = clk_get_rate(pwm->clk) / USEC_PER_SEC; > + period_cycles = (clock_freq * period_ns) / MSEC_PER_SEC; > + duty_cycle = (clock_freq * duty_ns) / MSEC_PER_SEC; > + > + ret = pwm->pwm_config_device(pwm, period_cycles, duty_cycle); > + } > + > + return ret; > +} > +EXPORT_SYMBOL(pwm_config); > + > +int pwm_enable(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return -EINVAL; > + > + if (pwm->pwm_enable) > + return pwm->pwm_enable(pwm); > + > + return 0; > +} > +EXPORT_SYMBOL(pwm_enable); > + > +void pwm_disable(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return; > + > + if (pwm->pwm_disable) > + pwm->pwm_disable(pwm); > +} > +EXPORT_SYMBOL(pwm_disable); > + > +static DEFINE_MUTEX(pwm_lock); > +static LIST_HEAD(pwm_list); > + > +struct pwm_device *pwm_request(int pwm_id, const char *label) > +{ > + struct pwm_device *pwm, *tmp_pwm = ERR_PTR(-ENOENT); > + > + mutex_lock(&pwm_lock); > + > + list_for_each_entry(pwm, &pwm_list, node) { > + if (pwm->pwm_id == pwm_id) { > + if (pwm->use_count == 0) { > + pwm->use_count++; > + pwm->label = label; > + } else { > + pwm = ERR_PTR(-EBUSY); > + } > + tmp_pwm = pwm; > + break; > + } > + } > + > + mutex_unlock(&pwm_lock); > + return tmp_pwm; > +} > +EXPORT_SYMBOL(pwm_request); > + > +void pwm_free(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return; > + > + mutex_lock(&pwm_lock); > + > + if (pwm->use_count) { > + pwm->use_count--; > + pwm->label = NULL; > + } else { > + dev_warn(&pwm->pdev->dev, "PWM device already freed\n"); > + } > + > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(pwm_free); > + > +void pwm_add(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return; > + > + mutex_lock(&pwm_lock); > + list_add_tail(&pwm->node, &pwm_list); > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(pwm_add); > + > +void pwm_remove(struct pwm_device *pwm) > +{ > + if (WARN_ON(!pwm)) > + return; > + > + mutex_lock(&pwm_lock); > + list_del(&pwm->node); > + mutex_unlock(&pwm_lock); > +} > +EXPORT_SYMBOL(pwm_remove); > diff --git a/arch/arm/mach-davinci/include/mach/davinci_pwm.h b/arch/arm/mach-davinci/include/mach/davinci_pwm.h > new file mode 100644 > index 0000000..5762881 > --- /dev/null > +++ b/arch/arm/mach-davinci/include/mach/davinci_pwm.h > @@ -0,0 +1,34 @@ > +/* > + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed .as is. WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + */ > + > +#ifndef __DAVINCI_PWM_H > +#define __DAVINCI_PWM_H > + > +struct pwm_device { > + struct list_head node; > + struct platform_device *pdev; > + int (*pwm_enable)(struct pwm_device *pwm); > + void (*pwm_disable)(struct pwm_device *pwm); > + int (*pwm_config_device)(struct pwm_device *pwm, > + unsigned int period, unsigned int dutycycle); > + const char *label; > + struct clk *clk; > + unsigned int use_count; > + unsigned int pwm_id; > +}; > + > +void pwm_add(struct pwm_device *pwm); > +void pwm_remove(struct pwm_device *pwm); > + > +#endif From troy.kisky at boundarydevices.com Mon Sep 20 16:14:49 2010 From: troy.kisky at boundarydevices.com (Troy Kisky) Date: Mon, 20 Sep 2010 14:14:49 -0700 Subject: [PATCH v3] i2c: davinci: Fix race when setting up for TX In-Reply-To: <70E876B0EA86DD4BAF101844BC814DFE093ED5F50E@Cloud.RL.local> References: <70E876B0EA86DD4BAF101844BC814DFE093ED5F50E@Cloud.RL.local> Message-ID: <4C97CEC9.8060602@boundarydevices.com> >> On 9/17/2010 6:09 AM, Sudhakar Rajashekhara wrote: >>> I remember I had some issues on OMAP-L138 with this fix, that's when >>> I reverted to configuring ICMDR before writing to DXR (Please see >>> here: https://patchwork.kernel.org/patch/75262/). I checked the BIOS >>> I2C driver code for OMAP-L138 and there also we are configuring MDR >>> before accessing DXR. > > Ah :/ > >> >> and resetting the i2c upon a NAK interrupt (after the stop) >> to clear the bad fifo data? > > I can't really comment on how valid that would be and can't easily test it. > > However preloading DXR does save one interrupt on transmit so the whole operation is faster and more efficient. > > Maybe v1 of my patch, with locking, is the best option? > > -- > Jon Povey How about writing MDR twice? Once where Sudakar wants it, without the start bit. And then where you want it with the start bit? Troy From jon.povey at racelogic.co.uk Mon Sep 20 23:13:28 2010 From: jon.povey at racelogic.co.uk (Jon Povey) Date: Tue, 21 Sep 2010 13:13:28 +0900 Subject: [PATCH v4] i2c: davinci: Fix race when setting up for TX In-Reply-To: <4C97CEC9.8060602@boundarydevices.com> References: <4C97CEC9.8060602@boundarydevices.com> Message-ID: <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> When setting up to transmit, a race exists between the ISR and i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. This is mostly visible for transmits > 1 byte long. The hardware starts sending immediately that MDR.STT is set. IMR trickery doesn't work because if we start sending, finish the first byte and an XRDY event occurs before we load IMR to unmask it, we never get an interrupt, and we timeout. Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode settings before DXR for correct behaviour, so load MDR first with STT cleared and later load again with STT set. Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 Signed-off-by: Jon Povey CC: Sudhakar Rajashekhara CC: Troy Kisky --- Reworked after comments by Troy and Sudhakar. Looking at the datasheet it seemed like setting STP without STT early might cause a stray STOP to be generated, so I moved it into the second MDR load. This passes a quick smoke test but I can't do much more testing right at the moment. Sudhakar, your comments would be welcomed. drivers/i2c/busses/i2c-davinci.c | 24 +++++++++++++++--------- 1 files changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 2222c87..5795c83 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -331,21 +331,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) INIT_COMPLETION(dev->cmd_complete); dev->cmd_err = 0; - /* Take I2C out of reset, configure it as master and set the - * start bit */ - flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT; + /* Take I2C out of reset and configure it as master */ + flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST; /* if the slave address is ten bit address, enable XA bit */ if (msg->flags & I2C_M_TEN) flag |= DAVINCI_I2C_MDR_XA; if (!(msg->flags & I2C_M_RD)) flag |= DAVINCI_I2C_MDR_TRX; - if (stop) - flag |= DAVINCI_I2C_MDR_STP; - if (msg->len == 0) { + if (msg->len == 0) flag |= DAVINCI_I2C_MDR_RM; - flag &= ~DAVINCI_I2C_MDR_STP; - } /* Enable receive or transmit interrupts */ w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); @@ -357,7 +352,11 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) dev->terminate = 0; - /* write the data into mode register */ + /* + * Write mode register first as needed for correct behaviour + * on OMAP-L138, but don't set STT yet to avoid a race with XRDY + * occuring before we have loaded DXR + */ davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); /* @@ -365,12 +364,19 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) * because transmit-data-ready interrupt can come before * NACK-interrupt during sending of previous message and * ICDXR may have wrong data + * It also saves us one interrupt, slightly faster */ if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); dev->buf_len--; } + /* Set STT to begin transmit now DXR is loaded */ + flag |= DAVINCI_I2C_MDR_STT; + if (stop && msg->len != 0) + flag |= DAVINCI_I2C_MDR_STP; + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); + r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, dev->adapter.timeout); if (r == 0) { -- 1.6.3.3 From gongzy_sjz at yahoo.cn Tue Sep 21 00:29:48 2010 From: gongzy_sjz at yahoo.cn (=?utf-8?B?6Ieq55Sx5Lq6?=) Date: Mon, 20 Sep 2010 22:29:48 -0700 (PDT) Subject: how to start dsp program from ubl? Message-ID: <606998.26302.qm@web92408.mail.cnh.yahoo.com> ? hello ,my custom 6467 board's ubl boot right.not using linux,not using dsplink,how can i start my dsp program from ubl??can someone??give me some advise?thank you very much -------------- next part -------------- An HTML attachment was scrubbed... URL: From sugumar at ti.com Tue Sep 21 02:55:04 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Tue, 21 Sep 2010 13:25:04 +0530 Subject: [PATCH 2/2] davinci: Add platform specific support for eHRPWM driver In-Reply-To: <4C971EA3.4080402@mvista.com> References: <1284968715-17272-1-git-send-email-sugumar@ti.com> <4C971EA3.4080402@mvista.com> Message-ID: <016001cb5962$56138ce0$023aa6a0$@com> Sergei, On Mon, Sep 20, 2010 at 14:13:15, Sergei Shtylyov wrote: > Hello. > > On 20-09-2010 11:45, Sugumar Natarajan wrote: > > > This patch registers the eHRPWM module as a platform device and also > > configures the pin for PWM output > [...] > > diff --git a/arch/arm/mach-davinci/da850.c > > b/arch/arm/mach-davinci/da850.c index 7bc51f1..ab1758e 100644 > > --- a/arch/arm/mach-davinci/da850.c > > +++ b/arch/arm/mach-davinci/da850.c > [...] > > +static struct platform_device da850_ehrpwm_dev = { > > + .name = "ehrpwm", > > + .id = 1, > > Why not -1? Isn't this the only device? All the modules that support pwm are considered here to be as PWM devices. So, each of the pwm device (Including every instance) is assigned a unique ID. These IDs are added to the list of available PWM devices. So, drivers such as motor control driver or backlight driver can use any of the drivers in the list. The 'pwm id' is passed in the platform data of the motor control/backlight driver to specify the actual pwm driver to be used. Regards, N.sugumar From sugumar at ti.com Tue Sep 21 06:02:45 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Tue, 21 Sep 2010 16:32:45 +0530 Subject: [PATCH v5 1/4] davinci: Add generic PWM support for PWM control In-Reply-To: <8762y0ur8s.fsf@deeprootsystems.com> References: <1284968386-16898-1-git-send-email-sugumar@ti.com> <8762y0ur8s.fsf@deeprootsystems.com> Message-ID: <016a01cb597c$8ee462a0$acad27e0$@com> Kevin, On Tue, Sep 21, 2010 at 01:22:51, Kevin Hilman wrote: > Sugumar Natarajan writes: > > > This patch adds generic PWM support where it maintains the list of PWM > > control devices that can be added or removed. > > > > The interface provides a list of functions that can be accessed by the > > PWM control driver module and the generic PWM driver. > > > > The PWM control driver module such as eCAP uses the interface to > > register and add itself to the list as a PWM control device. > > The generic PWM driver uses the interface to search for a PWM control > > device and if present, uses the device for PWM control. > > > > Signed-off-by: Sugumar Natarajan > > --- > > Changes since v4: > > a) pwm_enable and pwm_disable function implementation have been modified, > > such that the actual implementation is done by the corresponding driver, > > and these functions would just make a callback. > > Would it make sense for the core to directly manage the clocks if the driver has not provided its own enable/disable hooks? I guess that would slightly simplify simple users. Of course yes. But, the driver code would undergo few changes if the clk_enable/clk_disable function is implemented. Please see below > > Now that I say that, I noticed the eCAP driver no longer touches the clocks in its own enable/disable hooks. Why? Clock enable/disable function implementation requires few changes in the driver code. Clock_enable function has to be called every time before writing into the registers. This is needed as pwm_config function could be called with the clock disabled. This condition arises when the backlight driver receives 0% duty cycle. At this time, the backlight driver calls the pwm_disable function. Since the clock is disabled now, if the pwm_config fuction is called again, no read/write access would actually happen. I have implemented the enable/disable function in the previous patch. This had resulted in inclusion of clk_enable and clk_disable function. I had to also incorporate an extra random delay for the ecap driver to function properly. To avoid this delay, clk_enable/clk_disable function implementation has been removed. In the present implementation, clk_enable and clk_disable function are called only during probe and remove respectively. Please see the code snippet below. >From davinci_pwm.c int pwm_enable(struct pwm_device *pwm) { int rc = 0; if (WARN_ON(!pwm)) return -EINVAL; if (!pwm->clk_enabled) { rc = clk_enable(pwm->clk); if (!rc) pwm->clk_enabled = 1; } return rc; } >From ecap.c, static int ecap_pwm_config(struct pwm_device *pwm, unsigned int period_cycles, + unsigned int duty_cycle) { clk_enable(pwm->clock); __raw_writew(); mdelay(10); clk_disable(pwm->clock); } AFAIK, pwm_enable / pwm_disable function are used to start / stop the pwm output and relies heavily on the driver capabilities. Why should the clk_enable and clk_disable be called if the driver does not support the above feature? Why can't it simply return instead? Regards, N.Sugumar > > Kevin From sudhakar.raj at ti.com Tue Sep 21 06:24:17 2010 From: sudhakar.raj at ti.com (Sudhakar Rajashekhara) Date: Tue, 21 Sep 2010 16:54:17 +0530 Subject: [PATCH v4] i2c: davinci: Fix race when setting up for TX In-Reply-To: <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> References: <4C97CEC9.8060602@boundarydevices.com> <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> Message-ID: <026901cb597f$86fa9980$94efcc80$@raj@ti.com> Hi, On Tue, Sep 21, 2010 at 09:43:28, Jon Povey wrote: > When setting up to transmit, a race exists between the ISR and > i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. > This is mostly visible for transmits > 1 byte long. > > The hardware starts sending immediately that MDR.STT is set. IMR trickery > doesn't work because if we start sending, finish the first byte and an > XRDY event occurs before we load IMR to unmask it, we never get an > interrupt, and we timeout. > > Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode > settings before DXR for correct behaviour, so load MDR first with > STT cleared and later load again with STT set. > > Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 > > Signed-off-by: Jon Povey > CC: Sudhakar Rajashekhara > CC: Troy Kisky > --- > Reworked after comments by Troy and Sudhakar. > > Looking at the datasheet it seemed like setting STP without STT early > might cause a stray STOP to be generated, so I moved it into the second > MDR load. > > This passes a quick smoke test but I can't do much more testing right at > the moment. Sudhakar, your comments would be welcomed. > Looks good to me. I can test on couple of platforms I have and update the result by tomorrow. Thanks, Sudhakar From khilman at deeprootsystems.com Tue Sep 21 09:31:32 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Tue, 21 Sep 2010 07:31:32 -0700 Subject: [PATCH v5 1/4] davinci: Add generic PWM support for PWM control In-Reply-To: <016a01cb597c$8ee462a0$acad27e0$@com> (Sugumar Natarajan's message of "Tue, 21 Sep 2010 16:32:45 +0530") References: <1284968386-16898-1-git-send-email-sugumar@ti.com> <8762y0ur8s.fsf@deeprootsystems.com> <016a01cb597c$8ee462a0$acad27e0$@com> Message-ID: <87vd5zp3qz.fsf@deeprootsystems.com> "Sugumar Natarajan" writes: > Kevin, > > On Tue, Sep 21, 2010 at 01:22:51, Kevin Hilman wrote: >> Sugumar Natarajan writes: >> >> > This patch adds generic PWM support where it maintains the list of PWM >> > control devices that can be added or removed. >> > >> > The interface provides a list of functions that can be accessed by the >> > PWM control driver module and the generic PWM driver. >> > >> > The PWM control driver module such as eCAP uses the interface to >> > register and add itself to the list as a PWM control device. >> > The generic PWM driver uses the interface to search for a PWM control >> > device and if present, uses the device for PWM control. >> > >> > Signed-off-by: Sugumar Natarajan >> > --- >> > Changes since v4: >> > a) pwm_enable and pwm_disable function implementation have been modified, >> > such that the actual implementation is done by the corresponding driver, >> > and these functions would just make a callback. >> >> Would it make sense for the core to directly manage the clocks if the driver has not provided its own enable/disable hooks? I > guess that would slightly simplify simple users. > > Of course yes. But, the driver code would undergo few changes if > the clk_enable/clk_disable function is implemented. Please see below > > >> >> Now that I say that, I noticed the eCAP driver no longer touches the clocks in its own enable/disable hooks. Why? > Clock enable/disable function implementation requires few changes > in the driver code. Clock_enable function has to be called every > time before writing into the registers. This is needed as pwm_config > function could be called with the clock disabled. This > condition arises when the backlight driver receives 0% duty cycle. > At this time, the backlight driver calls the pwm_disable function. > Since the clock is disabled now, if the pwm_config fuction is called > again, no read/write access would actually happen. > > I have implemented the enable/disable function in the previous > patch. This had resulted in inclusion of clk_enable and clk_disable > function. I had to also incorporate an extra random delay for the > ecap driver to function properly. To avoid this delay, clk_enable/clk_disable > function implementation has been removed. In the present implementation, > clk_enable and clk_disable function are called only during probe > and remove respectively. > Please see the code snippet below. > > From davinci_pwm.c > > int pwm_enable(struct pwm_device *pwm) { > int rc = 0; > if (WARN_ON(!pwm)) > return -EINVAL; > if (!pwm->clk_enabled) { > rc = clk_enable(pwm->clk); > if (!rc) > pwm->clk_enabled = 1; > } > return rc; > } > > From ecap.c, > > static int ecap_pwm_config(struct pwm_device *pwm, unsigned int period_cycles, > + unsigned int duty_cycle) > { > clk_enable(pwm->clock); > > __raw_writew(); > > mdelay(10); > > clk_disable(pwm->clock); > > } > > AFAIK, pwm_enable / pwm_disable function are used to start / stop > the pwm output and relies heavily on the driver capabilities. > > Why should the clk_enable and clk_disable be called if the driver > does not support the above feature? Why can't it simply return instead? The problem is a power-management problem. A module should only be clocked when needed. Currently, you clock the module on problem and disable clocks on remove. The result is the that the module is clocked, even if there are no PWM users. If the clock is needed only for register writes, then that's all it should be enabled for. The need for such a long delay needs to be investigated and clearly described in the changelog. Is the delay needed between the clock enable and writing to the module? or is it needed between a module access and a clock disable. Either way, I expect there is way to handle this in SW without needed a delay. Kevin From khilman at deeprootsystems.com Tue Sep 21 09:33:56 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Tue, 21 Sep 2010 07:33:56 -0700 Subject: [PATCH v6] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <87vd60urp6.fsf@deeprootsystems.com> (Kevin Hilman's message of "Mon, 20 Sep 2010 12:43:01 -0700") References: <1284045675-4025-1-git-send-email-vm.rod25@gmail.com> <87vd60urp6.fsf@deeprootsystems.com> Message-ID: <87k4mfp3mz.fsf@deeprootsystems.com> Kevin Hilman writes: > Victor Rodriguez writes: > >> This patch adds initial support for the Hawkboard-L138 system >> It is under the machine name "omapl138_hawkboard". >> This system is based on the da850 davinci CPU architecture. >> Information on these system may be found at http://www.hawkboard.org. >> Basic support for the UART console is included in this patch. >> >> Signed-off-by: Victor Rodriguez > > Applying and queuing for 2.6.37 in davinci-next. > On 2nd thought, I'm not ready to merge this. I'd like to see resolution of need for that UART hack and a better description in the changelog and the code, both for the EVM and for Hawkboard. Kevin From vm.rod25 at gmail.com Tue Sep 21 09:38:52 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Tue, 21 Sep 2010 09:38:52 -0500 Subject: [PATCH v6] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <87k4mfp3mz.fsf@deeprootsystems.com> References: <1284045675-4025-1-git-send-email-vm.rod25@gmail.com> <87vd60urp6.fsf@deeprootsystems.com> <87k4mfp3mz.fsf@deeprootsystems.com> Message-ID: On Tue, Sep 21, 2010 at 9:33 AM, Kevin Hilman wrote: > Kevin Hilman writes: > >> Victor Rodriguez writes: >> >>> This patch adds initial support for the Hawkboard-L138 system >>> It is under the machine name "omapl138_hawkboard". >>> This system is based on the da850 davinci CPU architecture. >>> Information on these system may be found at http://www.hawkboard.org. >>> Basic support for the UART console is included in this patch. >>> >>> Signed-off-by: Victor Rodriguez >> >> Applying and queuing for 2.6.37 in davinci-next. >> > > On 2nd thought, I'm not ready to merge this. ?I'd like to see resolution > of need for that UART hack and a better description in the changelog and > the code, both for the EVM and for Hawkboard. > > Kevin > OK Kevin just one question the resolution should be for hawkboard and evm in order to merge into mainline hawk board. I am able to work with hawk board but not with EVM. Would be fine if I just give you the resolution for hawkboard and not for EVM? Thanks Victor Rodriguez From khilman at deeprootsystems.com Tue Sep 21 09:44:16 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Tue, 21 Sep 2010 07:44:16 -0700 Subject: [PATCH v6] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: (Victor Rodriguez's message of "Tue, 21 Sep 2010 09:38:52 -0500") References: <1284045675-4025-1-git-send-email-vm.rod25@gmail.com> <87vd60urp6.fsf@deeprootsystems.com> <87k4mfp3mz.fsf@deeprootsystems.com> Message-ID: <87bp7rnolb.fsf@deeprootsystems.com> Victor Rodriguez writes: > On Tue, Sep 21, 2010 at 9:33 AM, Kevin Hilman > wrote: >> Kevin Hilman writes: >> >>> Victor Rodriguez writes: >>> >>>> This patch adds initial support for the Hawkboard-L138 system >>>> It is under the machine name "omapl138_hawkboard". >>>> This system is based on the da850 davinci CPU architecture. >>>> Information on these system may be found at http://www.hawkboard.org. >>>> Basic support for the UART console is included in this patch. >>>> >>>> Signed-off-by: Victor Rodriguez >>> >>> Applying and queuing for 2.6.37 in davinci-next. >>> >> >> On 2nd thought, I'm not ready to merge this. ?I'd like to see resolution >> of need for that UART hack and a better description in the changelog and >> the code, both for the EVM and for Hawkboard. >> >> Kevin >> > OK Kevin just one question the resolution should be for hawkboard and > evm in order to merge into mainline hawk board. I am able to work with > hawk board but not with EVM. Would be fine if I just give you the > resolution for hawkboard and not for EVM? I suggest you continue to work with Sekhar. He can validate on the EVM and sign-off on the EVM changes. Kevin From deepali at ti.com Tue Sep 21 11:43:19 2010 From: deepali at ti.com (Uppal, Deepali) Date: Tue, 21 Sep 2010 22:13:19 +0530 Subject: how to start dsp program from ubl? In-Reply-To: <606998.26302.qm@web92408.mail.cnh.yahoo.com> References: <606998.26302.qm@web92408.mail.cnh.yahoo.com> Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B031610E17D@dbde02.ent.ti.com> DSPLink expects the Linux kernel to be booted and available. To use any DSPLink API?s the DSPLink kernel module needs to be ?insmod?-ed. You will have to write custom code to boot load the DSP from your ubl. Deepali ________________________________ From: davinci-linux-open-source-bounces at linux.davincidsp.com [mailto:davinci-linux-open-source-bounces at linux.davincidsp.com] On Behalf Of ??? Sent: Tuesday, September 21, 2010 11:00 AM To: davinci-linux-open-source at linux.davincidsp.com Subject: how to start dsp program from ubl? hello ,my custom 6467 board's ubl boot right.not using linux,not using dsplink,how can i start my dsp program from ubl? can someone give me some advise?thank you very much -------------- next part -------------- An HTML attachment was scrubbed... URL: From troy.kisky at boundarydevices.com Tue Sep 21 14:17:58 2010 From: troy.kisky at boundarydevices.com (Troy Kisky) Date: Tue, 21 Sep 2010 12:17:58 -0700 Subject: [PATCH v4] i2c: davinci: Fix race when setting up for TX In-Reply-To: <026901cb597f$86fa9980$94efcc80$@raj@ti.com> References: <4C97CEC9.8060602@boundarydevices.com> <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> <026901cb597f$86fa9980$94efcc80$@raj@ti.com> Message-ID: <4C9904E6.7070608@boundarydevices.com> On 9/21/2010 4:24 AM, Sudhakar Rajashekhara wrote: > Hi, > > On Tue, Sep 21, 2010 at 09:43:28, Jon Povey wrote: >> When setting up to transmit, a race exists between the ISR and >> i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. >> This is mostly visible for transmits > 1 byte long. >> >> The hardware starts sending immediately that MDR.STT is set. IMR trickery >> doesn't work because if we start sending, finish the first byte and an >> XRDY event occurs before we load IMR to unmask it, we never get an >> interrupt, and we timeout. >> >> Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode >> settings before DXR for correct behaviour, so load MDR first with >> STT cleared and later load again with STT set. >> >> Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 >> >> Signed-off-by: Jon Povey >> CC: Sudhakar Rajashekhara >> CC: Troy Kisky >> --- >> Reworked after comments by Troy and Sudhakar. >> >> Looking at the datasheet it seemed like setting STP without STT early >> might cause a stray STOP to be generated, so I moved it into the second >> MDR load. >> >> This passes a quick smoke test but I can't do much more testing right at >> the moment. Sudhakar, your comments would be welcomed. >> > > Looks good to me. I can test on couple of platforms I have and update the result > by tomorrow. > > Thanks, > Sudhakar > > > I like it too. I hope it works for omap. Thanks as well Troy From sudhakar.raj at ti.com Wed Sep 22 05:50:16 2010 From: sudhakar.raj at ti.com (Sudhakar Rajashekhara) Date: Wed, 22 Sep 2010 16:20:16 +0530 Subject: [PATCH v4] i2c: davinci: Fix race when setting up for TX In-Reply-To: <20100922000916.GH7494@trinity.fluff.org> References: <4C97CEC9.8060602@boundarydevices.com> <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> <4C9904E6.7070608@boundarydevices.com> <20100922000916.GH7494@trinity.fluff.org> Message-ID: <005701cb5a43$f1f9f4f0$d5edded0$@raj@ti.com> Hi, On Wed, Sep 22, 2010 at 05:39:16, Ben Dooks wrote: > On Tue, Sep 21, 2010 at 12:17:58PM -0700, Troy Kisky wrote: > > On 9/21/2010 4:24 AM, Sudhakar Rajashekhara wrote: > > > Hi, > > > > > > On Tue, Sep 21, 2010 at 09:43:28, Jon Povey wrote: > > >> When setting up to transmit, a race exists between the ISR and > > >> i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. > > >> This is mostly visible for transmits > 1 byte long. > > >> > > >> The hardware starts sending immediately that MDR.STT is set. IMR trickery > > >> doesn't work because if we start sending, finish the first byte and an > > >> XRDY event occurs before we load IMR to unmask it, we never get an > > >> interrupt, and we timeout. > > >> > > >> Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode > > >> settings before DXR for correct behaviour, so load MDR first with > > >> STT cleared and later load again with STT set. > > >> > > >> Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 > > >> > > >> Signed-off-by: Jon Povey > > >> CC: Sudhakar Rajashekhara > > >> CC: Troy Kisky > > >> --- > > >> Reworked after comments by Troy and Sudhakar. > > >> > > >> Looking at the datasheet it seemed like setting STP without STT early > > >> might cause a stray STOP to be generated, so I moved it into the second > > >> MDR load. > > >> > > >> This passes a quick smoke test but I can't do much more testing right at > > >> the moment. Sudhakar, your comments would be welcomed. > > >> > > > > > > Looks good to me. I can test on couple of platforms I have and update the result > > > by tomorrow. > > > > > > Thanks, > > > Sudhakar > > > > > > > > > > > I like it too. I hope it works for omap. > > > > Thanks as well > > Troy > > Ok, any objections to this being applied, or should I wait? > I am stuck in some other work. If you can wait till I test it, that'll be good. Thanks, Sudhakar From hebert.marcandre at gmail.com Wed Sep 22 10:22:55 2010 From: hebert.marcandre at gmail.com (=?ISO-8859-1?Q?Marc=2DAndr=E9_H=E9bert?=) Date: Wed, 22 Sep 2010 11:22:55 -0400 Subject: USB0 problem on OMAPL138 Message-ID: Hi, I've been having a problem with my USB0 on my omapl138 board. I've got both USB0 and USB1 setup as host. I can use USB mass storage sticks in both of them without any problems (did plenty of copying and checksums are ok). But I am trying to use USB Wi-Fi cards but so far they only work correctly when using USB1. So far I tested 2 different models the D-Link DWA160A2 (AR9170) and the Linksys WUSB600N V2 (RT3572USB). I got each of them working with the full speed USB1, but the driver either crashes or stalls when using the hi speed USB0. The debug traces are listed further below for reference. I have tried the D-Link with a hawkboard I have here and I had the similar behavior. Unfortunately I don't have a EVM board anymore to test it on. Now I am trying to determine if this is a hardware issue, a software issue with the USB0 host controller driver or something else. I am using the arago staging kernel. One thing I would like to do would be to limit the USB0 to high speed to see if there is an impact but I haven't had the time yet to look into it. I was wondering if anyone had any ideas. Thanks Marc D-Link DWA160A2 usb 1-1: no command feedback received (-110). Backtrace: [] (dump_backtrace+0x0/0x114) from [] (dump_stack+0x18/0x1c) r7:c1c0ca4c r6:ffffff92 r5:c1c0c8a0 r4:c1e36f00 [] (dump_stack+0x0/0x1c) from [] (ar9170_usb_exec_cmd+0x1d0/0x264) [] (ar9170_usb_exec_cmd+0x0/0x264) from [] (ar9170_set_qos+0x190/0x22c) [] (ar9170_set_qos+0x0/0x22c) from [] (ar9170_conf_tx+0x58/0x70) [] (ar9170_conf_tx+0x0/0x70) from [] (ieee80211_set_wmm_default+0x144/0x15c) r7:0000000e r6:00000000 r5:c1c0c1e0 r4:00000000 [] (ieee80211_set_wmm_default+0x0/0x15c) from [] (ieee80211_set_disassoc+0x124/0x230) r6:c1c0c1e0 r5:c1e12ae0 r4:00000000 [] (ieee80211_set_disassoc+0x0/0x230) from [] (ieee80211_sta_work+0x9c4/0x13c8) r7:c1e12de0 r6:c1e12d84 r5:c1e62000 r4:c1e63eb8 [] (ieee80211_sta_work+0x0/0x13c8) from [] (worker_thread+0x194/0x25c) [] (worker_thread+0x0/0x25c) from [] (kthread+0x88/0x90) [] (kthread+0x0/0x90) from [] (do_exit+0x0/0x6b4) r7:00000000 r6:00000000 r5:00000000 r4:00000000 Linksys WUSB600N V2 (These messages come from the ralink driver) BulkIn IRP Pending!!! BulkIn IRP Pending!!! BulkIn IRP Pending!!! BIRIdx(0): RXDMALen not multiple of 4.[16566], BulkInBufLen = 8364) BulkIn IRP Pending!!! BIRIdx(3): RXDMALen not multiple of 4.[2049], BulkInBufLen = 6912) BulkIn IRP Pending!!! ... From hebert.marcandre at gmail.com Wed Sep 22 13:52:00 2010 From: hebert.marcandre at gmail.com (=?ISO-8859-1?Q?Marc=2DAndr=E9_H=E9bert?=) Date: Wed, 22 Sep 2010 14:52:00 -0400 Subject: USB0 problem on OMAPL138 In-Reply-To: References: Message-ID: 2010/9/22 Marc-Andr? H?bert : > Hi, > > I've been having a problem with my USB0 on my omapl138 board. I've got > both USB0 and USB1 setup as host. I can use USB mass storage sticks in > both of them without any problems (did plenty of copying and checksums > are ok). But I am trying to use USB Wi-Fi cards but so far they only > work correctly when using USB1. > > So far I tested 2 different models the D-Link DWA160A2 (AR9170) and > the Linksys WUSB600N V2 (RT3572USB). I got each of them working with > the full speed USB1, but the driver either crashes or stalls when > using the hi speed USB0. The debug traces are listed further below for > reference. I have tried the D-Link with a hawkboard I have here and I > had the similar behavior. Unfortunately I don't have a EVM board > anymore to test it on. > > Now I am trying to determine if this is a hardware issue, a software > issue with the USB0 host controller driver or something else. I am > using the arago staging kernel. One thing I would like to do would be > to limit the USB0 to high speed to see if there is an impact but I > haven't had the time yet to look into it. > > I was wondering if anyone had any ideas. > Thanks > Marc > > D-Link DWA160A2 > usb 1-1: no command feedback received (-110). > Backtrace: > [] (dump_backtrace+0x0/0x114) from [] (dump_stack+0x18/0x1c) > r7:c1c0ca4c r6:ffffff92 r5:c1c0c8a0 r4:c1e36f00 > [] (dump_stack+0x0/0x1c) from [] > (ar9170_usb_exec_cmd+0x1d0/0x264) > [] (ar9170_usb_exec_cmd+0x0/0x264) from [] > (ar9170_set_qos+0x190/0x22c) > [] (ar9170_set_qos+0x0/0x22c) from [] > (ar9170_conf_tx+0x58/0x70) > [] (ar9170_conf_tx+0x0/0x70) from [] > (ieee80211_set_wmm_default+0x144/0x15c) > ?r7:0000000e r6:00000000 r5:c1c0c1e0 r4:00000000 > ?[] (ieee80211_set_wmm_default+0x0/0x15c) from [] > (ieee80211_set_disassoc+0x124/0x230) > ?r6:c1c0c1e0 r5:c1e12ae0 r4:00000000 > ?[] (ieee80211_set_disassoc+0x0/0x230) from [] > (ieee80211_sta_work+0x9c4/0x13c8) > ?r7:c1e12de0 r6:c1e12d84 r5:c1e62000 r4:c1e63eb8 > ?[] (ieee80211_sta_work+0x0/0x13c8) from [] > (worker_thread+0x194/0x25c) > ?[] (worker_thread+0x0/0x25c) from [] (kthread+0x88/0x90) > ?[] (kthread+0x0/0x90) from [] (do_exit+0x0/0x6b4) > ?r7:00000000 r6:00000000 r5:00000000 r4:00000000 > > Linksys WUSB600N V2 (These messages come from the ralink driver) > BulkIn IRP Pending!!! > BulkIn IRP Pending!!! > BulkIn IRP Pending!!! > BIRIdx(0): RXDMALen not multiple of 4.[16566], BulkInBufLen = 8364) > BulkIn IRP Pending!!! > BIRIdx(3): RXDMALen not multiple of 4.[2049], BulkInBufLen = 6912) > BulkIn IRP Pending!!! > ... > If I disable DMA for the USB0 musb controller using the CONFIG_MUSB_PIO_ONLY option then the WUSB600N card works correctly. Marc From Jon.Povey at racelogic.co.uk Wed Sep 22 22:49:28 2010 From: Jon.Povey at racelogic.co.uk (Jon Povey) Date: Thu, 23 Sep 2010 04:49:28 +0100 Subject: New WARN from dm9000 since merge to 2.6.36-rc4 Message-ID: <70E876B0EA86DD4BAF101844BC814DFE093ED5FAA5@Cloud.RL.local> I have been working based on 2.6.34 for a while, tried merging from 2.6.36-rc4 to look at some possible USB improvements, and get a new warning on boot. This is on DM355, not the EVM, but uses the same ethernet design, in the same way. As far as I can tell the board and config are the same. Given that this looks like something to do with dm9000, I tried reverting the suspicious 380fefb2d "dm9000: fix "BUG: spinlock recursion"" but that made no difference. Any clues welcome, here's the console output with some uninteresting stuff snipped. Linux version 2.6.36-rc4+ (jon at eroko) (gcc version 4.3.3 (Sourcery G++ Lite 2009q1-203) ) #33 PREEMPT Wed Sep 22 19:26:45 JST 2010 CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177 CPU: VIVT data cache, VIVT instruction cache Machine: Racelogic Video VBOX (SDPRO4) Memory policy: ECC disabled, Data cache writeback DaVinci dm355 variant 0x0 On node 0 totalpages: 32768 free_area_init_node: node 0, pgdat c038105c, node_mem_map c03ab000 DMA zone: 256 pages used for memmap DMA zone: 0 pages reserved DMA zone: 32512 pages, LIFO batch:7 Built 1 zonelists in Zone order, mobility grouping on. Total pages: 32512 Kernel command line: console=ttyS0,115200n8 rw ip=dhcp root=/dev/nfs nfsroot=192.168.1.140:/home/jon/vidbox-gitkernel/dvnfs,nolock loglevel=8 PID hash table entries: 512 (order: -1, 2048 bytes) Dentry cache hash table entries: 16384 (order: 4, 65536 bytes) Inode-cache hash table entries: 8192 (order: 3, 32768 bytes) Memory: 128MB = 128MB total Memory: 126196k/126196k available, 4876k reserved, 0K highmem Virtual kernel memory layout: vector : 0xffff0000 - 0xffff1000 ( 4 kB) fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB) DMA : 0xff000000 - 0xffe00000 ( 14 MB) vmalloc : 0xc8800000 - 0xfea00000 ( 866 MB) lowmem : 0xc0000000 - 0xc8000000 ( 128 MB) modules : 0xbf000000 - 0xc0000000 ( 16 MB) .init : 0xc0008000 - 0xc0026000 ( 120 kB) .text : 0xc0026000 - 0xc0361000 (3308 kB) .data : 0xc0362000 - 0xc0381960 ( 127 kB) SLUB: Genslabs=11, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 Hierarchical RCU implementation. RCU-based detection of stalled CPUs is disabled. Verbose stalled-CPUs detection is disabled. NR_IRQS:245 Calibrating delay loop... 134.34 BogoMIPS (lpj=671744) pid_max: default: 32768 minimum: 301 Mount-cache hash table entries: 512 CPU: Testing write buffer coherency: ok devtmpfs: initialized DaVinci: 104 gpio irqs ... Switching to clocksource timer0_1 NET: Registered protocol family 2 IP route cache hash table entries: 1024 (order: 0, 4096 bytes) TCP established hash table entries: 4096 (order: 3, 32768 bytes) TCP bind hash table entries: 4096 (order: 2, 16384 bytes) TCP: Hash tables configured (established 4096 bind 4096) TCP reno registered UDP hash table entries: 256 (order: 0, 4096 bytes) UDP-Lite hash table entries: 256 (order: 0, 4096 bytes) NET: Registered protocol family 1 RPC: Registered udp transport module. RPC: Registered tcp transport module. RPC: Registered tcp NFSv4.1 backchannel transport module. msgmni has been set to 246 ... dm9000 Ethernet Driver, V1.31 eth0: dm9000a at c8838000,c883c002 IRQ 65 MAC: 00:50:c2:68:00:10 (chip) console [netcon0] enabled netconsole: network logging started ... TCP cubic registered NET: Registered protocol family 17 rtc-m41t80 1-0068: setting system clock to 2010-09-23 02:40:56 UTC (1285209656) eth0: link down eth0: link up, 100Mbps, full-duplex, lpa 0x45E1 Sending DHCP requests . ------------[ cut here ]------------ WARNING: at kernel/softirq.c:143 local_bh_enable+0x4c/0xc8() Modules linked in: Backtrace: [] (dump_backtrace+0x0/0x114) from [] (dump_stack+0x18/0x1c) r7:00000000 r6:c0040aec r5:c0319fef r4:0000008f [] (dump_stack+0x0/0x1c) from [] (warn_slowpath_common+0x54/0x6c) [] (warn_slowpath_common+0x0/0x6c) from [] (warn_slowpath_null+0x24/0x2c) r9:00000015 r8:00000015 r7:0000015a r6:c6ffc240 r5:c786b3a0 r4:c0386860 [] (warn_slowpath_null+0x0/0x2c) from [] (local_bh_enable+0x4c/0xc8) [] (local_bh_enable+0x0/0xc8) from [] (netif_rx+0xb0/0x21c) r5:c786b3a0 r4:00000000 [] (netif_rx+0x0/0x21c) from [] (dm9000_interrupt+0x1d4/0x334) r6:c786b000 r5:c786b3a0 r4:c6ffc240 [] (dm9000_interrupt+0x0/0x334) from [] (handle_IRQ_event+0x2c/0xfc) [] (handle_IRQ_event+0x0/0xfc) from [] (handle_simple_irq+0x94/0xf4) r7:00000042 r6:00000041 r5:c036d728 r4:c7ad70c0 [] (handle_simple_irq+0x0/0xf4) from [] (gpio_irq_handler+0xc0/0xf0) r7:00000042 r6:00000002 r5:00000041 r4:00000002 [] (gpio_irq_handler+0x0/0xf0) from [] (asm_do_IRQ+0x7c/0xa0) [] (asm_do_IRQ+0x0/0xa0) from [] (__irq_svc+0x4c/0x90) Exception stack(0xc0363f48 to 0xc0363f90) 3f40: 00000000 0005317f 0005217f 60000013 c0362000 c0381a60 3f60: c002301c c0366840 80020ce8 41069265 80020cb4 c0363f9c 600000d3 c0363f90 3f80: c0027a4c c0027a58 60000013 ffffffff r5:fec48000 r4:ffffffff [] (default_idle+0x0/0x38) from [] (cpu_idle+0x78/0xe4) [] (cpu_idle+0x0/0xe4) from [] (rest_init+0xa8/0xc0) r5:c0381a60 r4:00000002 [] (rest_init+0x0/0xc0) from [] (start_kernel+0x270/0x2c4) r5:c0381a60 r4:c0396584 [] (start_kernel+0x0/0x2c4) from [<80008034>] (0x80008034) r5:c0381b04 r4:00053175 ---[ end trace af4a93804142fc65 ]--- , OK IP-Config: Got DHCP answer from 192.168.1.1, my address is 192.168.1.142 IP-Config: Complete: device=eth0, addr=192.168.1.142, mask=255.255.255.0, gw=192.168.1.1, host=192.168.1.142, domain=, nis-domain=(none), bootserver=192.168.1.1, rootserver=192.168.1.140, rootpath= Looking up port of RPC 100003/2 on 192.168.1.140 Looking up port of RPC 100005/1 on 192.168.1.140 VFS: Mounted root (nfs filesystem) on device 0:14. -- Jon Povey jon.povey at racelogic.co.uk Racelogic is a limited company registered in England. Registered number 2743719 . Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB . The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network From siva.prasad at freesystems.biz Thu Sep 23 00:25:03 2010 From: siva.prasad at freesystems.biz (siva prasad T) Date: Thu, 23 Sep 2010 10:55:03 +0530 Subject: porting android on dm6467 Message-ID: <4C9AE4AF.2010807@freesystems.biz> hi, i am working on TMS320DM6467 processor of DM6467EVM, my intention is to port android kernel on dm6467evm, so for that i had downloaded the android kernel source code from the following link "http://software-dl.ti.com/dsps/dsps_public_sw/sdo_tii/TI_Android_DevKit/01_00_00/index_FDS.html" i am able to configure for dm6467 and compiled an uImage. but i did not find any corresponding android root file system to mount the above kernel through nfs. so please provide me link to get the related rfs to download (or) suggest me any process to make appropriate root file system to mount the above kernel.it will be a great help if any one provide solution regarding this...... Thanks & Regards Siva From siva.prasad at freesystems.biz Thu Sep 23 00:30:47 2010 From: siva.prasad at freesystems.biz (siva prasad T) Date: Thu, 23 Sep 2010 11:00:47 +0530 Subject: support for dm6467 framebuffer Message-ID: <4C9AE607.50306@freesystems.biz> hi, i am working on TMS320DM6467 processor of DM6467EVM and after booting my linux kernel which has been taken from arego project i am not able to observe frame buffer nodes in /dev folder... so please sugest me how to get frame buffer nodes enabled. Thanks & Regards Siva From khasim at ti.com Thu Sep 23 03:38:11 2010 From: khasim at ti.com (Syed Mohammed, Khasim) Date: Thu, 23 Sep 2010 14:08:11 +0530 Subject: porting android on dm6467 In-Reply-To: <4C9AE4AF.2010807@freesystems.biz> References: <4C9AE4AF.2010807@freesystems.biz> Message-ID: <0680EC522D0CC943BC586913CF3768C003C21EE797@dbde02.ent.ti.com> Hi Siva prasad, We don't support Android on DM6467, the release you are referring to below is for OMAP35x, AM35x, AM37x platforms only. Regards, Khasim > -----Original Message----- > From: davinci-linux-open-source-bounces at linux.davincidsp.com [mailto:davinci- > linux-open-source-bounces at linux.davincidsp.com] On Behalf Of siva prasad T > Sent: Thursday, September 23, 2010 10:55 AM > To: davinci-linux-open-source at linux.davincidsp.com > Subject: porting android on dm6467 > > hi, > > i am working on TMS320DM6467 processor of DM6467EVM, my intention > is to port android kernel on dm6467evm, > so for that i had downloaded the android kernel source code from > the following link > "http://software- > dl.ti.com/dsps/dsps_public_sw/sdo_tii/TI_Android_DevKit/01_00_00/index_FDS.htm > l" > i am able to configure for dm6467 and compiled an uImage. but i did > not find any corresponding android root file system to mount the above > kernel through nfs. so please provide me link to get the > related rfs to download (or) suggest me any process to make appropriate > root file system to mount the above kernel.it will be a great > help if any one provide solution regarding this...... > > Thanks & Regards > Siva > > > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source at linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source From Jon.Povey at racelogic.co.uk Thu Sep 23 06:35:11 2010 From: Jon.Povey at racelogic.co.uk (Jon Povey) Date: Thu, 23 Sep 2010 12:35:11 +0100 Subject: musb: repeatable CPPI DMA hang bug on peripheral RX 64 byte packet Message-ID: <70E876B0EA86DD4BAF101844BC814DFE093ED5FB9C@Cloud.RL.local> On DM355 with CPPI DMA enabled, operating as gadget serial, the USB driver RX side locks up when sent a 64-byte line of text. Up to and above 64 bytes are OK, exactly 64 bytes wedges it. I see the 64-byte line come out of "cat /dev/ttyGS0", but then nothing after. The TX side still works OK, but if the other end tries to send any more, it times out. If it helps at all, a few times when testing this I have seen extra 1-byte transfers appear at the g_serial layer rather than wedging when a 64-byte packet was sent. I haven't been able to reproduce this reliably. But that is to say I was seeing: Send 64 bytes, g_serial layer gets 64-byte transfer followed by a 1-byte transfer containing garbage: always the first character of some previous line received. Send any other line size e.g. 63 bytes, g_serial layer gets a single 63-byte transfer. Disabling DMA fixes the problem, but I'd like to have DMA if possible, and help fix this. I observed this problem in a 2.6.34 based kernel, I am now running the master of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci.git with local board support etc. patches applied, and tried applying the 12 musb fix patches at the top of http://gitorious.org/usb/usb/commits/musb which did not help. loading musb_hdrc with debug=7 shows up some suspicious differences when receiving a 64-byte line, some console logs below. I note that bits 0x3 of csr are set in the problem case. 63-byte RX (ok): cppi_interrupt 1172: CPPI IRQ Tx0 Rx1 cppi_dump_rx 377: RX DMA0/K: 0 left, csr 2000, 00000000 H00000000 S873388c0 C873388c0, B86ec6c3f L003f01c1 0000003f .. 873388c0 cppi_rx_scan 1045: C/RXBD 873388c0: nxt 00000000 buf 86ec6c00 off.len 0000003f opt.len d000003f (0) cppi_dump_rx 377: RX DMA0/completed: 0 left, csr 2000, 00000000 H00000000 S873388c0 C873388c0, B86ec6c3f L003f01c1 0000003f .. 873388c0 musb_g_rx 757: <== ep1out, rxcsr 2000 (dma) c6e92dc0 musb_g_rx 800: RXCSR1 0000, dma off, 0000, len 63, req c6e92dc0 musb_g_giveback 143: ep1out done request c6e92dc0, 63/512 gs_read_complete: req c6e92dc0 cppi_next_rx_segment 831: RX DMA0 seg, maxp 512 onepacket bds 1 (cnt 0) dma 0x86854000 len 512 0/512 RXBD/S 873388a0: nxt 00000000 buf 86854000 off.blen 00000200 opt.plen e0000200 cppi_dump_rx 377: RX DMA0/S: 3 left, csr 0000, 00000000 H873388a0 S873388c0 C873388c0, B86ec6c3f L003f01c1 0000003f .. 873388c0 davinci_interrupt 292: IRQ 00000000 ttyGS 63 bytes to tty (s S . ... 0x39 0x0a) musb_gadget_queue 1120: <== to ep1out request=c6e92dc0 musb_gadget_queue 1120: <== to ep1in request=c6e927c0 musb_ep_restart 1088: <== TX/IN request c6e927c0 len 1 on hw_ep1 txstate 298: hw_ep1, maxpacket 512, fifo count 1, txcsr 2404 cppi_next_tx_segment 604: TX DMA0, pktSz 512 transparent bds 1 dma 0x86854a00 len 1 cppi_next_tx_segment 658: TXBD ff32a800: nxt 00000000 buf 86854a00 len 0001 opt e0000001 cppi_dump_tx 405: TX DMA0/S: csr 3403, H00000000 S86e71800 C86e71800 86854a01, F00020000 L00000001 .. 86e71800 txstate 410: ep1in TX/IN dma len 0/1, txcsr 3404, fifo 1/512 cppi_interrupt 1172: CPPI IRQ Tx1 Rx0 cppi_dump_tx 405: TX DMA0/E: csr 3404, H00000000 S86e71800 C86e71800 86854a01, F00020000 L00000001 .. 86e71800 cppi_interrupt 1217: C/TXBD ff32a800 n 0 b 86854a00 off 1 opt d0000000 musb_g_tx 430: <== ep1in, txcsr 3404 musb_g_tx 475: TXCSR1 2400, DMA off, len 1, req c6e927c0 musb_g_giveback 143: ep1in done request c6e927c0, 1/1 musb_g_tx 522: ep1in idle now 64-byte RX (wedges things, but gets to tty): cppi_interrupt 1172: CPPI IRQ Tx0 Rx1 cppi_dump_rx 377: RX DMA0/K: 0 left, csr 2003, 00000000 H00000000 S873388a0 C873388a0, B86854040 L004001c0 00000040 .. 873388a0 cppi_rx_scan 1045: C/RXBD 873388a0: nxt 00000000 buf 86854000 off.len 00000040 opt.len d0000040 (0) cppi_dump_rx 377: RX DMA0/completed: 0 left, csr 2003, 00000000 H00000000 S873388a0 C873388a0, B86854040 L004001c0 00000040 .. 873388a0 musb_g_rx 757: <== ep1out, rxcsr 2003 (dma) c6e92d00 musb_g_rx 800: RXCSR1 0003, dma off, 0003, len 64, req c6e92d00 musb_g_giveback 143: ep1out done request c6e92d00, 64/512 gs_read_complete: req c6e92d00 cppi_next_rx_segment 831: RX DMA0 seg, maxp 512 onepacket bds 1 (cnt 0) dma 0x86854200 len 512 0/512 RXBD/S 873388c0: nxt 00000000 buf 86854200 off.blen 00000200 opt.plen e0000200 cppi_dump_rx 377: RX DMA0/S: 3 left, csr 0003, 00000000 H873388c0 S873388a0 C873388a0, B86854040 L004001c0 00000040 .. 873388a0 davinci_interrupt 292: IRQ 00000000 ttyGS 64 bytes to tty (t T . ... 0x30 0x0a) musb_gadget_queue 1120: <== to ep1out request=c6e92d00 musb_gadget_queue 1120: <== to ep1in request=c6e927c0 musb_ep_restart 1088: <== TX/IN request c6e927c0 len 1 on hw_ep1 txstate 298: hw_ep1, maxpacket 512, fifo count 1, txcsr 2404 cppi_next_tx_segment 604: TX DMA0, pktSz 512 transparent bds 1 dma 0x86854a00 len 1 cppi_next_tx_segment 658: TXBD ff32a800: nxt 00000000 buf 86854a00 len 0001 opt e0000001 cppi_dump_tx 405: TX DMA0/S: csr 3403, H00000000 S86e71800 C86e71800 86854a01, F00020000 L00000001 .. 86e71800 txstate 410: ep1in TX/IN dma len 0/1, txcsr 3404, fifo 1/512 cppi_interrupt 1172: CPPI IRQ Tx1 Rx0 cppi_dump_tx 405: TX DMA0/E: csr 3404, H00000000 S86e71800 C86e71800 86854a01, F00020000 L00000001 .. 86e71800 cppi_interrupt 1217: C/TXBD ff32a800 n 0 b 86854a00 off 1 opt d0000000 musb_g_tx 430: <== ep1in, txcsr 3404 musb_g_tx 475: TXCSR1 2400, DMA off, len 1, req c6e927c0 musb_g_giveback 143: ep1in done request c6e927c0, 1/1 musb_g_tx 522: ep1in idle now Subsequent 63-byte RX (fails to arrive at tty) Not quite sure what's going on here, something very different: davinci_interrupt 292: IRQ 00000001 musb_interrupt 1583: ** IRQ peripheral usb0000 tx0001 rx0000 musb_g_ep0_irq 671: csr 0001, count 8, myaddr 3, ep0stage idle musb_read_fifo 283: RX ep0 fifo fec64420 count 8 buf c0363e36 musb_read_setup 605: SETUP req21.22 v0000 i0000 l0 musb_g_ep0_irq 853: handled 0, csr 0001, ep0stage wait g_serial gadget: acm ttyGS0 req21.22 v0000 i0000 l0 musb_g_ep0_queue 959: queue to ep0 (OUT/RX), length=0 musb_g_giveback 143: ep0 done request c6eca040, 0/0 -- Jon Povey jon.povey at racelogic.co.uk Racelogic is a limited company registered in England. Registered number 2743719 . Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB . The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network From balbi at ti.com Thu Sep 23 07:15:20 2010 From: balbi at ti.com (Felipe Balbi) Date: Thu, 23 Sep 2010 15:15:20 +0300 Subject: musb: repeatable CPPI DMA hang bug on peripheral RX 64 byte packet In-Reply-To: <70E876B0EA86DD4BAF101844BC814DFE093ED5FB9C@Cloud.RL.local> References: <70E876B0EA86DD4BAF101844BC814DFE093ED5FB9C@Cloud.RL.local> Message-ID: <20100923121520.GN4580@legolas.emea.dhcp.ti.com> Hi, On Thu, Sep 23, 2010 at 06:35:11AM -0500, Jon Povey wrote: >loading musb_hdrc with debug=7 shows up some suspicious differences >when receiving a 64-byte line, some console logs below. I note that >bits 0x3 of csr are set in the problem case. that's RxPktRdy and FifoFull. >64-byte RX (wedges things, but gets to tty): > >cppi_interrupt 1172: CPPI IRQ Tx0 Rx1 >cppi_dump_rx 377: RX DMA0/K: 0 left, csr 2003, 00000000 H00000000 S873388a0 C873388a0, B86854040 L004001c0 00000040 .. 873388a0 Can you check if you have the same with 512 byte transfers ?? >cppi_rx_scan 1045: C/RXBD 873388a0: nxt 00000000 buf 86854000 off.len 00000040 opt.len d0000040 (0) >cppi_dump_rx 377: RX DMA0/completed: 0 left, csr 2003, 00000000 H00000000 S873388a0 C873388a0, B86854040 L004001c0 00000040 .. 873388a0 >musb_g_rx 757: <== ep1out, rxcsr 2003 (dma) c6e92d00 >musb_g_rx 800: RXCSR1 0003, dma off, 0003, len 64, req c6e92d00 >musb_g_giveback 143: ep1out done request c6e92d00, 64/512 >gs_read_complete: req c6e92d00 >cppi_next_rx_segment 831: RX DMA0 seg, maxp 512 onepacket bds 1 (cnt 0) dma 0x86854200 len 512 0/512 >RXBD/S 873388c0: nxt 00000000 buf 86854200 off.blen 00000200 opt.plen e0000200 >cppi_dump_rx 377: RX DMA0/S: 3 left, csr 0003, 00000000 H873388c0 S873388a0 C873388a0, B86854040 L004001c0 00000040 .. 873388a0 >davinci_interrupt 292: IRQ 00000000 >ttyGS 64 bytes to tty (t T . ... 0x30 0x0a) >musb_gadget_queue 1120: <== to ep1out request=c6e92d00 >musb_gadget_queue 1120: <== to ep1in request=c6e927c0 >musb_ep_restart 1088: <== TX/IN request c6e927c0 len 1 on hw_ep1 >txstate 298: hw_ep1, maxpacket 512, fifo count 1, txcsr 2404 what's this one byte you're sending back ? >cppi_next_tx_segment 604: TX DMA0, pktSz 512 transparent bds 1 dma 0x86854a00 len 1 >cppi_next_tx_segment 658: TXBD ff32a800: nxt 00000000 buf 86854a00 len 0001 opt e0000001 >cppi_dump_tx 405: TX DMA0/S: csr 3403, H00000000 S86e71800 C86e71800 86854a01, F00020000 L00000001 .. 86e71800 >txstate 410: ep1in TX/IN dma len 0/1, txcsr 3404, fifo 1/512 >cppi_interrupt 1172: CPPI IRQ Tx1 Rx0 >cppi_dump_tx 405: TX DMA0/E: csr 3404, H00000000 S86e71800 C86e71800 86854a01, F00020000 L00000001 .. 86e71800 >cppi_interrupt 1217: C/TXBD ff32a800 n 0 b 86854a00 off 1 opt d0000000 >musb_g_tx 430: <== ep1in, txcsr 3404 >musb_g_tx 475: TXCSR1 2400, DMA off, len 1, req c6e927c0 >musb_g_giveback 143: ep1in done request c6e927c0, 1/1 >musb_g_tx 522: ep1in idle now > >Subsequent 63-byte RX (fails to arrive at tty) >Not quite sure what's going on here, something very different: > >davinci_interrupt 292: IRQ 00000001 >musb_interrupt 1583: ** IRQ peripheral usb0000 tx0001 rx0000 only ep0 IRQ ?!? weird. >Racelogic is a limited company registered in England. Registered number >2743719 . Registered Office Unit 10, Swan Business Centre, Osier Way, >Buckingham, Bucks, MK18 1TB . > >The information contained in this electronic mail transmission is >intended by Racelogic Ltd for the use of the named individual or entity >to which it is directed and may contain information that is >confidential or privileged. If you have received this electronic mail >transmission in error, please delete it from your system without >copying or forwarding it, and notify the sender of the error by reply >email so that the sender's address records can be corrected. The views >expressed by the sender of this communication do not necessarily >represent those of Racelogic Ltd. Please note that Racelogic reserves >the right to monitor e-mail communications passing through its network remove this sort of footer when sending mails to the mailing list!!! -- balbi From gongzy_sjz at yahoo.cn Thu Sep 23 08:40:42 2010 From: gongzy_sjz at yahoo.cn (=?utf-8?B?6Ieq55Sx5Lq6?=) Date: Thu, 23 Sep 2010 21:40:42 +0800 (CST) Subject: =?utf-8?B?cmXvvJogaG93IHRvIHN0YXJ0IGRzcCBwcm9ncmFtIGZyb20gdWJsPw==?= Message-ID: <727769.12078.qm@web92413.mail.cnh.yahoo.com> thank you replay. according to?document spruep9c.pdf. i?wrote?ubl booting dsp code,work well. -------------- next part -------------- An HTML attachment was scrubbed... URL: From khilman at deeprootsystems.com Thu Sep 23 09:24:11 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 23 Sep 2010 07:24:11 -0700 Subject: New WARN from dm9000 since merge to 2.6.36-rc4 In-Reply-To: <70E876B0EA86DD4BAF101844BC814DFE093ED5FAA5@Cloud.RL.local> (Jon Povey's message of "Thu, 23 Sep 2010 04:49:28 +0100") References: <70E876B0EA86DD4BAF101844BC814DFE093ED5FAA5@Cloud.RL.local> Message-ID: <87hbhg7d2s.fsf@deeprootsystems.com> Jon Povey writes: > I have been working based on 2.6.34 for a while, tried merging from 2.6.36-rc4 to look at some possible USB improvements, and get a new warning on boot. > > This is on DM355, not the EVM, but uses the same ethernet design, in the same way. > As far as I can tell the board and config are the same. > > Given that this looks like something to do with dm9000, I tried reverting the suspicious > 380fefb2d "dm9000: fix "BUG: spinlock recursion"" > but that made no difference. > > Any clues welcome, here's the console output with some uninteresting stuff snipped. Hi Jon, I noticed this as well but didn't debug it much further. It might be worth posting to the netdev list: netdev at vger.kernel.org as when I looked at this, it looked like the softirq code in question hadn't changed for some time. Kevin > Linux version 2.6.36-rc4+ (jon at eroko) (gcc version 4.3.3 (Sourcery G++ Lite 2009q1-203) ) #33 PREEMPT Wed Sep 22 19:26:45 JST 2010 > CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177 > CPU: VIVT data cache, VIVT instruction cache > Machine: Racelogic Video VBOX (SDPRO4) > Memory policy: ECC disabled, Data cache writeback > DaVinci dm355 variant 0x0 > On node 0 totalpages: 32768 > free_area_init_node: node 0, pgdat c038105c, node_mem_map c03ab000 > DMA zone: 256 pages used for memmap > DMA zone: 0 pages reserved > DMA zone: 32512 pages, LIFO batch:7 > Built 1 zonelists in Zone order, mobility grouping on. Total pages: 32512 > Kernel command line: console=ttyS0,115200n8 rw ip=dhcp root=/dev/nfs nfsroot=192.168.1.140:/home/jon/vidbox-gitkernel/dvnfs,nolock loglevel=8 > PID hash table entries: 512 (order: -1, 2048 bytes) > Dentry cache hash table entries: 16384 (order: 4, 65536 bytes) > Inode-cache hash table entries: 8192 (order: 3, 32768 bytes) > Memory: 128MB = 128MB total > Memory: 126196k/126196k available, 4876k reserved, 0K highmem > Virtual kernel memory layout: > vector : 0xffff0000 - 0xffff1000 ( 4 kB) > fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB) > DMA : 0xff000000 - 0xffe00000 ( 14 MB) > vmalloc : 0xc8800000 - 0xfea00000 ( 866 MB) > lowmem : 0xc0000000 - 0xc8000000 ( 128 MB) > modules : 0xbf000000 - 0xc0000000 ( 16 MB) > .init : 0xc0008000 - 0xc0026000 ( 120 kB) > .text : 0xc0026000 - 0xc0361000 (3308 kB) > .data : 0xc0362000 - 0xc0381960 ( 127 kB) > SLUB: Genslabs=11, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 > Hierarchical RCU implementation. > RCU-based detection of stalled CPUs is disabled. > Verbose stalled-CPUs detection is disabled. > NR_IRQS:245 > Calibrating delay loop... 134.34 BogoMIPS (lpj=671744) > pid_max: default: 32768 minimum: 301 > Mount-cache hash table entries: 512 > CPU: Testing write buffer coherency: ok > devtmpfs: initialized > DaVinci: 104 gpio irqs > ... > Switching to clocksource timer0_1 > NET: Registered protocol family 2 > IP route cache hash table entries: 1024 (order: 0, 4096 bytes) > TCP established hash table entries: 4096 (order: 3, 32768 bytes) > TCP bind hash table entries: 4096 (order: 2, 16384 bytes) > TCP: Hash tables configured (established 4096 bind 4096) > TCP reno registered > UDP hash table entries: 256 (order: 0, 4096 bytes) > UDP-Lite hash table entries: 256 (order: 0, 4096 bytes) > NET: Registered protocol family 1 > RPC: Registered udp transport module. > RPC: Registered tcp transport module. > RPC: Registered tcp NFSv4.1 backchannel transport module. > msgmni has been set to 246 > ... > dm9000 Ethernet Driver, V1.31 > eth0: dm9000a at c8838000,c883c002 IRQ 65 MAC: 00:50:c2:68:00:10 (chip) > console [netcon0] enabled > netconsole: network logging started > ... > TCP cubic registered > NET: Registered protocol family 17 > rtc-m41t80 1-0068: setting system clock to 2010-09-23 02:40:56 UTC (1285209656) > eth0: link down > eth0: link up, 100Mbps, full-duplex, lpa 0x45E1 > Sending DHCP requests . > ------------[ cut here ]------------ > WARNING: at kernel/softirq.c:143 local_bh_enable+0x4c/0xc8() > Modules linked in: > Backtrace: > [] (dump_backtrace+0x0/0x114) from [] (dump_stack+0x18/0x1c) > r7:00000000 r6:c0040aec r5:c0319fef r4:0000008f > [] (dump_stack+0x0/0x1c) from [] (warn_slowpath_common+0x54/0x6c) > [] (warn_slowpath_common+0x0/0x6c) from [] (warn_slowpath_null+0x24/0x2c) > r9:00000015 r8:00000015 r7:0000015a r6:c6ffc240 r5:c786b3a0 > r4:c0386860 > [] (warn_slowpath_null+0x0/0x2c) from [] (local_bh_enable+0x4c/0xc8) > [] (local_bh_enable+0x0/0xc8) from [] (netif_rx+0xb0/0x21c) > r5:c786b3a0 r4:00000000 > [] (netif_rx+0x0/0x21c) from [] (dm9000_interrupt+0x1d4/0x334) > r6:c786b000 r5:c786b3a0 r4:c6ffc240 > [] (dm9000_interrupt+0x0/0x334) from [] (handle_IRQ_event+0x2c/0xfc) > [] (handle_IRQ_event+0x0/0xfc) from [] (handle_simple_irq+0x94/0xf4) > r7:00000042 r6:00000041 r5:c036d728 r4:c7ad70c0 > [] (handle_simple_irq+0x0/0xf4) from [] (gpio_irq_handler+0xc0/0xf0) > r7:00000042 r6:00000002 r5:00000041 r4:00000002 > [] (gpio_irq_handler+0x0/0xf0) from [] (asm_do_IRQ+0x7c/0xa0) > [] (asm_do_IRQ+0x0/0xa0) from [] (__irq_svc+0x4c/0x90) > Exception stack(0xc0363f48 to 0xc0363f90) > 3f40: 00000000 0005317f 0005217f 60000013 c0362000 c0381a60 > 3f60: c002301c c0366840 80020ce8 41069265 80020cb4 c0363f9c 600000d3 c0363f90 > 3f80: c0027a4c c0027a58 60000013 ffffffff > r5:fec48000 r4:ffffffff > [] (default_idle+0x0/0x38) from [] (cpu_idle+0x78/0xe4) > [] (cpu_idle+0x0/0xe4) from [] (rest_init+0xa8/0xc0) > r5:c0381a60 r4:00000002 > [] (rest_init+0x0/0xc0) from [] (start_kernel+0x270/0x2c4) > r5:c0381a60 r4:c0396584 > [] (start_kernel+0x0/0x2c4) from [<80008034>] (0x80008034) > r5:c0381b04 r4:00053175 > ---[ end trace af4a93804142fc65 ]--- > , OK > IP-Config: Got DHCP answer from 192.168.1.1, my address is 192.168.1.142 > IP-Config: Complete: > device=eth0, addr=192.168.1.142, mask=255.255.255.0, gw=192.168.1.1, > host=192.168.1.142, domain=, nis-domain=(none), > bootserver=192.168.1.1, rootserver=192.168.1.140, rootpath= > Looking up port of RPC 100003/2 on 192.168.1.140 > Looking up port of RPC 100005/1 on 192.168.1.140 > VFS: Mounted root (nfs filesystem) on device 0:14. > > -- > Jon Povey > jon.povey at racelogic.co.uk > > Racelogic is a limited company registered in England. Registered number 2743719 . > Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB . > > The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network > > > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source at linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source From khilman at deeprootsystems.com Thu Sep 23 09:27:38 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 23 Sep 2010 07:27:38 -0700 Subject: [PATCH v4] i2c: davinci: Fix race when setting up for TX In-Reply-To: <4C9904E6.7070608@boundarydevices.com> (Troy Kisky's message of "Tue, 21 Sep 2010 12:17:58 -0700") References: <4C97CEC9.8060602@boundarydevices.com> <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> <026901cb597f$86fa9980$94efcc80$@raj@ti.com> <4C9904E6.7070608@boundarydevices.com> Message-ID: <87d3s47cx1.fsf@deeprootsystems.com> Troy Kisky writes: > On 9/21/2010 4:24 AM, Sudhakar Rajashekhara wrote: >> Hi, >> >> On Tue, Sep 21, 2010 at 09:43:28, Jon Povey wrote: >>> When setting up to transmit, a race exists between the ISR and >>> i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. >>> This is mostly visible for transmits > 1 byte long. >>> >>> The hardware starts sending immediately that MDR.STT is set. IMR trickery >>> doesn't work because if we start sending, finish the first byte and an >>> XRDY event occurs before we load IMR to unmask it, we never get an >>> interrupt, and we timeout. >>> >>> Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode >>> settings before DXR for correct behaviour, so load MDR first with >>> STT cleared and later load again with STT set. >>> >>> Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 >>> >>> Signed-off-by: Jon Povey >>> CC: Sudhakar Rajashekhara >>> CC: Troy Kisky >>> --- >>> Reworked after comments by Troy and Sudhakar. >>> >>> Looking at the datasheet it seemed like setting STP without STT early >>> might cause a stray STOP to be generated, so I moved it into the second >>> MDR load. >>> >>> This passes a quick smoke test but I can't do much more testing right at >>> the moment. Sudhakar, your comments would be welcomed. >>> >> >> Looks good to me. I can test on couple of platforms I have and update the result >> by tomorrow. >> >> Thanks, >> Sudhakar >> >> >> > I like it too. I hope it works for omap. Troy, can I take this as an Acked-by from you? or a Tested-by? Thanks, Kevin From nsekhar at ti.com Thu Sep 23 09:48:04 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Thu, 23 Sep 2010 20:18:04 +0530 Subject: support for dm6467 framebuffer In-Reply-To: <4C9AE607.50306@freesystems.biz> References: <4C9AE607.50306@freesystems.biz> Message-ID: Hi Siva, On Thu, Sep 23, 2010 at 11:00:47, siva prasad T wrote: > hi, > > i am working on TMS320DM6467 processor of DM6467EVM and after booting my > linux kernel which has been taken from arego project i am not able to > observe frame buffer nodes in /dev folder... so please sugest me how to > get frame buffer nodes enabled. DM6467 does not support framebuffer. Only V4L2 is supported. Thanks, Sekhar From vm.rod25 at gmail.com Thu Sep 23 11:28:40 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Thu, 23 Sep 2010 11:28:40 -0500 Subject: [PATCH v7] davinci: Initial support for Omapl138-Hawkboard Message-ID: <1285259320-2541-1-git-send-email-vm.rod25@gmail.com> This patch adds initial support for the Hawkboard-L138 system It is under the machine name "omapl138_hawkboard". This system is based on the da850 davinci CPU architecture. Information on these system may be found at http://www.hawkboard.org. Basic support for the UART console is included in this patch. It's tested with latest Angstrom File Systems like ramdisk from http://alturl.com/imb45. Signed-off-by: Victor Rodriguez --- Changes since v6: 1) Change commit reference 2) Remove hack that shut down UART1 because it is unused at present on the hawkboard. It shares pins with McASP0 transmit/receive master clock, opening UART1 will lead to a series of spurious interrupts. Some filesystems call getty on UART1 irrespective of whether it is console or not. On such filesystems, not shutting down UART1 causes boot-failure because of interrupt flood. Notes: This patch is checked with b8a24f38d6ee61b819f73ba53d51e3445314f0dc from Kernel development tree for TI DaVinci family of processors. This patch works with da8xx_omapl_defconfig plus this patch. --- arch/arm/configs/da8xx_omapl_defconfig | 1 + arch/arm/mach-davinci/Kconfig | 8 +++ arch/arm/mach-davinci/Makefile | 1 + arch/arm/mach-davinci/board-omapl138-hawk.c | 64 +++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/uncompress.h | 1 + 5 files changed, 75 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/board-omapl138-hawk.c diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig index f8a47ee..cdc40c4 100644 --- a/arch/arm/configs/da8xx_omapl_defconfig +++ b/arch/arm/configs/da8xx_omapl_defconfig @@ -18,6 +18,7 @@ CONFIG_ARCH_DAVINCI=y CONFIG_ARCH_DAVINCI_DA830=y CONFIG_ARCH_DAVINCI_DA850=y CONFIG_MACH_MITYOMAPL138=y +CONFIG_MACH_OMAPL138_HAWKBOARD=y CONFIG_DAVINCI_RESET_CLOCKS=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 9aca60c..b77b860 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -193,6 +193,14 @@ config MACH_MITYOMAPL138 System on Module. Information on this SoM may be found at http://www.mitydsp.com +config MACH_OMAPL138_HAWKBOARD + bool "TI AM1808 / OMAPL-138 Hawkboard platform" + depends on ARCH_DAVINCI_DA850 + help + Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard platform . + Information of this board may be found at + http://www.hawkboard.org/ + config DAVINCI_MUX bool "DAVINCI multiplexing support" depends on ARCH_DAVINCI diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index a7a70d1..0b87a1c 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o # Power Management obj-$(CONFIG_CPU_FREQ) += cpufreq.o diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c new file mode 100644 index 0000000..014876b --- /dev/null +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c @@ -0,0 +1,64 @@ +/* + * Hawkboard.org based on TI's OMAP-L138 Platform + * + * Initial code: Syed Mohammed Khasim + * + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 +#include +#include +#include + +#include +#include + +#include +#include + +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { + .enabled_uarts = 0x7, +}; + +static __init void omapl138_hawk_init(void) +{ + int ret; + + davinci_serial_init(&omapl138_hawk_uart_config); + + ret = da8xx_register_watchdog(); + if (ret) + pr_warning("omapl138_hawk_init: " + "watchdog registration failed: %d\n", + ret); +} + +#ifdef CONFIG_SERIAL_8250_CONSOLE +static int __init omapl138_hawk_console_init(void) +{ + if (!machine_is_omapl138_hawkboard()) + return 0; + + return add_preferred_console("ttyS", 2, "115200"); +} +console_initcall(omapl138_hawk_console_init); +#endif + +static void __init omapl138_hawk_map_io(void) +{ + da850_init(); +} + +MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") + .phys_io = IO_PHYS, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, + .boot_params = (DA8XX_DDR_BASE + 0x100), + .map_io = omapl138_hawk_map_io, + .init_irq = cp_intc_init, + .timer = &davinci_timer, + .init_machine = omapl138_hawk_init, +MACHINE_END diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h index d370391..47723e8 100644 --- a/arch/arm/mach-davinci/include/mach/uncompress.h +++ b/arch/arm/mach-davinci/include/mach/uncompress.h @@ -89,6 +89,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) DEBUG_LL_DA8XX(davinci_da830_evm, 2); DEBUG_LL_DA8XX(davinci_da850_evm, 2); DEBUG_LL_DA8XX(mityomapl138, 1); + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); /* TNETV107x boards */ DEBUG_LL_TNETV107X(tnetv107x, 1); -- 1.6.0.5 From troy.kisky at boundarydevices.com Thu Sep 23 15:27:58 2010 From: troy.kisky at boundarydevices.com (Troy Kisky) Date: Thu, 23 Sep 2010 13:27:58 -0700 Subject: [PATCH v4] i2c: davinci: Fix race when setting up for TX In-Reply-To: <87d3s47cx1.fsf@deeprootsystems.com> References: <4C97CEC9.8060602@boundarydevices.com> <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> <026901cb597f$86fa9980$94efcc80$@raj@ti.com> <4C9904E6.7070608@boundarydevices.com> <87d3s47cx1.fsf@deeprootsystems.com> Message-ID: <4C9BB84E.2040000@boundarydevices.com> On 9/23/2010 7:27 AM, Kevin Hilman wrote: > Troy Kisky writes: > >> On 9/21/2010 4:24 AM, Sudhakar Rajashekhara wrote: >>> Hi, >>> >>> On Tue, Sep 21, 2010 at 09:43:28, Jon Povey wrote: >>>> When setting up to transmit, a race exists between the ISR and >>>> i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. >>>> This is mostly visible for transmits > 1 byte long. >>>> >>>> The hardware starts sending immediately that MDR.STT is set. IMR trickery >>>> doesn't work because if we start sending, finish the first byte and an >>>> XRDY event occurs before we load IMR to unmask it, we never get an >>>> interrupt, and we timeout. >>>> >>>> Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode >>>> settings before DXR for correct behaviour, so load MDR first with >>>> STT cleared and later load again with STT set. >>>> >>>> Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 >>>> >>>> Signed-off-by: Jon Povey >>>> CC: Sudhakar Rajashekhara >>>> CC: Troy Kisky >>>> --- >>>> Reworked after comments by Troy and Sudhakar. >>>> >>>> Looking at the datasheet it seemed like setting STP without STT early >>>> might cause a stray STOP to be generated, so I moved it into the second >>>> MDR load. >>>> >>>> This passes a quick smoke test but I can't do much more testing right at >>>> the moment. Sudhakar, your comments would be welcomed. >>>> >>> >>> Looks good to me. I can test on couple of platforms I have and update the result >>> by tomorrow. >>> >>> Thanks, >>> Sudhakar >>> >>> >>> >> I like it too. I hope it works for omap. > > Troy, can I take this as an Acked-by from you? or a Tested-by? > > Thanks, > > Kevin > Acked-by is fine, but I didn't test it. Troy From sudhakar.raj at ti.com Thu Sep 23 23:42:07 2010 From: sudhakar.raj at ti.com (Sudhakar Rajashekhara) Date: Fri, 24 Sep 2010 10:12:07 +0530 Subject: [PATCH v4] i2c: davinci: Fix race when setting up for TX In-Reply-To: <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> References: <4C97CEC9.8060602@boundarydevices.com> <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> Message-ID: <022501cb5ba2$d801d760$88058620$@raj@ti.com> On Tue, Sep 21, 2010 at 09:43:28, Jon Povey wrote: > When setting up to transmit, a race exists between the ISR and > i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. > This is mostly visible for transmits > 1 byte long. > > The hardware starts sending immediately that MDR.STT is set. IMR trickery > doesn't work because if we start sending, finish the first byte and an > XRDY event occurs before we load IMR to unmask it, we never get an > interrupt, and we timeout. > > Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode > settings before DXR for correct behaviour, so load MDR first with > STT cleared and later load again with STT set. > > Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 > > Signed-off-by: Jon Povey > CC: Sudhakar Rajashekhara > CC: Troy Kisky > --- Tested-by: Sudhakar Rajashekhara Tested with audio loopback on OMAP-L138, OMAP-L137 and DM365. Also tested with i2cdetect function which probes all the devices on the i2c bus. Thanks, Sudhakar From Jon.Povey at racelogic.co.uk Fri Sep 24 02:39:03 2010 From: Jon.Povey at racelogic.co.uk (Jon Povey) Date: Fri, 24 Sep 2010 08:39:03 +0100 Subject: musb: repeatable CPPI DMA hang bug on peripheral RX 64 byte packet In-Reply-To: <20100923121520.GN4580@legolas.emea.dhcp.ti.com> Message-ID: <70E876B0EA86DD4BAF101844BC814DFE093ED5FCA7@Cloud.RL.local> Felipe Balbi wrote: > On Thu, Sep 23, 2010 at 06:35:11AM -0500, Jon Povey wrote: >> loading musb_hdrc with debug=7 shows up some suspicious differences >> when receiving a 64-byte line, some console logs below. I note that >> bits 0x3 of csr are set in the problem case. > > that's RxPktRdy and FifoFull. Yup. But I don't know enough about this driver and hardware to know what that implies. > Can you check if you have the same with 512 byte transfers ?? Yes, it looks like it. 511 is ok, 512 locks up rx and gives the below on the console. 128 chars also locks things up. cppi_interrupt 1173: CPPI IRQ Tx0 Rx1 cppi_dump_rx 378: RX DMA0/K: 0 left, csr 2003, 00000000 H00000000 S86eb78a0 C86eb78a0, B879eea00 L02000000 00000200 .. 86eb78a0 cppi_rx_scan 1046: C/RXBD 86eb78a0: nxt 00000000 buf 879ee800 off.len 00000200 opt.len d0000200 (0) cppi_dump_rx 378: RX DMA0/completed: 0 left, csr 2003, 00000000 H00000000 S86eb78a0 C86eb78a0, B879eea00 L02000000 00000200 .. 86eb78a0 musb_g_rx 763: <== ep1out, rxcsr 2003 (dma) c6efdcc0 musb_g_rx 806: RXCSR1 0003, dma off, 0003, len 512, req c6efdcc0 musb_g_giveback 143: ep1out done request c6efdcc0, 512/512 gs_read_complete: req c6efdcc0 cppi_next_rx_segment 832: RX DMA0 seg, maxp 512 onepacket bds 1 (cnt 0) dma 0x879eec00 len 512 0/512 RXBD/S 86eb78c0: nxt 00000000 buf 879eec00 off.blen 00000200 opt.plen e0000200 cppi_dump_rx 378: RX DMA0/S: 3 left, csr 0003, 00000000 H86eb78c0 S86eb78a0 C86eb78a0, B879eea00 L02000000 00000200 .. 86eb78a0 davinci_interrupt 292: IRQ 00000000 ttyGS 512 bytes to tty (c C - ... 0x2e 0x0a) musb_gadget_queue 1148: <== to ep1out request=c6efdcc0 >> musb_ep_restart 1088: <== TX/IN request c6e927c0 len 1 on hw_ep1 >> txstate 298: hw_ep1, maxpacket 512, fifo count 1, txcsr 2404 > > what's this one byte you're sending back ? I snipped the rest but it seems the tty layer was echoing back each character, individually (!) stty -F /dev/ttyGS0 -echo stopped that. I don't remember it doing this echoing by default with 2.6.34.. >> Subsequent 63-byte RX (fails to arrive at tty) >> Not quite sure what's going on here, something very different: >> >> davinci_interrupt 292: IRQ 00000001 >> musb_interrupt 1583: ** IRQ peripheral usb0000 tx0001 rx0000 > > only ep0 IRQ ?!? weird. Oh, I think was ACM traffic from the Windows app reopening the serial port when it gets a TX timeout. I stopped it doing that, now after sending a line with killer length, any subsequent line times out and there are no more console messages from usb. >> Racelogic is a limited company registered in England. Registered >> number 2743719 . Registered Office Unit 10, Swan Business Centre, >> Osier Way, Buckingham, Bucks, MK18 1TB . >> >> The information contained in this electronic mail transmission is ... > > remove this sort of footer when sending mails to the mailing list!!! I'd love to, but it's not my decision, and part of it is a legal requirement: http://www.theregister.co.uk/2006/12/21/new_web_email_regulation/ Sorry. -- Jon Povey jon.povey at racelogic.co.uk Racelogic is a limited company registered in England. Registered number 2743719 . Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB . The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network From balbi at ti.com Fri Sep 24 02:44:32 2010 From: balbi at ti.com (Felipe Balbi) Date: Fri, 24 Sep 2010 10:44:32 +0300 Subject: musb: repeatable CPPI DMA hang bug on peripheral RX 64 byte packet In-Reply-To: <70E876B0EA86DD4BAF101844BC814DFE093ED5FCA7@Cloud.RL.local> References: <20100923121520.GN4580@legolas.emea.dhcp.ti.com> <70E876B0EA86DD4BAF101844BC814DFE093ED5FCA7@Cloud.RL.local> Message-ID: <20100924074432.GF8365@legolas.emea.dhcp.ti.com> Hi, On Fri, Sep 24, 2010 at 02:39:03AM -0500, Jon Povey wrote: >Yup. But I don't know enough about this driver and hardware to know >what that implies. it means you have a packet pending on the FIFO and the fifo is now full :-p >cppi_interrupt 1173: CPPI IRQ Tx0 Rx1 >cppi_dump_rx 378: RX DMA0/K: 0 left, csr 2003, 00000000 H00000000 S86eb78a0 C86eb78a0, B879eea00 L02000000 00000200 .. 86eb78a0 >cppi_rx_scan 1046: C/RXBD 86eb78a0: nxt 00000000 buf 879ee800 off.len 00000200 opt.len d0000200 (0) >cppi_dump_rx 378: RX DMA0/completed: 0 left, csr 2003, 00000000 H00000000 S86eb78a0 C86eb78a0, B879eea00 L02000000 00000200 .. 86eb78a0 >musb_g_rx 763: <== ep1out, rxcsr 2003 (dma) c6efdcc0 >musb_g_rx 806: RXCSR1 0003, dma off, 0003, len 512, req c6efdcc0 >musb_g_giveback 143: ep1out done request c6efdcc0, 512/512 >gs_read_complete: req c6efdcc0 >cppi_next_rx_segment 832: RX DMA0 seg, maxp 512 onepacket bds 1 (cnt 0) dma 0x879eec00 len 512 0/512 >RXBD/S 86eb78c0: nxt 00000000 buf 879eec00 off.blen 00000200 opt.plen e0000200 >cppi_dump_rx 378: RX DMA0/S: 3 left, csr 0003, 00000000 H86eb78c0 S86eb78a0 C86eb78a0, B879eea00 L02000000 00000200 .. 86eb78a0 >davinci_interrupt 292: IRQ 00000000 >ttyGS 512 bytes to tty (c C - ... 0x2e 0x0a) >musb_gadget_queue 1148: <== to ep1out request=c6efdcc0 Sergei, do you see anything fishy wrt CPPI dma ?? -- balbi From sshtylyov at mvista.com Fri Sep 24 08:02:14 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Fri, 24 Sep 2010 17:02:14 +0400 Subject: musb: repeatable CPPI DMA hang bug on peripheral RX 64 byte packet In-Reply-To: <20100924074432.GF8365@legolas.emea.dhcp.ti.com> References: <20100923121520.GN4580@legolas.emea.dhcp.ti.com> <70E876B0EA86DD4BAF101844BC814DFE093ED5FCA7@Cloud.RL.local> <20100924074432.GF8365@legolas.emea.dhcp.ti.com> Message-ID: <4C9CA156.2010404@ru.mvista.com> Hello. Felipe Balbi wrote: >> cppi_interrupt 1173: CPPI IRQ Tx0 Rx1 >> cppi_dump_rx 378: RX DMA0/K: 0 left, csr 2003, 00000000 H00000000 >> S86eb78a0 C86eb78a0, B879eea00 L02000000 00000200 .. 86eb78a0 >> cppi_rx_scan 1046: C/RXBD 86eb78a0: nxt 00000000 buf 879ee800 off.len >> 00000200 opt.len d0000200 (0) >> cppi_dump_rx 378: RX DMA0/completed: 0 left, csr 2003, 00000000 >> H00000000 S86eb78a0 C86eb78a0, B879eea00 L02000000 00000200 .. 86eb78a0 >> musb_g_rx 763: <== ep1out, rxcsr 2003 (dma) c6efdcc0 >> musb_g_rx 806: RXCSR1 0003, dma off, 0003, len 512, req c6efdcc0 >> musb_g_giveback 143: ep1out done request c6efdcc0, 512/512 >> gs_read_complete: req c6efdcc0 >> cppi_next_rx_segment 832: RX DMA0 seg, maxp 512 onepacket bds 1 (cnt >> 0) dma 0x879eec00 len 512 0/512 >> RXBD/S 86eb78c0: nxt 00000000 buf 879eec00 off.blen 00000200 opt.plen >> e0000200 >> cppi_dump_rx 378: RX DMA0/S: 3 left, csr 0003, 00000000 H86eb78c0 >> S86eb78a0 C86eb78a0, B879eea00 L02000000 00000200 .. 86eb78a0 >> davinci_interrupt 292: IRQ 00000000 >> ttyGS 512 bytes to tty (c C - ... 0x2e 0x0a) >> musb_gadget_queue 1148: <== to ep1out request=c6efdcc0 > Sergei, do you see anything fishy wrt CPPI dma ?? Unfortunately, I'm not an expert in CPPI 3.0 DMA code... WBR, Sergei From khilman at deeprootsystems.com Fri Sep 24 09:37:03 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Fri, 24 Sep 2010 07:37:03 -0700 Subject: [PATCH v4] i2c: davinci: Fix race when setting up for TX In-Reply-To: <022501cb5ba2$d801d760$88058620$@raj@ti.com> (Sudhakar Rajashekhara's message of "Fri, 24 Sep 2010 10:12:07 +0530") References: <4C97CEC9.8060602@boundarydevices.com> <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> <022501cb5ba2$d801d760$88058620$@raj@ti.com> Message-ID: <87sk0zky28.fsf@deeprootsystems.com> "Sudhakar Rajashekhara" writes: > On Tue, Sep 21, 2010 at 09:43:28, Jon Povey wrote: >> When setting up to transmit, a race exists between the ISR and >> i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. >> This is mostly visible for transmits > 1 byte long. >> >> The hardware starts sending immediately that MDR.STT is set. IMR trickery >> doesn't work because if we start sending, finish the first byte and an >> XRDY event occurs before we load IMR to unmask it, we never get an >> interrupt, and we timeout. >> >> Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode >> settings before DXR for correct behaviour, so load MDR first with >> STT cleared and later load again with STT set. >> >> Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 >> >> Signed-off-by: Jon Povey >> CC: Sudhakar Rajashekhara >> CC: Troy Kisky >> --- > > Tested-by: Sudhakar Rajashekhara > > Tested with audio loopback on OMAP-L138, OMAP-L137 and DM365. Also tested with > i2cdetect function which probes all the devices on the i2c bus. Ben, can you queue this one for 2.6.37 with the addition of: Acked-by: Troy Kisky Tested-by: Sudhakar Rajashekhara Acked-by: Kevin Hilman Thanks, Kevin From khilman at deeprootsystems.com Fri Sep 24 09:41:57 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Fri, 24 Sep 2010 07:41:57 -0700 Subject: [PATCH v7] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <1285259320-2541-1-git-send-email-vm.rod25@gmail.com> (Victor Rodriguez's message of "Thu, 23 Sep 2010 11:28:40 -0500") References: <1285259320-2541-1-git-send-email-vm.rod25@gmail.com> Message-ID: <87lj6rkxu2.fsf@deeprootsystems.com> Victor Rodriguez writes: > This patch adds initial support for the Hawkboard-L138 system > It is under the machine name "omapl138_hawkboard". > This system is based on the da850 davinci CPU architecture. > Information on these system may be found at http://www.hawkboard.org. > Basic support for the UART console is included in this patch. > It's tested with latest Angstrom File Systems like ramdisk > from http://alturl.com/imb45. > > Signed-off-by: Victor Rodriguez > --- > Changes since v6: > 1) Change commit reference > 2) Remove hack that shut down UART1 because > it is unused at present on the hawkboard. Thanks for removing this. Applying and queuing for 2.6.37 in davinci-next. Kevin > It shares pins with McASP0 transmit/receive master clock, > opening UART1 will lead to a series of spurious interrupts. > Some filesystems call getty on UART1 irrespective of whether > it is console or not. On such filesystems, not shutting down > UART1 causes boot-failure because of interrupt flood. > > Notes: > > This patch is checked with b8a24f38d6ee61b819f73ba53d51e3445314f0dc > from Kernel development tree for TI DaVinci family of processors. > This patch works with da8xx_omapl_defconfig plus this patch. > --- > arch/arm/configs/da8xx_omapl_defconfig | 1 + > arch/arm/mach-davinci/Kconfig | 8 +++ > arch/arm/mach-davinci/Makefile | 1 + > arch/arm/mach-davinci/board-omapl138-hawk.c | 64 +++++++++++++++++++++++ > arch/arm/mach-davinci/include/mach/uncompress.h | 1 + > 5 files changed, 75 insertions(+), 0 deletions(-) > create mode 100644 arch/arm/mach-davinci/board-omapl138-hawk.c > > diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig > index f8a47ee..cdc40c4 100644 > --- a/arch/arm/configs/da8xx_omapl_defconfig > +++ b/arch/arm/configs/da8xx_omapl_defconfig > @@ -18,6 +18,7 @@ CONFIG_ARCH_DAVINCI=y > CONFIG_ARCH_DAVINCI_DA830=y > CONFIG_ARCH_DAVINCI_DA850=y > CONFIG_MACH_MITYOMAPL138=y > +CONFIG_MACH_OMAPL138_HAWKBOARD=y > CONFIG_DAVINCI_RESET_CLOCKS=y > CONFIG_NO_HZ=y > CONFIG_HIGH_RES_TIMERS=y > diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig > index 9aca60c..b77b860 100644 > --- a/arch/arm/mach-davinci/Kconfig > +++ b/arch/arm/mach-davinci/Kconfig > @@ -193,6 +193,14 @@ config MACH_MITYOMAPL138 > System on Module. Information on this SoM may be found at > http://www.mitydsp.com > > +config MACH_OMAPL138_HAWKBOARD > + bool "TI AM1808 / OMAPL-138 Hawkboard platform" > + depends on ARCH_DAVINCI_DA850 > + help > + Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard platform . > + Information of this board may be found at > + http://www.hawkboard.org/ > + > config DAVINCI_MUX > bool "DAVINCI multiplexing support" > depends on ARCH_DAVINCI > diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile > index a7a70d1..0b87a1c 100644 > --- a/arch/arm/mach-davinci/Makefile > +++ b/arch/arm/mach-davinci/Makefile > @@ -34,6 +34,7 @@ obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o > obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o > obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o > obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o > +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o > > # Power Management > obj-$(CONFIG_CPU_FREQ) += cpufreq.o > diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c > new file mode 100644 > index 0000000..014876b > --- /dev/null > +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c > @@ -0,0 +1,64 @@ > +/* > + * Hawkboard.org based on TI's OMAP-L138 Platform > + * > + * Initial code: Syed Mohammed Khasim > + * > + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 > +#include > +#include > +#include > + > +#include > +#include > + > +#include > +#include > + > +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { > + .enabled_uarts = 0x7, > +}; > + > +static __init void omapl138_hawk_init(void) > +{ > + int ret; > + > + davinci_serial_init(&omapl138_hawk_uart_config); > + > + ret = da8xx_register_watchdog(); > + if (ret) > + pr_warning("omapl138_hawk_init: " > + "watchdog registration failed: %d\n", > + ret); > +} > + > +#ifdef CONFIG_SERIAL_8250_CONSOLE > +static int __init omapl138_hawk_console_init(void) > +{ > + if (!machine_is_omapl138_hawkboard()) > + return 0; > + > + return add_preferred_console("ttyS", 2, "115200"); > +} > +console_initcall(omapl138_hawk_console_init); > +#endif > + > +static void __init omapl138_hawk_map_io(void) > +{ > + da850_init(); > +} > + > +MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") > + .phys_io = IO_PHYS, > + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, > + .boot_params = (DA8XX_DDR_BASE + 0x100), > + .map_io = omapl138_hawk_map_io, > + .init_irq = cp_intc_init, > + .timer = &davinci_timer, > + .init_machine = omapl138_hawk_init, > +MACHINE_END > diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h > index d370391..47723e8 100644 > --- a/arch/arm/mach-davinci/include/mach/uncompress.h > +++ b/arch/arm/mach-davinci/include/mach/uncompress.h > @@ -89,6 +89,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) > DEBUG_LL_DA8XX(davinci_da830_evm, 2); > DEBUG_LL_DA8XX(davinci_da850_evm, 2); > DEBUG_LL_DA8XX(mityomapl138, 1); > + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); > > /* TNETV107x boards */ > DEBUG_LL_TNETV107X(tnetv107x, 1); From vm.rod25 at gmail.com Fri Sep 24 10:08:43 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Fri, 24 Sep 2010 10:08:43 -0500 Subject: [PATCH v7] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <87lj6rkxu2.fsf@deeprootsystems.com> References: <1285259320-2541-1-git-send-email-vm.rod25@gmail.com> <87lj6rkxu2.fsf@deeprootsystems.com> Message-ID: On Fri, Sep 24, 2010 at 9:41 AM, Kevin Hilman wrote: > Victor Rodriguez writes: > >> This patch adds initial support for the Hawkboard-L138 system >> It is under the machine name "omapl138_hawkboard". >> This system is based on the da850 davinci CPU architecture. >> Information on these system may be found at http://www.hawkboard.org. >> Basic support for the UART console is included in this patch. >> It's tested with latest Angstrom File Systems like ramdisk >> from http://alturl.com/imb45. >> >> Signed-off-by: Victor Rodriguez >> --- >> Changes since v6: >> 1) Change commit reference >> 2) Remove hack that shut down UART1 because >> it is unused at present on the hawkboard. > > Thanks for removing this. > > Applying and queuing for 2.6.37 in davinci-next. Thanks , Is ok start to send the next patches for EMAC, EDMA, NAND and all the other modules? Bye the way I am a little bit lost with EMAC, I have tested it with ping but when i try to mount my FS by NFS it show kernel panic i will send a mail to the mailing list , but do you know how to search the patch that added EMAC support to board-da850-evm.c ? Thanks for all the help Sincerely yours Victor Rodriguez > Kevin > >> It shares pins with McASP0 transmit/receive master clock, >> opening UART1 will lead to a series of spurious interrupts. >> Some filesystems call getty on UART1 irrespective of whether >> it is console or not. On such filesystems, not shutting down >> UART1 causes boot-failure because of interrupt flood. >> >> Notes: >> >> This patch is checked with b8a24f38d6ee61b819f73ba53d51e3445314f0dc >> from Kernel development tree for TI DaVinci family of processors. >> This patch works with da8xx_omapl_defconfig plus this patch. >> --- >> ?arch/arm/configs/da8xx_omapl_defconfig ? ? ? ? ?| ? ?1 + >> ?arch/arm/mach-davinci/Kconfig ? ? ? ? ? ? ? ? ? | ? ?8 +++ >> ?arch/arm/mach-davinci/Makefile ? ? ? ? ? ? ? ? ?| ? ?1 + >> ?arch/arm/mach-davinci/board-omapl138-hawk.c ? ? | ? 64 +++++++++++++++++++++++ >> ?arch/arm/mach-davinci/include/mach/uncompress.h | ? ?1 + >> ?5 files changed, 75 insertions(+), 0 deletions(-) >> ?create mode 100644 arch/arm/mach-davinci/board-omapl138-hawk.c >> >> diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig >> index f8a47ee..cdc40c4 100644 >> --- a/arch/arm/configs/da8xx_omapl_defconfig >> +++ b/arch/arm/configs/da8xx_omapl_defconfig >> @@ -18,6 +18,7 @@ CONFIG_ARCH_DAVINCI=y >> ?CONFIG_ARCH_DAVINCI_DA830=y >> ?CONFIG_ARCH_DAVINCI_DA850=y >> ?CONFIG_MACH_MITYOMAPL138=y >> +CONFIG_MACH_OMAPL138_HAWKBOARD=y >> ?CONFIG_DAVINCI_RESET_CLOCKS=y >> ?CONFIG_NO_HZ=y >> ?CONFIG_HIGH_RES_TIMERS=y >> diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig >> index 9aca60c..b77b860 100644 >> --- a/arch/arm/mach-davinci/Kconfig >> +++ b/arch/arm/mach-davinci/Kconfig >> @@ -193,6 +193,14 @@ config MACH_MITYOMAPL138 >> ? ? ? ? System on Module. ?Information on this SoM may be found at >> ? ? ? ? http://www.mitydsp.com >> >> +config MACH_OMAPL138_HAWKBOARD >> + ? ? bool "TI AM1808 / OMAPL-138 Hawkboard platform" >> + ? ? depends on ARCH_DAVINCI_DA850 >> + ? ? help >> + ? ? ? Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard platform . >> + ? ? ? Information of this board may be found at >> + ? ? ? http://www.hawkboard.org/ >> + >> ?config DAVINCI_MUX >> ? ? ? bool "DAVINCI multiplexing support" >> ? ? ? depends on ARCH_DAVINCI >> diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile >> index a7a70d1..0b87a1c 100644 >> --- a/arch/arm/mach-davinci/Makefile >> +++ b/arch/arm/mach-davinci/Makefile >> @@ -34,6 +34,7 @@ obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) ? ? ? ?+= board-da830-evm.o >> ?obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o >> ?obj-$(CONFIG_MACH_TNETV107X) ? ? ? ? += board-tnetv107x-evm.o >> ?obj-$(CONFIG_MACH_MITYOMAPL138) ? ? ? ? ? ? ?+= board-mityomapl138.o >> +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) ? ? ? ?+= board-omapl138-hawk.o >> >> ?# Power Management >> ?obj-$(CONFIG_CPU_FREQ) ? ? ? ? ? ? ? ? ? ? ? += cpufreq.o >> diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c >> new file mode 100644 >> index 0000000..014876b >> --- /dev/null >> +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c >> @@ -0,0 +1,64 @@ >> +/* >> + * Hawkboard.org based on TI's OMAP-L138 Platform >> + * >> + * Initial code: Syed Mohammed Khasim >> + * >> + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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 >> +#include >> +#include >> +#include >> + >> +#include >> +#include >> + >> +#include >> +#include >> + >> +static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { >> + ? ? .enabled_uarts = 0x7, >> +}; >> + >> +static __init void omapl138_hawk_init(void) >> +{ >> + ? ? int ret; >> + >> + ? ? davinci_serial_init(&omapl138_hawk_uart_config); >> + >> + ? ? ret = da8xx_register_watchdog(); >> + ? ? if (ret) >> + ? ? ? ? ? ? pr_warning("omapl138_hawk_init: " >> + ? ? ? ? ? ? ? ? ? ? "watchdog registration failed: %d\n", >> + ? ? ? ? ? ? ? ? ? ? ret); >> +} >> + >> +#ifdef CONFIG_SERIAL_8250_CONSOLE >> +static int __init omapl138_hawk_console_init(void) >> +{ >> + ? ? if (!machine_is_omapl138_hawkboard()) >> + ? ? ? ? ? ? return 0; >> + >> + ? ? return add_preferred_console("ttyS", 2, "115200"); >> +} >> +console_initcall(omapl138_hawk_console_init); >> +#endif >> + >> +static void __init omapl138_hawk_map_io(void) >> +{ >> + ? ? da850_init(); >> +} >> + >> +MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") >> + ? ? .phys_io ? ? ? ?= IO_PHYS, >> + ? ? .io_pg_offst ? ?= (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, >> + ? ? .boot_params ? ?= (DA8XX_DDR_BASE + 0x100), >> + ? ? .map_io ? ? ? ? = omapl138_hawk_map_io, >> + ? ? .init_irq ? ? ? = cp_intc_init, >> + ? ? .timer ? ? ? ? ?= &davinci_timer, >> + ? ? .init_machine ? = omapl138_hawk_init, >> +MACHINE_END >> diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h b/arch/arm/mach-davinci/include/mach/uncompress.h >> index d370391..47723e8 100644 >> --- a/arch/arm/mach-davinci/include/mach/uncompress.h >> +++ b/arch/arm/mach-davinci/include/mach/uncompress.h >> @@ -89,6 +89,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) >> ? ? ? ? ? ? ? DEBUG_LL_DA8XX(davinci_da830_evm, ? ? ? 2); >> ? ? ? ? ? ? ? DEBUG_LL_DA8XX(davinci_da850_evm, ? ? ? 2); >> ? ? ? ? ? ? ? DEBUG_LL_DA8XX(mityomapl138, ? ? ? ? ? ?1); >> + ? ? ? ? ? ? DEBUG_LL_DA8XX(omapl138_hawkboard, ? ? ?2); >> >> ? ? ? ? ? ? ? /* TNETV107x boards */ >> ? ? ? ? ? ? ? DEBUG_LL_TNETV107X(tnetv107x, ? ? ? ? ? 1); > From nsekhar at ti.com Fri Sep 24 12:20:11 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Fri, 24 Sep 2010 22:50:11 +0530 Subject: [PATCH v7] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: References: <1285259320-2541-1-git-send-email-vm.rod25@gmail.com> <87lj6rkxu2.fsf@deeprootsystems.com> Message-ID: On Fri, Sep 24, 2010 at 20:38:43, Victor Rodriguez wrote: > > Bye the way I am a little bit lost with EMAC, I have tested it with > ping but when i try to mount my FS by NFS it show kernel panic i will > send a mail to the mailing list , but do you know how to search the > patch that added EMAC support to board-da850-evm.c ? git blame arch/arm/mach-davinci/board-da850-evm.c and look for commit-ids against emac support lines. Thanks, Sekhar From vm.rod25 at gmail.com Fri Sep 24 17:45:31 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Fri, 24 Sep 2010 17:45:31 -0500 Subject: Problem with EMAC conficuration Message-ID: Hi I have a problem, I have been tring to configure the EMAC for the Hawkboard, is is based on board -da850-evm.c but I can't make it works. The files system boots but give me this error Setting up IP spoofing protection: rp_filter. Configuring network interfaces... ifconfig: SIOCGIFFLAGS: No such device done. hwclock: can't open '/dev/misc/rtc': No such file or directory Tue Apr 14 20:24:00 UTC 2009 hwclock: can't open '/dev/misc/rtc': No such file or directory INIT: Entering runlevel: 5 Starting telnet daemon. Starting syslogd/klogd: done when i do the ifconfig root at hawkboard:~# ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) So the EMAC is not working The code ( patch ) is the next: #include #define DA850_EVM_PHY_ID "0:00 << 7" /* I look for in the datasheet of the LAN chip and said that the PHY ID Number is 0007 */ #define DA850_MII_MDIO_CLKEN_PIN GPIO_TO_PIN(2, 6) #ifdef CONFIG_DA850_UI_RMII static inline void omapl138_hawk_setup_emac_rmii(int rmii_sel) { struct davinci_soc_info *soc_info = &davinci_soc_info; soc_info->emac_pdata->rmii_en = 1; gpio_set_value(rmii_sel, 0); } #else static inline void omapl138_hawk_setup_emac_rmii(int rmii_sel) { } #endif static const short hawk_mii_pins[] = { DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3, DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER, DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3, DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK, DA850_MDIO_D, -1 }; static const short hawk_rmii_pins[] = { DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN, DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK, DA850_MDIO_D, -1 }; static int __init omapl138_hawk_config_emac(void) { void __iomem *cfg_chip3_base; int ret; u32 val; struct davinci_soc_info *soc_info = &davinci_soc_info; u8 rmii_en = soc_info->emac_pdata->rmii_en; if (!machine_is_davinci_da850_evm()) return 0; cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG); val = __raw_readl(cfg_chip3_base); //val &= ~BIT(8); if (rmii_en) { val |= BIT(8); ret = davinci_cfg_reg_list(hawk_rmii_pins); //ret = davinci_cfg_reg_list(da850_cpgmac_pins); pr_info("EMAC: RMII PHY configured, MII PHY will not be" " functional\n"); } else { val &= ~BIT(8); ret = davinci_cfg_reg_list(hawk_rmii_pins); //ret = davinci_cfg_reg_list(da850_cpgmac_pins); pr_info("EMAC: MII PHY configured, RMII PHY will not be" " functional\n"); } if (ret) pr_warning("hawk_init: cpgmac/rmii mux setup failed: %d\n", ret); /* configure the CFGCHIP3 register for RMII or MII */ __raw_writel(val, cfg_chip3_base); ret = davinci_cfg_reg(DA850_GPIO2_6); if (ret) pr_warning("hawk_init:GPIO(2,6) mux setup" "failed\n"); ret = gpio_request(DA850_MII_MDIO_CLKEN_PIN, "mdio_clk_en"); if (ret) { pr_warning("Cannot open GPIO %d\n", DA850_MII_MDIO_CLKEN_PIN); return ret; } /* Enable/Disable MII MDIO clock */ gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en); soc_info->emac_pdata->phy_id = DA850_EVM_PHY_ID; ret = da8xx_register_emac(); if (ret) pr_warning("hawk_init: emac registration failed: %d\n", ret); return 0; } device_initcall(omapl138_hawk_config_emac); Thanks for all your help Victor Rodriguez From michael.williamson at criticallink.com Fri Sep 24 19:11:20 2010 From: michael.williamson at criticallink.com (Michael Williamson) Date: Fri, 24 Sep 2010 20:11:20 -0400 Subject: Problem with EMAC conficuration In-Reply-To: References: Message-ID: <4C9D3E28.1070105@criticallink.com> Hi Victor, On 09/24/2010 06:45 PM, Victor Rodriguez wrote: [...] > > So the EMAC is not working > > The code ( patch ) is the next: > > > #include > > #define DA850_EVM_PHY_ID "0:00 << 7" > I thought the syntax for this was "0:07" or "MDIOBus:PhyAddr", so you would want "0:07". You might also just try leaving soc_info->emac_pdata->phy_id to null and letting the MDIO bus scan and use whatever it finds, as an experiment. > /* I look for in the datasheet of the LAN chip and said that the PHY > ID Number is 0007 */ > Unless you are programming it via the SPI port, the phy address gets for that part gets bootstrapped when you assert the reset line on the chip. I assume u-Boot is doing that, but it may not be. When that is asserted, you need to check what you are doing (pulling up, down, driving) to the lines connected to the PHYADn pins on the chip. That's how I read 3.7.1 of the LAN8710A spec. You might be getting random addresses assigned if the reset isn't being done. -Mike From caglarakyuz at gmail.com Sat Sep 25 00:30:32 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Sat, 25 Sep 2010 08:30:32 +0300 Subject: [PATCH v7] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: References: <1285259320-2541-1-git-send-email-vm.rod25@gmail.com> <87lj6rkxu2.fsf@deeprootsystems.com> Message-ID: <201009250830.32423.caglarakyuz@gmail.com> On Friday 24 September 2010 06:08:43 pm Victor Rodriguez wrote: > On Fri, Sep 24, 2010 at 9:41 AM, Kevin Hilman > > wrote: > > Victor Rodriguez writes: > >> This patch adds initial support for the Hawkboard-L138 system > >> It is under the machine name "omapl138_hawkboard". > >> This system is based on the da850 davinci CPU architecture. > >> Information on these system may be found at http://www.hawkboard.org. > >> Basic support for the UART console is included in this patch. > >> It's tested with latest Angstrom File Systems like ramdisk > >> from http://alturl.com/imb45. > >> > >> Signed-off-by: Victor Rodriguez > >> --- > >> Changes since v6: > >> 1) Change commit reference > >> 2) Remove hack that shut down UART1 because > >> it is unused at present on the hawkboard. > > > > Thanks for removing this. > > > > Applying and queuing for 2.6.37 in davinci-next. > > Thanks , Is ok start to send the next patches for EMAC, EDMA, NAND and > all the other modules? > > Bye the way I am a little bit lost with EMAC, I have tested it with > ping but when i try to mount my FS by NFS it show kernel panic i will > send a mail to the mailing list , but do you know how to search the > patch that added EMAC support to board-da850-evm.c ? > I have EMAC, EDMA, NAND, Audio, VGA, USB 1.1 and USB 2.0 working at the moment. You can see my patches at [1]. I've splitted all changes into branches for submitting different trees. What you can find in branches are: * hawk-board-code3: This branch is for Hawk related patches * soc-common: Changes needed in mach-davinci arch files for Hawkboard * da8xx-nand: NAND related changes, for linux-mtd * musb-da8xx2: For USB OTG, I will drop these when they are in mainline. * da8xx-fb: Framebuffer related changes, will go through fb tree. * asoc2: For audio, for alsa tree. These are based on rc2 still... Regards, Caglar [1] http://gitorious.org/linux-davinci-hawk > Thanks for all the help > > Sincerely yours > > Victor Rodriguez > > > Kevin > > > >> It shares pins with McASP0 transmit/receive master clock, > >> opening UART1 will lead to a series of spurious interrupts. > >> Some filesystems call getty on UART1 irrespective of whether > >> it is console or not. On such filesystems, not shutting down > >> UART1 causes boot-failure because of interrupt flood. > >> > >> Notes: > >> > >> This patch is checked with b8a24f38d6ee61b819f73ba53d51e3445314f0dc > >> from Kernel development tree for TI DaVinci family of processors. > >> This patch works with da8xx_omapl_defconfig plus this patch. > >> --- > >> arch/arm/configs/da8xx_omapl_defconfig | 1 + > >> arch/arm/mach-davinci/Kconfig | 8 +++ > >> arch/arm/mach-davinci/Makefile | 1 + > >> arch/arm/mach-davinci/board-omapl138-hawk.c | 64 > >> +++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/uncompress.h > >> | 1 + > >> 5 files changed, 75 insertions(+), 0 deletions(-) > >> create mode 100644 arch/arm/mach-davinci/board-omapl138-hawk.c > >> > >> diff --git a/arch/arm/configs/da8xx_omapl_defconfig > >> b/arch/arm/configs/da8xx_omapl_defconfig index f8a47ee..cdc40c4 100644 > >> --- a/arch/arm/configs/da8xx_omapl_defconfig > >> +++ b/arch/arm/configs/da8xx_omapl_defconfig > >> @@ -18,6 +18,7 @@ CONFIG_ARCH_DAVINCI=y > >> CONFIG_ARCH_DAVINCI_DA830=y > >> CONFIG_ARCH_DAVINCI_DA850=y > >> CONFIG_MACH_MITYOMAPL138=y > >> +CONFIG_MACH_OMAPL138_HAWKBOARD=y > >> CONFIG_DAVINCI_RESET_CLOCKS=y > >> CONFIG_NO_HZ=y > >> CONFIG_HIGH_RES_TIMERS=y > >> diff --git a/arch/arm/mach-davinci/Kconfig > >> b/arch/arm/mach-davinci/Kconfig index 9aca60c..b77b860 100644 > >> --- a/arch/arm/mach-davinci/Kconfig > >> +++ b/arch/arm/mach-davinci/Kconfig > >> @@ -193,6 +193,14 @@ config MACH_MITYOMAPL138 > >> System on Module. Information on this SoM may be found at > >> http://www.mitydsp.com > >> > >> +config MACH_OMAPL138_HAWKBOARD > >> + bool "TI AM1808 / OMAPL-138 Hawkboard platform" > >> + depends on ARCH_DAVINCI_DA850 > >> + help > >> + Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard > >> platform . + Information of this board may be found at > >> + http://www.hawkboard.org/ > >> + > >> config DAVINCI_MUX > >> bool "DAVINCI multiplexing support" > >> depends on ARCH_DAVINCI > >> diff --git a/arch/arm/mach-davinci/Makefile > >> b/arch/arm/mach-davinci/Makefile index a7a70d1..0b87a1c 100644 > >> --- a/arch/arm/mach-davinci/Makefile > >> +++ b/arch/arm/mach-davinci/Makefile > >> @@ -34,6 +34,7 @@ obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += > >> board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += > >> board-da850-evm.o > >> obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o > >> obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o > >> +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o > >> > >> # Power Management > >> obj-$(CONFIG_CPU_FREQ) += cpufreq.o > >> diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c > >> b/arch/arm/mach-davinci/board-omapl138-hawk.c new file mode 100644 > >> index 0000000..014876b > >> --- /dev/null > >> +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c > >> @@ -0,0 +1,64 @@ > >> +/* > >> + * Hawkboard.org based on TI's OMAP-L138 Platform > >> + * > >> + * Initial code: Syed Mohammed Khasim > >> + * > >> + * Copyright (C) 2009 Texas Instruments Incorporated - > >> http://www.ti.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 > >> +#include > >> +#include > >> +#include > >> + > >> +#include > >> +#include > >> + > >> +#include > >> +#include > >> + > >> +static struct davinci_uart_config omapl138_hawk_uart_config __initdata > >> = { + .enabled_uarts = 0x7, > >> +}; > >> + > >> +static __init void omapl138_hawk_init(void) > >> +{ > >> + int ret; > >> + > >> + davinci_serial_init(&omapl138_hawk_uart_config); > >> + > >> + ret = da8xx_register_watchdog(); > >> + if (ret) > >> + pr_warning("omapl138_hawk_init: " > >> + "watchdog registration failed: %d\n", > >> + ret); > >> +} > >> + > >> +#ifdef CONFIG_SERIAL_8250_CONSOLE > >> +static int __init omapl138_hawk_console_init(void) > >> +{ > >> + if (!machine_is_omapl138_hawkboard()) > >> + return 0; > >> + > >> + return add_preferred_console("ttyS", 2, "115200"); > >> +} > >> +console_initcall(omapl138_hawk_console_init); > >> +#endif > >> + > >> +static void __init omapl138_hawk_map_io(void) > >> +{ > >> + da850_init(); > >> +} > >> + > >> +MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") > >> + .phys_io = IO_PHYS, > >> + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, > >> + .boot_params = (DA8XX_DDR_BASE + 0x100), > >> + .map_io = omapl138_hawk_map_io, > >> + .init_irq = cp_intc_init, > >> + .timer = &davinci_timer, > >> + .init_machine = omapl138_hawk_init, > >> +MACHINE_END > >> diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h > >> b/arch/arm/mach-davinci/include/mach/uncompress.h index d370391..47723e8 > >> 100644 > >> --- a/arch/arm/mach-davinci/include/mach/uncompress.h > >> +++ b/arch/arm/mach-davinci/include/mach/uncompress.h > >> @@ -89,6 +89,7 @@ static inline void __arch_decomp_setup(unsigned long > >> arch_id) DEBUG_LL_DA8XX(davinci_da830_evm, 2); > >> DEBUG_LL_DA8XX(davinci_da850_evm, 2); > >> DEBUG_LL_DA8XX(mityomapl138, 1); > >> + DEBUG_LL_DA8XX(omapl138_hawkboard, 2); > >> > >> /* TNETV107x boards */ > >> DEBUG_LL_TNETV107X(tnetv107x, 1); > > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source at linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source > From windlazio at gmail.com Sat Sep 25 04:55:06 2010 From: windlazio at gmail.com (Han Jun-peng) Date: Sat, 25 Sep 2010 17:55:06 +0800 Subject: what is the meaning of INPSRC1 and INPSRC2 in IPIPEIF module of DM365? Message-ID: Hi,guys Now I am reading the vpfe datasheet of dm365,I find that the IPIPEIF of DM365 has a big difference with DM355's. I want to kown what is the real meaning of INPSRC1 and INPSRC2 in IPIPEIF module of DM365? I think the INPSRC1 is used to choose the data source for ISIF and the INPSRC2 is used to choose the data source of IPIPE,is it right? Anyone can help me to descripe the register more detailed. Thank you! -------------- next part -------------- An HTML attachment was scrubbed... URL: From ayildirim at aselsan.com.tr Sat Sep 25 07:55:47 2010 From: ayildirim at aselsan.com.tr (Alper YILDIRIM) Date: Sat, 25 Sep 2010 05:55:47 -0700 (PDT) Subject: UBI crashes / fixing NAND subpage writes In-Reply-To: <70E876B0EA86DD4BAF101844BC814DFE0903E02F56@Cloud.RL.local> References: <70E876B0EA86DD4BAF101844BC814DFE0903E02F56@Cloud.RL.local> Message-ID: <1285419347890-5569840.post@n2.nabble.com> Jon, i studied the davinci subpage write problem to find an applicable solution, but can not come up with a good idea. Your findings about the cause of the problem is totally correct but there is a question in my mind: Nand subpage support is added to the mainline kernel with this patch: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=29072b96078ffde36f03d51e6b5d0cff1ba8c7df link Since its in mainline i guess nand subpage support is working with other nand controllers, but not with davinci. There must be a way to solve this problem within the davinci_nand.c driver without touching the main nand API's. What is your opinion? Regards, Alper YILDIRIM -- View this message in context: http://davinci-linux-open-source.1494791.n2.nabble.com/UBI-crashes-fixing-NAND-subpage-writes-tp5485828p5569840.html Sent from the davinci-linux-open-source mailing list archive at Nabble.com. From ayildirim at aselsan.com.tr Sat Sep 25 08:34:43 2010 From: ayildirim at aselsan.com.tr (Alper YILDIRIM) Date: Sat, 25 Sep 2010 06:34:43 -0700 (PDT) Subject: [PATCH v7] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <1285259320-2541-1-git-send-email-vm.rod25@gmail.com> References: <1285259320-2541-1-git-send-email-vm.rod25@gmail.com> Message-ID: <1285421683201-5569892.post@n2.nabble.com> Victor Rodriguez wrote: > > This patch works with da8xx_omapl_defconfig plus this patch. > I think, it would be nicer to have a different defconfig file for hawkboard. -- View this message in context: http://davinci-linux-open-source.1494791.n2.nabble.com/PATCH-v7-davinci-Initial-support-for-Omapl138-Hawkboard-tp5563740p5569892.html Sent from the davinci-linux-open-source mailing list archive at Nabble.com. From sugumar at ti.com Sun Sep 26 23:44:41 2010 From: sugumar at ti.com (Sugumar Natarajan) Date: Mon, 27 Sep 2010 10:14:41 +0530 Subject: [PATCH v5 1/4] davinci: Add generic PWM support for PWM control In-Reply-To: <87vd5zp3qz.fsf@deeprootsystems.com> References: <1284968386-16898-1-git-send-email-sugumar@ti.com> <8762y0ur8s.fsf@deeprootsystems.com> <016a01cb597c$8ee462a0$acad27e0$@com> <87vd5zp3qz.fsf@deeprootsystems.com> Message-ID: <000c01cb5dfe$b32e1850$198a48f0$@com> On Tue, Sep 21, 2010 at 20:01:32, Kevin Hilman wrote: > "Sugumar Natarajan" writes: > > > Kevin, > > > > On Tue, Sep 21, 2010 at 01:22:51, Kevin Hilman wrote: > >> Sugumar Natarajan writes: > >> > >> > This patch adds generic PWM support where it maintains the list of > >> > PWM control devices that can be added or removed. > >> > > >> > The interface provides a list of functions that can be accessed by > >> > the PWM control driver module and the generic PWM driver. > >> > > >> > The PWM control driver module such as eCAP uses the interface to > >> > register and add itself to the list as a PWM control device. > >> > The generic PWM driver uses the interface to search for a PWM > >> > control device and if present, uses the device for PWM control. > >> > > >> > Signed-off-by: Sugumar Natarajan > >> > --- > >> > Changes since v4: > >> > a) pwm_enable and pwm_disable function implementation have been modified, > >> > such that the actual implementation is done by the corresponding driver, > >> > and these functions would just make a callback. > >> > >> Would it make sense for the core to directly manage the clocks if the > >> driver has not provided its own enable/disable hooks? I > > guess that would slightly simplify simple users. > > > > Of course yes. But, the driver code would undergo few changes if the > > clk_enable/clk_disable function is implemented. Please see below > > > > > >> > >> Now that I say that, I noticed the eCAP driver no longer touches the clocks in its own enable/disable hooks. Why? > > Clock enable/disable function implementation requires few changes in > > the driver code. Clock_enable function has to be called every time > > before writing into the registers. This is needed as pwm_config > > function could be called with the clock disabled. This condition > > arises when the backlight driver receives 0% duty cycle. > > At this time, the backlight driver calls the pwm_disable function. > > Since the clock is disabled now, if the pwm_config fuction is called > > again, no read/write access would actually happen. > > > > I have implemented the enable/disable function in the previous patch. > > This had resulted in inclusion of clk_enable and clk_disable function. > > I had to also incorporate an extra random delay for the ecap driver to > > function properly. To avoid this delay, clk_enable/clk_disable > > function implementation has been removed. In the present > > implementation, clk_enable and clk_disable function are called only > > during probe and remove respectively. > > > Please see the code snippet below. > > > > From davinci_pwm.c > > > > int pwm_enable(struct pwm_device *pwm) { > > int rc = 0; > > if (WARN_ON(!pwm)) > > return -EINVAL; > > if (!pwm->clk_enabled) { > > rc = clk_enable(pwm->clk); > > if (!rc) > > pwm->clk_enabled = 1; > > } > > return rc; > > } > > > > From ecap.c, > > > > static int ecap_pwm_config(struct pwm_device *pwm, unsigned int > > period_cycles, > > + unsigned int duty_cycle) > > { > > clk_enable(pwm->clock); > > > > __raw_writew(); > > > > mdelay(10); > > > > clk_disable(pwm->clock); > > > > } > > > > AFAIK, pwm_enable / pwm_disable function are used to start / stop the > > pwm output and relies heavily on the driver capabilities. > > > > Why should the clk_enable and clk_disable be called if the driver does > > not support the above feature? Why can't it simply return instead? > > The problem is a power-management problem. A module should only be clocked when needed. Currently, you clock the module on problem and disable clocks on remove. The result is the that the module is clocked, even if there are no PWM users. > > If the clock is needed only for register writes, then that's all it should be enabled for. > > The need for such a long delay needs to be investigated and clearly described in the changelog. > > Is the delay needed between the clock enable and writing to the module? > or is it needed between a module access and a clock disable. > > Either way, I expect there is way to handle this in SW without needed a delay. Kevin, I am currently working with the hardware team to try and remove this delay. Regards, N.Sugumar > Kevin > From pjohn at mvista.com Mon Sep 27 07:40:05 2010 From: pjohn at mvista.com (Philby John) Date: Mon, 27 Sep 2010 18:10:05 +0530 Subject: [PATCH 6/6] i2c: davinci: bus recovery procedure to clear the bus In-Reply-To: References: <1264549293-25556-1-git-send-email-khilman@deeprootsystems.com> <1264549293-25556-7-git-send-email-khilman@deeprootsystems.com> Message-ID: <1285591205.3643.63.camel@localhost.localdomain> Hello Pablo, On Mon, 2010-09-13 at 16:23 +0200, Pablo Bitton wrote: > Hi Philby, > i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev, > char allow_sleep) > { > unsigned long timeout; > + static u16 to_cnt; > > timeout = jiffies + dev->adapter.timeout; > while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) > & DAVINCI_I2C_STR_BB) { > - if (time_after(jiffies, timeout)) { > - dev_warn(dev->dev, > - "timeout waiting for bus > ready\n"); > - return -ETIMEDOUT; > + if (to_cnt <= DAVINCI_I2C_MAX_TRIES) { > + if (time_after(jiffies, timeout)) { > + dev_warn(dev->dev, > + "timeout waiting for bus ready > \n"); > + to_cnt++; > + return -ETIMEDOUT; > + } else { > + to_cnt = 0; > + i2c_recover_bus(dev); > + i2c_davinci_init(dev); > + } > } > if (allow_sleep) > schedule_timeout(1); > > The resulting loop has the following drawbacks: > 1) If to_cnt reaches DAVINCI_I2C_MAX_TRIES+1 (which it currently > can't, see 2) and the i2c bus collapses, > the kernel will be stuck in the loop forever, especially if > allow_sleep is false. I do not understand how to_cnt can reach DAVINCI_I2C_MAX_TRIES+1. You seem to be contradicting your own statement, you also say that this cannot happen!! > 2) The to_cnt static var never increments beyond 1. Precisely. > It's initialized to zero and then kept at zero until the timeout > expires. > When the timeout expires, to_cnt is incremented once, until the > next call to the function, where it will be zeroed again. How then can your 1st assumption hold good? > 3) Do we really want to retry recovering the bus thousands of times, > until the timeout arrives? > It seems to me that if the bus recovery procedure didn't help > after one or two tries, it probably never will. Once a bus recovery is initiated, we are in the last phase of a recovery and if that fails the user is left with no other choice but to reset the target. From the very beginning the idea was to try until timeout. Wouldn't you have a working system rather than to have to reset the target? > > > I also have the following nitpicks: > a) The timeout variable actually holds the finish time. Well, that's just aesthetic makeover. I could say the timeout is 10 seconds and the finish time is 10 seconds, it sounds the same to me. > b) The i2c_recover_bus function uses dev_err to report a bus recovery > process, > but if all recovery attempts failed and the timeout was reached, > only dev_warn is used to report the timeout. Agreed. But your patch does not reflect this change. > > > Other than that the patch is very helpful, thanks a lot. > > > Below is my suggestion for the wait_bus_not_busy function. My patch > has been tested on a DM6446. All in all, your patch gives multiple checkpatch errors/warnings (spaces instead of tabs etc). You have missed out parts of the code present in the pristine kernel and so will not cleanly apply. To me, there are two things that are of interest in your patch. First is you got rid of the static variable definition and the other is usage of dev_err. I fail to understand your assumption that the "kernel will be stuck in the loop forever", hence I cannot tell how useful this patch really is. > > > Signed-off-by: Pablo Bitton > -- > diff --git a/drivers/i2c/busses/i2c-davinci.c > b/drivers/i2c/busses/i2c-davinci.c > --- a/drivers/i2c/busses/i2c-davinci.c > +++ b/drivers/i2c/busses/i2c-davinci.c > > > > > > @@ -220,16 +261,24 @@ static int i2c_davinci_init(struct > davinci_i2c_dev *dev) > static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev, > char allow_sleep) > { > - unsigned long timeout; > + unsigned long finish_time; You have missed out on this line static u16 to_cnt; > + unsigned long to_cnt = 0; > > - timeout = jiffies + dev->adapter.timeout; > + finish_time = jiffies + dev->adapter.timeout; > + /* While bus busy */ > while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) > & DAVINCI_I2C_STR_BB) { Your patch misses out on this line. if (to_cnt <= DAVINCI_I2C_MAX_TRIES) { Shouldn't you show removing it in the patch? > - if (time_after(jiffies, timeout)) { > + if (time_after(jiffies, finish_time)) { > dev_warn(dev->dev, > "timeout waiting for bus ready\n"); This is the part where the bus recover procedure would have failed. In this case we could use dev_err here instead of in the function i2c_recover_bus(). Also this line.. to_cnt++; is missing from your patch. You should show that you are removing it. > return -ETIMEDOUT; > } > + else if (to_cnt <= DAVINCI_I2C_MAX_TRIES) { > + dev_warn(dev->dev, "bus busy, performing bus > recovery\n"); There is already a warning in the function i2c_recover_bus(). This can be removed? > + ++to_cnt; Can we stick to to_cnt++; ? > + i2c_recover_bus(dev); > + i2c_davinci_init(dev); > + } > if (allow_sleep) > schedule_timeout(1); > } Regards, Philby From cyril at ti.com Mon Sep 27 08:25:07 2010 From: cyril at ti.com (Cyril Chemparathy) Date: Mon, 27 Sep 2010 09:25:07 -0400 Subject: Problem with EMAC conficuration In-Reply-To: References: Message-ID: <4CA09B33.5040308@ti.com> Hi Victor, On 09/24/2010 06:45 PM, Victor Rodriguez wrote: > Hi I have a problem, I have been tring to configure the EMAC for the > Hawkboard, is is based on board -da850-evm.c but I can't make it > works. The files system boots but give me this error > [...] > > #define DA850_EVM_PHY_ID "0:00 << 7" I am pretty certain a bus id is expected here. Please use "0:07" instead of the shift. Next, please look for mdio messages ensure that the phys probed properly. Thanks Cyril. From khilman at deeprootsystems.com Mon Sep 27 09:16:41 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Mon, 27 Sep 2010 07:16:41 -0700 Subject: [PATCH v4] i2c: davinci: Fix race when setting up for TX In-Reply-To: <20100924163754.GH27885@trinity.fluff.org> (Ben Dooks's message of "Fri, 24 Sep 2010 17:37:54 +0100") References: <4C97CEC9.8060602@boundarydevices.com> <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> <87sk0zky28.fsf@deeprootsystems.com> <20100924163754.GH27885@trinity.fluff.org> Message-ID: <87sk0vuv92.fsf@deeprootsystems.com> Ben Dooks writes: > On Fri, Sep 24, 2010 at 07:37:03AM -0700, Kevin Hilman wrote: >> "Sudhakar Rajashekhara" writes: >> >> > On Tue, Sep 21, 2010 at 09:43:28, Jon Povey wrote: >> >> When setting up to transmit, a race exists between the ISR and >> >> i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. >> >> This is mostly visible for transmits > 1 byte long. >> >> >> >> The hardware starts sending immediately that MDR.STT is set. IMR trickery >> >> doesn't work because if we start sending, finish the first byte and an >> >> XRDY event occurs before we load IMR to unmask it, we never get an >> >> interrupt, and we timeout. >> >> >> >> Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode >> >> settings before DXR for correct behaviour, so load MDR first with >> >> STT cleared and later load again with STT set. >> >> >> >> Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 >> >> >> >> Signed-off-by: Jon Povey >> >> CC: Sudhakar Rajashekhara >> >> CC: Troy Kisky >> >> --- >> > >> > Tested-by: Sudhakar Rajashekhara >> > >> > Tested with audio loopback on OMAP-L138, OMAP-L137 and DM365. Also tested with >> > i2cdetect function which probes all the devices on the i2c bus. >> >> >> Ben, can you queue this one for 2.6.37 with the addition of: > > If it is a worthwhile bugfix i'll send it for the next -rc. OK, yeah. It's probably better to queue for the next -rc. Thanks, Kevin From vm.rod25 at gmail.com Mon Sep 27 09:31:31 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Mon, 27 Sep 2010 09:31:31 -0500 Subject: [PATCH v7] davinci: Initial support for Omapl138-Hawkboard In-Reply-To: <201009250830.32423.caglarakyuz@gmail.com> References: <1285259320-2541-1-git-send-email-vm.rod25@gmail.com> <87lj6rkxu2.fsf@deeprootsystems.com> <201009250830.32423.caglarakyuz@gmail.com> Message-ID: On Sat, Sep 25, 2010 at 12:30 AM, Caglar Akyuz wrote: > On Friday 24 September 2010 06:08:43 pm Victor Rodriguez wrote: >> On Fri, Sep 24, 2010 at 9:41 AM, Kevin Hilman >> >> wrote: >> > Victor Rodriguez writes: >> >> This patch adds initial support for the Hawkboard-L138 system >> >> It is under the machine name "omapl138_hawkboard". >> >> This system is based on the da850 davinci CPU architecture. >> >> Information on these system may be found at http://www.hawkboard.org. >> >> Basic support for the UART console is included in this patch. >> >> It's tested with latest Angstrom File Systems like ramdisk >> >> from http://alturl.com/imb45. >> >> >> >> Signed-off-by: Victor Rodriguez >> >> --- >> >> Changes since v6: >> >> 1) Change commit reference >> >> 2) Remove hack that shut down UART1 because >> >> it is unused at present on the hawkboard. >> > >> > Thanks for removing this. >> > >> > Applying and queuing for 2.6.37 in davinci-next. >> >> Thanks , Is ok start to send the next patches for EMAC, EDMA, NAND and >> all the other modules? >> >> Bye the way I am a little bit lost with EMAC, I have tested it with >> ping but when i try to mount my FS by NFS it show kernel panic i will >> send a mail to the mailing list , but do you know how to search the >> patch that added EMAC support to board-da850-evm.c ? >> > > I have EMAC, EDMA, NAND, Audio, VGA, USB 1.1 and USB 2.0 working at the > moment. You can see my patches at [1]. I've splitted all changes into branches > for submitting different trees. What you can find in branches are: > > * hawk-board-code3: ? ? This branch is for Hawk related patches > * soc-common: Changes needed in mach-davinci arch files for Hawkboard > * da8xx-nand: NAND related changes, for linux-mtd > * musb-da8xx2: For USB OTG, I will drop these when they are in mainline. > * da8xx-fb: Framebuffer related changes, will go through fb tree. > * asoc2: For audio, for alsa tree. > > These are based on rc2 still... > > Regards, > Caglar > > [1] http://gitorious.org/linux-davinci-hawk Hi Caglar glad to hear that you already have those patches, in order to avoid double effort, would you like to send the patches to the mailing list on the latest rc?. We could give the complete support for Hawkboard, just tell me which patches are you working right now and i will start to work with the rest. Thanks for all. Sincerely yours Victor Rodriguez >> Thanks for all the help >> >> Sincerely yours >> >> Victor Rodriguez >> >> > Kevin >> > >> >> It shares pins with McASP0 transmit/receive master clock, >> >> opening UART1 will lead to a series of spurious interrupts. >> >> Some filesystems call getty on UART1 irrespective of whether >> >> it is console or not. On such filesystems, not shutting down >> >> UART1 causes boot-failure because of interrupt flood. >> >> >> >> Notes: >> >> >> >> This patch is checked with b8a24f38d6ee61b819f73ba53d51e3445314f0dc >> >> from Kernel development tree for TI DaVinci family of processors. >> >> This patch works with da8xx_omapl_defconfig plus this patch. >> >> --- >> >> ?arch/arm/configs/da8xx_omapl_defconfig ? ? ? ? ?| ? ?1 + >> >> ?arch/arm/mach-davinci/Kconfig ? ? ? ? ? ? ? ? ? | ? ?8 +++ >> >> ?arch/arm/mach-davinci/Makefile ? ? ? ? ? ? ? ? ?| ? ?1 + >> >> ?arch/arm/mach-davinci/board-omapl138-hawk.c ? ? | ? 64 >> >> +++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/uncompress.h >> >> | ? ?1 + >> >> ?5 files changed, 75 insertions(+), 0 deletions(-) >> >> ?create mode 100644 arch/arm/mach-davinci/board-omapl138-hawk.c >> >> >> >> diff --git a/arch/arm/configs/da8xx_omapl_defconfig >> >> b/arch/arm/configs/da8xx_omapl_defconfig index f8a47ee..cdc40c4 100644 >> >> --- a/arch/arm/configs/da8xx_omapl_defconfig >> >> +++ b/arch/arm/configs/da8xx_omapl_defconfig >> >> @@ -18,6 +18,7 @@ CONFIG_ARCH_DAVINCI=y >> >> ?CONFIG_ARCH_DAVINCI_DA830=y >> >> ?CONFIG_ARCH_DAVINCI_DA850=y >> >> ?CONFIG_MACH_MITYOMAPL138=y >> >> +CONFIG_MACH_OMAPL138_HAWKBOARD=y >> >> ?CONFIG_DAVINCI_RESET_CLOCKS=y >> >> ?CONFIG_NO_HZ=y >> >> ?CONFIG_HIGH_RES_TIMERS=y >> >> diff --git a/arch/arm/mach-davinci/Kconfig >> >> b/arch/arm/mach-davinci/Kconfig index 9aca60c..b77b860 100644 >> >> --- a/arch/arm/mach-davinci/Kconfig >> >> +++ b/arch/arm/mach-davinci/Kconfig >> >> @@ -193,6 +193,14 @@ config MACH_MITYOMAPL138 >> >> ? ? ? ? System on Module. ?Information on this SoM may be found at >> >> ? ? ? ? http://www.mitydsp.com >> >> >> >> +config MACH_OMAPL138_HAWKBOARD >> >> + ? ? bool "TI AM1808 / OMAPL-138 Hawkboard platform" >> >> + ? ? depends on ARCH_DAVINCI_DA850 >> >> + ? ? help >> >> + ? ? ? Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard >> >> platform . + ? ? ? Information of this board may be found at >> >> + ? ? ? http://www.hawkboard.org/ >> >> + >> >> ?config DAVINCI_MUX >> >> ? ? ? bool "DAVINCI multiplexing support" >> >> ? ? ? depends on ARCH_DAVINCI >> >> diff --git a/arch/arm/mach-davinci/Makefile >> >> b/arch/arm/mach-davinci/Makefile index a7a70d1..0b87a1c 100644 >> >> --- a/arch/arm/mach-davinci/Makefile >> >> +++ b/arch/arm/mach-davinci/Makefile >> >> @@ -34,6 +34,7 @@ obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) ? ? ? ?+= >> >> board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += >> >> board-da850-evm.o >> >> ?obj-$(CONFIG_MACH_TNETV107X) ? ? ? ? += board-tnetv107x-evm.o >> >> ?obj-$(CONFIG_MACH_MITYOMAPL138) ? ? ? ? ? ? ?+= board-mityomapl138.o >> >> +obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) ? ? ? ?+= board-omapl138-hawk.o >> >> >> >> ?# Power Management >> >> ?obj-$(CONFIG_CPU_FREQ) ? ? ? ? ? ? ? ? ? ? ? += cpufreq.o >> >> diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c >> >> b/arch/arm/mach-davinci/board-omapl138-hawk.c new file mode 100644 >> >> index 0000000..014876b >> >> --- /dev/null >> >> +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c >> >> @@ -0,0 +1,64 @@ >> >> +/* >> >> + * Hawkboard.org based on TI's OMAP-L138 Platform >> >> + * >> >> + * Initial code: Syed Mohammed Khasim >> >> + * >> >> + * Copyright (C) 2009 Texas Instruments Incorporated - >> >> http://www.ti.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 >> >> +#include >> >> +#include >> >> +#include >> >> + >> >> +#include >> >> +#include >> >> + >> >> +#include >> >> +#include >> >> + >> >> +static struct davinci_uart_config omapl138_hawk_uart_config __initdata >> >> = { + ? ? .enabled_uarts = 0x7, >> >> +}; >> >> + >> >> +static __init void omapl138_hawk_init(void) >> >> +{ >> >> + ? ? int ret; >> >> + >> >> + ? ? davinci_serial_init(&omapl138_hawk_uart_config); >> >> + >> >> + ? ? ret = da8xx_register_watchdog(); >> >> + ? ? if (ret) >> >> + ? ? ? ? ? ? pr_warning("omapl138_hawk_init: " >> >> + ? ? ? ? ? ? ? ? ? ? "watchdog registration failed: %d\n", >> >> + ? ? ? ? ? ? ? ? ? ? ret); >> >> +} >> >> + >> >> +#ifdef CONFIG_SERIAL_8250_CONSOLE >> >> +static int __init omapl138_hawk_console_init(void) >> >> +{ >> >> + ? ? if (!machine_is_omapl138_hawkboard()) >> >> + ? ? ? ? ? ? return 0; >> >> + >> >> + ? ? return add_preferred_console("ttyS", 2, "115200"); >> >> +} >> >> +console_initcall(omapl138_hawk_console_init); >> >> +#endif >> >> + >> >> +static void __init omapl138_hawk_map_io(void) >> >> +{ >> >> + ? ? da850_init(); >> >> +} >> >> + >> >> +MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard") >> >> + ? ? .phys_io ? ? ? ?= IO_PHYS, >> >> + ? ? .io_pg_offst ? ?= (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, >> >> + ? ? .boot_params ? ?= (DA8XX_DDR_BASE + 0x100), >> >> + ? ? .map_io ? ? ? ? = omapl138_hawk_map_io, >> >> + ? ? .init_irq ? ? ? = cp_intc_init, >> >> + ? ? .timer ? ? ? ? ?= &davinci_timer, >> >> + ? ? .init_machine ? = omapl138_hawk_init, >> >> +MACHINE_END >> >> diff --git a/arch/arm/mach-davinci/include/mach/uncompress.h >> >> b/arch/arm/mach-davinci/include/mach/uncompress.h index d370391..47723e8 >> >> 100644 >> >> --- a/arch/arm/mach-davinci/include/mach/uncompress.h >> >> +++ b/arch/arm/mach-davinci/include/mach/uncompress.h >> >> @@ -89,6 +89,7 @@ static inline void __arch_decomp_setup(unsigned long >> >> arch_id) DEBUG_LL_DA8XX(davinci_da830_evm, ? ? ? 2); >> >> ? ? ? ? ? ? ? DEBUG_LL_DA8XX(davinci_da850_evm, ? ? ? 2); >> >> ? ? ? ? ? ? ? DEBUG_LL_DA8XX(mityomapl138, ? ? ? ? ? ?1); >> >> + ? ? ? ? ? ? DEBUG_LL_DA8XX(omapl138_hawkboard, ? ? ?2); >> >> >> >> ? ? ? ? ? ? ? /* TNETV107x boards */ >> >> ? ? ? ? ? ? ? DEBUG_LL_TNETV107X(tnetv107x, ? ? ? ? ? 1); >> >> _______________________________________________ >> Davinci-linux-open-source mailing list >> Davinci-linux-open-source at linux.davincidsp.com >> http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source >> > From vm.rod25 at gmail.com Mon Sep 27 11:30:10 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Mon, 27 Sep 2010 11:30:10 -0500 Subject: Problem with EMAC conficuration In-Reply-To: <4CA09B33.5040308@ti.com> References: <4CA09B33.5040308@ti.com> Message-ID: On Mon, Sep 27, 2010 at 8:25 AM, Cyril Chemparathy wrote: > Hi Victor, > > On 09/24/2010 06:45 PM, Victor Rodriguez wrote: >> Hi I have a problem, I have been tring to configure the EMAC for the >> Hawkboard, is is based on board -da850-evm.c but I can't make it >> works. The files system boots but give me this error >> > [...] >> >> #define DA850_EVM_PHY_ID ? ? ? ? ? ? ?"0:00 << 7" > > I am pretty certain a bus id is expected here. ?Please use "0:07" > instead of the shift. > > Next, please look for mdio messages ensure that the phys probed properly. > > Thanks > Cyril. > _______________________________________________ > Davinci-linux-open-source mailing list > Davinci-linux-open-source at linux.davincidsp.com > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source > Thanks Cyril and Michael, It works. Now I have the patch ready for Ethernet and NFS for Hawkboard in the latest rc. I have tested with ifconfig, ping and mounting a FS by NFS. Caglar the patch is different form your patch in [1], would be OK if I submit it ? I have attached my patch please tell me if it is ok for you if i send the patch, I have been working with all the other patches for complete support but always with the latest rc. except for USB. Thanks for all Sincerely yours Victor Rodriguez [1] http://gitorious.org/linux-davinci-hawk/linux-davinci-hawk/commit/3712194f2e674cc46cc076cb009c2530b4d46a63 -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-davinci-EMAC-support-for-Omapl138-Hawkboard.patch Type: text/x-patch Size: 3458 bytes Desc: not available URL: From caglarakyuz at gmail.com Mon Sep 27 12:13:23 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Mon, 27 Sep 2010 20:13:23 +0300 Subject: Problem with EMAC conficuration In-Reply-To: References: <4CA09B33.5040308@ti.com> Message-ID: <201009272013.23201.caglarakyuz@gmail.com> On Monday 27 September 2010 07:30:10 pm Victor Rodriguez wrote: > On Mon, Sep 27, 2010 at 8:25 AM, Cyril Chemparathy wrote: > > Hi Victor, > > > > On 09/24/2010 06:45 PM, Victor Rodriguez wrote: > >> Hi I have a problem, I have been tring to configure the EMAC for the > >> Hawkboard, is is based on board -da850-evm.c but I can't make it > >> works. The files system boots but give me this error > > > > [...] > > > >> #define DA850_EVM_PHY_ID "0:00 << 7" > > > > I am pretty certain a bus id is expected here. Please use "0:07" > > instead of the shift. > > > > Next, please look for mdio messages ensure that the phys probed properly. > > > > Thanks > > Cyril. > > _______________________________________________ > > Davinci-linux-open-source mailing list > > Davinci-linux-open-source at linux.davincidsp.com > > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source > > Thanks Cyril and Michael, It works. > > Now I have the patch ready for Ethernet and NFS for Hawkboard in the > latest rc. I have tested with ifconfig, ping and mounting a FS by NFS. > Caglar the patch is different form your patch in [1], would be OK if I > submit it ? > > I have attached my patch please tell me if it is ok for you if i send > the patch, I have been working with all the other patches for complete > support but always with the latest rc. except for USB. > Please go and submit it. Some comments though... * I doubt RMII wil be used on this board, should we really add support for it? * GPIO2_6 is not used on this board, no need to request gpio. * Inline patches please :) Regards, Caglar > Thanks for all > > Sincerely yours > > Victor Rodriguez > > [1] > http://gitorious.org/linux-davinci-hawk/linux-davinci-hawk/commit/3712194f > 2e674cc46cc076cb009c2530b4d46a63 > From nsekhar at ti.com Mon Sep 27 12:35:57 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Mon, 27 Sep 2010 23:05:57 +0530 Subject: [PATCH v5 1/1] davinci: spi: replace existing driver In-Reply-To: <4C979D1D.1070707@criticallink.com> References: <1280355490-11878-1-git-send-email-bniebuhr@efjohnson.com> <4C8EB795.1080607@criticallink.com> <201009140904.59555.caglarakyuz@gmail.com> <4C8F7460.6050006@criticallink.com> <4C94B9BD.4010606@criticallink.com> <4C979D1D.1070707@criticallink.com> Message-ID: Hi Mike, On Mon, Sep 20, 2010 at 23:12:53, Michael Williamson wrote: > > Let me know if you want testing on the DMA portion of the patch (when your ready, of course). > I just got back to this last Friday. Will let you know once done. Meanwhile I added your Tested-By: to the existing patches. Thanks for testing. Regards, Sekhar From vm.rod25 at gmail.com Mon Sep 27 14:10:15 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Mon, 27 Sep 2010 14:10:15 -0500 Subject: Problem with EMAC conficuration In-Reply-To: <201009272013.23201.caglarakyuz@gmail.com> References: <4CA09B33.5040308@ti.com> <201009272013.23201.caglarakyuz@gmail.com> Message-ID: On Mon, Sep 27, 2010 at 12:13 PM, Caglar Akyuz wrote: > On Monday 27 September 2010 07:30:10 pm Victor Rodriguez wrote: >> On Mon, Sep 27, 2010 at 8:25 AM, Cyril Chemparathy wrote: >> > Hi Victor, >> > >> > On 09/24/2010 06:45 PM, Victor Rodriguez wrote: >> >> Hi I have a problem, I have been tring to configure the EMAC for the >> >> Hawkboard, is is based on board -da850-evm.c but I can't make it >> >> works. The files system boots but give me this error >> > >> > [...] >> > >> >> #define DA850_EVM_PHY_ID ? ? ? ? ? ? ?"0:00 << 7" >> > >> > I am pretty certain a bus id is expected here. ?Please use "0:07" >> > instead of the shift. >> > >> > Next, please look for mdio messages ensure that the phys probed properly. >> > >> > Thanks >> > Cyril. >> > _______________________________________________ >> > Davinci-linux-open-source mailing list >> > Davinci-linux-open-source at linux.davincidsp.com >> > http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source >> >> Thanks Cyril and Michael, It works. >> >> Now I have the patch ready for Ethernet and NFS for Hawkboard in the >> latest rc. I have tested with ifconfig, ping and mounting a FS by NFS. >> Caglar the patch is different form your patch in [1], would be OK if I >> submit it ? >> >> I have attached my patch please tell me if it is ok for you if i send >> the patch, I have been working with all the other patches for complete >> support but always with the latest rc. except for USB. >> > > Please go and submit it. Some comments though... > > * I doubt RMII wil be used on this board, should we really add support for it? > * GPIO2_6 is not used on this board, no need to request gpio. Thanks for the observation I will fix it > * Inline patches please :) What do you mean with In line ? Sorry i do not understand the meaning ? Thanks for all Sincerely yours Victor Rodriguez > > Regards, > Caglar > >> Thanks for all >> >> Sincerely yours >> >> Victor Rodriguez >> >> [1] >> ?http://gitorious.org/linux-davinci-hawk/linux-davinci-hawk/commit/3712194f >> 2e674cc46cc076cb009c2530b4d46a63 >> > From vm.rod25 at gmail.com Mon Sep 27 14:41:07 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Mon, 27 Sep 2010 14:41:07 -0500 Subject: [PATCH v1] davinci: EMAC support for Omapl138-Hawkboard Message-ID: <1285616467-31955-1-git-send-email-vm.rod25@gmail.com> From: Victor Rodriguez This patch adds EMAC support for the Hawkboard-L138 system It is under the machine name "omapl138_hawkboard". This system is based on the da850 davinci CPU architecture. Signed-off-by: Victor Rodriguez --- arch/arm/mach-davinci/board-omapl138-hawk.c | 49 +++++++++++++++++++++++++++ 1 files changed, 49 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c index c472dd8..fd1f458 100644 --- a/arch/arm/mach-davinci/board-omapl138-hawk.c +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c @@ -19,6 +19,55 @@ #include #include +#include + +#define DA850_EVM_PHY_ID "0:07" + +static const short hawk_mii_pins[] = { + DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3, + DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER, + DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3, + DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK, + DA850_MDIO_D, + -1 +}; + +static int __init omapl138_hawk_config_emac(void) +{ + void __iomem *cfg_chip3_base; + int ret; + u32 val; + struct davinci_soc_info *soc_info = &davinci_soc_info; + + if (!machine_is_omapl138_hawkboard()) + return 0; + + cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG); + + val = __raw_readl(cfg_chip3_base); + + val &= ~BIT(8); + ret = davinci_cfg_reg_list(hawk_mii_pins); + pr_info("EMAC: MII PHY configured, RMII PHY will not be" + " functional\n"); + + if (ret) + pr_warning("hawk_init: cpgmac/rmii mux setup failed: %d\n", + ret); + + /* configure the CFGCHIP3 register for MII */ + __raw_writel(val, cfg_chip3_base); + + /* Enable/Disable MII MDIO clock */ + soc_info->emac_pdata->phy_id = DA850_EVM_PHY_ID; + + ret = da8xx_register_emac(); + if (ret) + pr_warning("hawk_init: emac registration failed: %d\n", + ret); + return 0; +} +device_initcall(omapl138_hawk_config_emac); static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { .enabled_uarts = 0x7, -- 1.6.0.5 From vm.rod25 at gmail.com Mon Sep 27 20:11:49 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Mon, 27 Sep 2010 20:11:49 -0500 Subject: Problem with McASP configuration Message-ID: Hi I have been working with McASP configuration for the Hawkboard, I test Audio with ALSA utils, I create a FS from http://www.angstrom-distribution.org/narcissus/ and in Additional console packages: Alsa utils I boot it from NFS (last patch that I send) I attach the boot process in a file. Then I apply the patch 0001-davinci-AUDIO-support-for-Omapl138-Hawkboard.patch and when I boot whit my patch for audio the command alsamixer works, as expected. but the problem is that with the command aplay it produce an error. root at hawkboard:~# aplay audio-samples/beethoven_44100.wav Unable to handle kernel NULL pointer dereference at virtual address 0000005c pgd = c7a7c000 [0000005c] *pgd=c7bf5031, *pte=00000000, *ppte=00000000 Internal error: Oops: 17 [#1] PREEMPT last sysfs file: /sys/kernel/uevent_seqnum Modules linked in: CPU: 0 Not tainted (2.6.36-rc4-07515-g6c9df1b-dirty #37) PC is at _clear_bit_le+0x14/0x2c LR is at prepare_unused_channel_list+0x54/0x70 pc : [] lr : [] psr: 20000093 sp : c7a17d40 ip : 20000013 fp : 00000001 r10: c7bf6800 r9 : c7823800 r8 : c7b64c60 r7 : c035b0bc r6 : c0340a90 r5 : 00000002 r4 : 0000001c r3 : 00000002 r2 : 00000001 r1 : 0000005c r0 : 00000001 Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user Control: 0005317f Table: c7a7c000 DAC: 00000015 Process aplay (pid: 1051, stack limit = 0xc7a16270) Stack: (0xc7a17d40 to 0xc7a18000) 7d40: 00000000 c0032400 00000000 c0191e50 c78074b8 c78415d0 c01c35c8 00000001 7d60: ffffffff c00327f4 00000001 c01c35c8 c7823800 c7b64c60 00000001 ffffffff 7d80: c7823800 c7b64c60 c78e7300 c7bf6800 c0355c44 c01c32cc c7823800 00000000 7da0: c03559f8 c0354df0 c7823800 c0355ce0 c0355938 c7bf6800 00000000 c01bde60 7dc0: c0354d00 c7a17e14 00000000 c7a16000 c7925ee0 c7925ef8 00000000 00000000 7de0: bedeb764 c01b50f4 c7925e00 c7823800 c7b0d400 c7925e00 c7b0d400 c01b5224 7e00: 00000000 c7aefb00 c0037d30 c7925ef8 c7925ef8 c01a9594 c0279680 c7b0d400 7e20: 00000000 c7ac7060 c792a9e0 00000000 00000000 c01a9a88 c7ac7060 c7b0d400 7e40: c78593c0 00000000 00000000 c0099f10 c7ac7060 00000010 c7b0d400 c7805a00 7e60: c7500d80 c7ac7060 c0099d64 c0095910 00000000 c7b0d400 00000000 00080802 7e80: 00000000 00000026 00000000 c0095ae8 c7b4bc60 00000026 c7a17ef0 c00a1048 7ea0: c7a17ef0 c7a17f50 00080802 00000026 c7a16000 00000026 00000000 00080803 7ec0: c7078000 c00a2b0c 00000000 c7078000 00000000 c794e000 00000000 00000000 7ee0: 00000000 00000000 00000000 ffffff9c c7805a00 c7500d80 c4254b62 00000008 7f00: c7078009 c7805820 c740e500 00000101 00000000 00000000 bedeb764 c00a3ff8 7f20: 00002000 c00a4750 c7b0d480 c034b168 c034b01c 40000013 60000093 00080803 7f40: 00000000 c7b0d400 c7b0f600 00000000 c7805a00 c7500d80 bedeb764 ffffff9c 7f60: 00000004 c7078000 00080802 bedeb60c c7a16000 ffffffff bedeb764 c00956dc 7f80: 00000000 bedeb764 00000802 00000000 401eb3b4 00000005 c0028024 c7a16000 7fa0: ffffffff c0027ea0 00000802 00000000 bedeb764 00080802 bedeb60c 0001e610 7fc0: 00000802 00000000 401eb3b4 00000005 00000000 00000001 ffffffff bedeb764 7fe0: 00000001 bedeb620 4018c204 400f34fc 60000010 bedeb764 00000000 00000000 Code: e3a03001 e1a03213 e10fc000 e321f093 (e7d121a0) ---[ end trace 1528f4db4f65a69b ]--- Segmentation fault root at hawkboard:~# I think is a problem with the configuration of the pins because is exactly the same if in the file arch/arm/mach-davinci/da850.c in the code const short da850_mcasp_pins[] __initdata = { DA850_AHCLKX, DA850_ACLKX, DA850_AFSX, DA850_AHCLKR, DA850_ACLKR, DA850_AFSR, DA850_AMUTE, DA850_AXR_11, DA850_AXR_12, DA850_AXR_13, DA850_AXR_14, -1 }; I change line DA850_AXR_11, DA850_AXR_12, DA850_AXR_13, DA850_AXR_14, to DA850_AXR_11, DA850_AXR_12, I am based my patch on Khasim patch [1] Thanks for all the help Sincerely yours Victor Rodriguez [1]http://cgit.openembedded.org/cgit.cgi/openembedded/tree/recipes/linux/linux-davinci/hawkboard/patch-2.6.33rc4-psp-to-hawkboard.patch -------------- next part -------------- A non-text attachment was scrubbed... Name: bootprocess Type: application/octet-stream Size: 4215 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-davinci-AUDIO-support-for-Omapl138-Hawkboard.patch Type: text/x-patch Size: 5659 bytes Desc: not available URL: From caglarakyuz at gmail.com Tue Sep 28 01:29:44 2010 From: caglarakyuz at gmail.com (Caglar Akyuz) Date: Tue, 28 Sep 2010 09:29:44 +0300 Subject: Problem with McASP configuration In-Reply-To: References: Message-ID: <201009280929.44574.caglarakyuz@gmail.com> On Tuesday 28 September 2010 04:11:49 am Victor Rodriguez wrote: > Hi I have been working with McASP configuration for the Hawkboard, I > test Audio with ALSA utils, I create a FS from > > http://www.angstrom-distribution.org/narcissus/ > > and in > > Additional console packages: > > Alsa utils > > I boot it from NFS (last patch that I send) I attach the boot process > in a file. > Then I apply the patch > > 0001-davinci-AUDIO-support-for-Omapl138-Hawkboard.patch > I don't see anything related to EDMA in this patch? Are you registering an EDMA instance? Did you have a look at [1]? Besides selecting CONFIG_KALLSYMS in your kernel config may give you a nicer backtrace. Regards, Caglar [1] http://gitorious.org/linux-davinci-hawk/linux-davinci-hawk/commit/3608cfa5eeb0bebc0943fece080bb34277a48e8e > > and when I boot whit my patch for audio the command alsamixer works, > as expected. > but the problem is that with the command aplay it produce an error. > > root at hawkboard:~# aplay audio-samples/beethoven_44100.wav > Unable to handle kernel NULL pointer dereference at virtual address > 0000005c pgd = c7a7c000 > [0000005c] *pgd=c7bf5031, *pte=00000000, *ppte=00000000 > Internal error: Oops: 17 [#1] PREEMPT > last sysfs file: /sys/kernel/uevent_seqnum > Modules linked in: > CPU: 0 Not tainted (2.6.36-rc4-07515-g6c9df1b-dirty #37) > PC is at _clear_bit_le+0x14/0x2c > LR is at prepare_unused_channel_list+0x54/0x70 > pc : [] lr : [] psr: 20000093 > sp : c7a17d40 ip : 20000013 fp : 00000001 > r10: c7bf6800 r9 : c7823800 r8 : c7b64c60 > r7 : c035b0bc r6 : c0340a90 r5 : 00000002 r4 : 0000001c > r3 : 00000002 r2 : 00000001 r1 : 0000005c r0 : 00000001 > Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user > Control: 0005317f Table: c7a7c000 DAC: 00000015 > Process aplay (pid: 1051, stack limit = 0xc7a16270) > Stack: (0xc7a17d40 to 0xc7a18000) > 7d40: 00000000 c0032400 00000000 c0191e50 c78074b8 c78415d0 c01c35c8 > 00000001 7d60: ffffffff c00327f4 00000001 c01c35c8 c7823800 c7b64c60 > 00000001 ffffffff 7d80: c7823800 c7b64c60 c78e7300 c7bf6800 c0355c44 > c01c32cc c7823800 00000000 7da0: c03559f8 c0354df0 c7823800 c0355ce0 > c0355938 c7bf6800 00000000 c01bde60 7dc0: c0354d00 c7a17e14 00000000 > c7a16000 c7925ee0 c7925ef8 00000000 00000000 7de0: bedeb764 c01b50f4 > c7925e00 c7823800 c7b0d400 c7925e00 c7b0d400 c01b5224 7e00: 00000000 > c7aefb00 c0037d30 c7925ef8 c7925ef8 c01a9594 c0279680 c7b0d400 7e20: > 00000000 c7ac7060 c792a9e0 00000000 00000000 c01a9a88 c7ac7060 c7b0d400 > 7e40: c78593c0 00000000 00000000 c0099f10 c7ac7060 00000010 c7b0d400 > c7805a00 7e60: c7500d80 c7ac7060 c0099d64 c0095910 00000000 c7b0d400 > 00000000 00080802 7e80: 00000000 00000026 00000000 c0095ae8 c7b4bc60 > 00000026 c7a17ef0 c00a1048 7ea0: c7a17ef0 c7a17f50 00080802 00000026 > c7a16000 00000026 00000000 00080803 7ec0: c7078000 c00a2b0c 00000000 > c7078000 00000000 c794e000 00000000 00000000 7ee0: 00000000 00000000 > 00000000 ffffff9c c7805a00 c7500d80 c4254b62 00000008 7f00: c7078009 > c7805820 c740e500 00000101 00000000 00000000 bedeb764 c00a3ff8 7f20: > 00002000 c00a4750 c7b0d480 c034b168 c034b01c 40000013 60000093 00080803 > 7f40: 00000000 c7b0d400 c7b0f600 00000000 c7805a00 c7500d80 bedeb764 > ffffff9c 7f60: 00000004 c7078000 00080802 bedeb60c c7a16000 ffffffff > bedeb764 c00956dc 7f80: 00000000 bedeb764 00000802 00000000 401eb3b4 > 00000005 c0028024 c7a16000 7fa0: ffffffff c0027ea0 00000802 00000000 > bedeb764 00080802 bedeb60c 0001e610 7fc0: 00000802 00000000 401eb3b4 > 00000005 00000000 00000001 ffffffff bedeb764 7fe0: 00000001 bedeb620 > 4018c204 400f34fc 60000010 bedeb764 00000000 00000000 Code: e3a03001 > e1a03213 e10fc000 e321f093 (e7d121a0) > ---[ end trace 1528f4db4f65a69b ]--- > Segmentation fault > root at hawkboard:~# > > I think is a problem with the configuration of the pins because is > exactly the same if in the file arch/arm/mach-davinci/da850.c in the > code > > const short da850_mcasp_pins[] __initdata = { > DA850_AHCLKX, DA850_ACLKX, DA850_AFSX, > DA850_AHCLKR, DA850_ACLKR, DA850_AFSR, DA850_AMUTE, > DA850_AXR_11, DA850_AXR_12, DA850_AXR_13, DA850_AXR_14, > -1 > }; > > I change line > > DA850_AXR_11, DA850_AXR_12, DA850_AXR_13, DA850_AXR_14, > > to > > DA850_AXR_11, DA850_AXR_12, > > I am based my patch on Khasim patch [1] > > Thanks for all the help > > Sincerely yours > > Victor Rodriguez > > > [1]http://cgit.openembedded.org/cgit.cgi/openembedded/tree/recipes/linux/li > nux-davinci/hawkboard/patch-2.6.33rc4-psp-to-hawkboard.patch > From sshtylyov at mvista.com Tue Sep 28 05:13:19 2010 From: sshtylyov at mvista.com (Sergei Shtylyov) Date: Tue, 28 Sep 2010 14:13:19 +0400 Subject: [PATCH v5 1/3] ARM: add CPPI 4.1 DMA support In-Reply-To: References: <201005152214.53993.sshtylyov@ru.mvista.com> Message-ID: <4CA1BFBF.2090102@mvista.com> Hello. On 28-09-2010 13:13, Linus Walleij wrote: >> Add support for Texas Instuments Communication Port Programming Interface 4.1 >> (CPPI 4.1) used on OMAP-L1x/DA8xx and AM35x. > Sorry for late feedback ... >> +++ linux-davinci/arch/arm/common/cppi41.c > Can you migrate this driver to drivers/dma/cppi41.c and use the > DMAengine interface like so many DMA drivers we have created > recently, or is there some very special characteristics about this > DMA controller meriting it to be placed in arch/arm/*? I have once studied the possibility of doing this driver under drivers/dma/, and found that hardly achievable. Maybe I should try again though... > Yours, > Linus Walleij WBR, Sergei From Jon.Povey at racelogic.co.uk Tue Sep 28 05:29:04 2010 From: Jon.Povey at racelogic.co.uk (Jon Povey) Date: Tue, 28 Sep 2010 11:29:04 +0100 Subject: UBI crashes / fixing NAND subpage writes In-Reply-To: <1285419347890-5569840.post@n2.nabble.com> Message-ID: <70E876B0EA86DD4BAF101844BC814DFE093ED60018@Cloud.RL.local> davinci-linux-open-source-bounces at linux.davincidsp.com wrote: > Jon, i studied the davinci subpage write problem to find an > applicable solution, but can not come up with a good idea. Your > findings about the > cause of the > problem is totally correct but there is a question in my mind: > > Nand subpage support is added to the mainline kernel with this patch: > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.g > it;a=commit;h=29072b96078ffde36f03d51e6b5d0cff1ba8c7df > link > > Since its in mainline i guess nand subpage support is working > with other > nand > controllers, but not with davinci. There must be a way to > solve this problem > within the davinci_nand.c driver without touching the main nand API's. Unfortunately there is not a good way of doing it only within davinci that I can see. The problem is that the nand_base layer handles a subpage write by writing a whole page, with areas outside the written subpage set to FFs. The davinci layer can't tell the difference. I hacked this up by adding start offset and length parameters to all the page writing functions, which works for me but isn't going to be acceptable for mainline. Artem over on the MTD list suggested a write_subpage family of functions might be the way to go, but I haven't implemented that. http://linux.davincidsp.com/pipermail/davinci-linux-open-source/2010-September/020206.html -- Jon Povey jon.povey at racelogic.co.uk Racelogic is a limited company registered in England. Registered number 2743719 . Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB . The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network From vm.rod25 at gmail.com Tue Sep 28 09:38:57 2010 From: vm.rod25 at gmail.com (Victor Rodriguez) Date: Tue, 28 Sep 2010 09:38:57 -0500 Subject: Problem with McASP configuration In-Reply-To: <201009280929.44574.caglarakyuz@gmail.com> References: <201009280929.44574.caglarakyuz@gmail.com> Message-ID: On Tue, Sep 28, 2010 at 1:29 AM, Caglar Akyuz wrote: > On Tuesday 28 September 2010 04:11:49 am Victor Rodriguez wrote: >> Hi I have been working with McASP configuration for the Hawkboard, I >> test Audio with ALSA utils, I create a FS from >> >> http://www.angstrom-distribution.org/narcissus/ >> >> and in >> >> Additional console packages: >> >> Alsa utils >> >> I boot it from NFS (last patch that I send) I attach the boot process >> in a file. >> Then I apply the patch >> >> 0001-davinci-AUDIO-support-for-Omapl138-Hawkboard.patch >> > > I don't see anything related to EDMA in this patch? Are you registering > an EDMA instance? Did you have a look at [1]? > > Besides selecting CONFIG_KALLSYMS in your kernel config may > give you a nicer backtrace. > > Regards, > Caglar > > [1] http://gitorious.org/linux-davinci-hawk/linux-davinci-hawk/commit/3608cfa5eeb0bebc0943fece080bb34277a48e8e Sorry about that dummy mistake i forgot the EDMA :) actually was the first patch that I had re-base after initial support but for some reason I decided not to apply now in Audio support. Thanks a lot Caglar it works perfect, will make a test case for ALSA utils, where did you find an error on audio for hawkboard? I have tested on 4400 Hz and it works perfect, Any way thanks a lot, did you plan to send your patches to main line? that would be very helpful, However I will keep learning doing all the other patches. Thanks Sincerely yours VIctor Rodriguez >> >> and when I boot whit my patch for audio the command alsamixer works, >> as expected. >> but the problem is that with the command aplay it produce an error. >> >> root at hawkboard:~# aplay audio-samples/beethoven_44100.wav >> Unable to handle kernel NULL pointer dereference at virtual address >> ?0000005c pgd = c7a7c000 >> [0000005c] *pgd=c7bf5031, *pte=00000000, *ppte=00000000 >> Internal error: Oops: 17 [#1] PREEMPT >> last sysfs file: /sys/kernel/uevent_seqnum >> Modules linked in: >> CPU: 0 ? ?Not tainted ?(2.6.36-rc4-07515-g6c9df1b-dirty #37) >> PC is at _clear_bit_le+0x14/0x2c >> LR is at prepare_unused_channel_list+0x54/0x70 >> pc : [] ? ?lr : [] ? ?psr: 20000093 >> sp : c7a17d40 ?ip : 20000013 ?fp : 00000001 >> r10: c7bf6800 ?r9 : c7823800 ?r8 : c7b64c60 >> r7 : c035b0bc ?r6 : c0340a90 ?r5 : 00000002 ?r4 : 0000001c >> r3 : 00000002 ?r2 : 00000001 ?r1 : 0000005c ?r0 : 00000001 >> Flags: nzCv ?IRQs off ?FIQs on ?Mode SVC_32 ?ISA ARM ?Segment user >> Control: 0005317f ?Table: c7a7c000 ?DAC: 00000015 >> Process aplay (pid: 1051, stack limit = 0xc7a16270) >> Stack: (0xc7a17d40 to 0xc7a18000) >> 7d40: 00000000 c0032400 00000000 c0191e50 c78074b8 c78415d0 c01c35c8 >> ?00000001 7d60: ffffffff c00327f4 00000001 c01c35c8 c7823800 c7b64c60 >> ?00000001 ffffffff 7d80: c7823800 c7b64c60 c78e7300 c7bf6800 c0355c44 >> ?c01c32cc c7823800 00000000 7da0: c03559f8 c0354df0 c7823800 c0355ce0 >> ?c0355938 c7bf6800 00000000 c01bde60 7dc0: c0354d00 c7a17e14 00000000 >> ?c7a16000 c7925ee0 c7925ef8 00000000 00000000 7de0: bedeb764 c01b50f4 >> ?c7925e00 c7823800 c7b0d400 c7925e00 c7b0d400 c01b5224 7e00: 00000000 >> ?c7aefb00 c0037d30 c7925ef8 c7925ef8 c01a9594 c0279680 c7b0d400 7e20: >> ?00000000 c7ac7060 c792a9e0 00000000 00000000 c01a9a88 c7ac7060 c7b0d400 >> ?7e40: c78593c0 00000000 00000000 c0099f10 c7ac7060 00000010 c7b0d400 >> ?c7805a00 7e60: c7500d80 c7ac7060 c0099d64 c0095910 00000000 c7b0d400 >> ?00000000 00080802 7e80: 00000000 00000026 00000000 c0095ae8 c7b4bc60 >> ?00000026 c7a17ef0 c00a1048 7ea0: c7a17ef0 c7a17f50 00080802 00000026 >> ?c7a16000 00000026 00000000 00080803 7ec0: c7078000 c00a2b0c 00000000 >> ?c7078000 00000000 c794e000 00000000 00000000 7ee0: 00000000 00000000 >> ?00000000 ffffff9c c7805a00 c7500d80 c4254b62 00000008 7f00: c7078009 >> ?c7805820 c740e500 00000101 00000000 00000000 bedeb764 c00a3ff8 7f20: >> ?00002000 c00a4750 c7b0d480 c034b168 c034b01c 40000013 60000093 00080803 >> ?7f40: 00000000 c7b0d400 c7b0f600 00000000 c7805a00 c7500d80 bedeb764 >> ?ffffff9c 7f60: 00000004 c7078000 00080802 bedeb60c c7a16000 ffffffff >> ?bedeb764 c00956dc 7f80: 00000000 bedeb764 00000802 00000000 401eb3b4 >> ?00000005 c0028024 c7a16000 7fa0: ffffffff c0027ea0 00000802 00000000 >> ?bedeb764 00080802 bedeb60c 0001e610 7fc0: 00000802 00000000 401eb3b4 >> ?00000005 00000000 00000001 ffffffff bedeb764 7fe0: 00000001 bedeb620 >> ?4018c204 400f34fc 60000010 bedeb764 00000000 00000000 Code: e3a03001 >> ?e1a03213 e10fc000 e321f093 (e7d121a0) >> ---[ end trace 1528f4db4f65a69b ]--- >> Segmentation fault >> root at hawkboard:~# >> >> I think is a problem with the configuration of the pins because is >> exactly the same if in the file arch/arm/mach-davinci/da850.c in the >> code >> >> const short da850_mcasp_pins[] __initdata = { >> ? ? ? DA850_AHCLKX, DA850_ACLKX, DA850_AFSX, >> ? ? ? DA850_AHCLKR, DA850_ACLKR, DA850_AFSR, DA850_AMUTE, >> ? ? ? DA850_AXR_11, DA850_AXR_12, DA850_AXR_13, DA850_AXR_14, >> ? ? ? -1 >> }; >> >> I change line >> >> ? ? ? DA850_AXR_11, DA850_AXR_12, DA850_AXR_13, DA850_AXR_14, >> >> to >> >> ? ? ? DA850_AXR_11, DA850_AXR_12, >> >> I am based my patch on Khasim patch [1] >> >> Thanks for all the help >> >> Sincerely yours >> >> Victor Rodriguez >> >> >> [1]http://cgit.openembedded.org/cgit.cgi/openembedded/tree/recipes/linux/li >> nux-davinci/hawkboard/patch-2.6.33rc4-psp-to-hawkboard.patch >> > From dmitry.torokhov at gmail.com Mon Sep 13 20:26:48 2010 From: dmitry.torokhov at gmail.com (Dmitry Torokhov) Date: Mon, 13 Sep 2010 18:26:48 -0700 Subject: [PATCH 1/7] davinci: define tnetv107x keypad platform data In-Reply-To: <1284395388-32687-2-git-send-email-cyril@ti.com> References: <1284395388-32687-1-git-send-email-cyril@ti.com> <1284395388-32687-2-git-send-email-cyril@ti.com> Message-ID: <20100914012648.GC2491@core.coreip.homeip.net> Hi Cyril, On Mon, Sep 13, 2010 at 12:29:42PM -0400, Cyril Chemparathy wrote: > This patch adds a definition for the platform data structure needed to > configure the keypad controller on tnetv107x socs. > > Since this controller is (so far) present only on tnetv107x devices, the data > structure definition has been kept local to tnetv107x. > > Signed-off-by: Cyril Chemparathy > --- > arch/arm/mach-davinci/include/mach/tnetv107x.h | 10 ++++++++++ > 1 files changed, 10 insertions(+), 0 deletions(-) > > diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h > index c720647..1ee3035 100644 > --- a/arch/arm/mach-davinci/include/mach/tnetv107x.h > +++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h > @@ -37,6 +37,16 @@ > #include > #include > > +struct tnetv107x_keypad_data { > + int *keymap; > + const char **keynames; > + int keymap_size; > + int rows; > + int cols; > + u32 debounce; > + u32 stable; > +}; > + This should be folded into the next patch and probably split into a separate header file. Also, please consider switching to interface in linux/input/matrix_keymap.h Thanks. - Dmitry From dmitry.torokhov at gmail.com Mon Sep 13 20:26:56 2010 From: dmitry.torokhov at gmail.com (Dmitry Torokhov) Date: Mon, 13 Sep 2010 18:26:56 -0700 Subject: [PATCH 2/7] input: add driver for tnetv107x on-chip keypad controller In-Reply-To: <1284395388-32687-3-git-send-email-cyril@ti.com> References: <1284395388-32687-1-git-send-email-cyril@ti.com> <1284395388-32687-3-git-send-email-cyril@ti.com> Message-ID: <20100914012655.GD2491@core.coreip.homeip.net> On Mon, Sep 13, 2010 at 12:29:43PM -0400, Cyril Chemparathy wrote: > This patch adds support for tnetv107x's on-chip keypad controller. > > Signed-off-by: Cyril Chemparathy > --- > drivers/input/keyboard/Kconfig | 9 + > drivers/input/keyboard/Makefile | 1 + > drivers/input/keyboard/tnetv107x-keypad.c | 324 +++++++++++++++++++++++++++++ > 3 files changed, 334 insertions(+), 0 deletions(-) > create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c > > diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig > index 9cc488d..0ea8648 100644 > --- a/drivers/input/keyboard/Kconfig > +++ b/drivers/input/keyboard/Kconfig > @@ -457,4 +457,13 @@ config KEYBOARD_W90P910 > To compile this driver as a module, choose M here: the > module will be called w90p910_keypad. > > +config KEYBOARD_TNETV107X > + tristate "TI TNETV107X keypad support" > + depends on ARCH_DAVINCI_TNETV107X > + help > + Say Y here if you want to use the TNETV107X keypad. > + > + To compile this driver as a module, choose M here: the > + module will be called tnetv107x-keypad. > + > endif > diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile > index 504b591..63261b0 100644 > --- a/drivers/input/keyboard/Makefile > +++ b/drivers/input/keyboard/Makefile > @@ -41,3 +41,4 @@ obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o > obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o > obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o > obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o > +obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o Please keep makefile and Kconfig sorted alphabetically please. > diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c > new file mode 100644 > index 0000000..5039164 > --- /dev/null > +++ b/drivers/input/keyboard/tnetv107x-keypad.c > @@ -0,0 +1,324 @@ > +/* > + * Texas Instruments TNETV107X Keypad Driver > + * > + * Copyright (C) 2010 Texas Instruments > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed "as is" WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#define KEYPAD_ROWS 9 > +#define KEYPAD_COLS 9 > + > +struct keypad_regs { > + u32 rev; > + u32 mode; > + u32 mask; > + u32 pol; > + u32 dclock; > + u32 rclock; > + u32 stable_cnt; > + u32 in_en; > + u32 out; > + u32 out_en; > + u32 in; > + u32 lock; > + u32 pres[3]; > +}; > + > +#define keypad_read(kp, reg) __raw_readl(&(kp)->regs->reg) > +#define keypad_write(kp, reg, val) __raw_writel(val, &(kp)->regs->reg) > + > +struct keypad_data { > + struct tnetv107x_keypad_data data; > + struct input_dev *input_dev; > + struct resource *res; > + struct keypad_regs __iomem *regs; > + struct clk *clk; > + struct device *dev; > + u32 irq_press; > + u32 irq_release; > + u32 curr_keys[3]; > + u32 prev_keys[3]; > +}; > + > +static void handle_change(struct keypad_data *kp) > +{ > + int bit, i; > + > + for (bit = 0; bit < (KEYPAD_ROWS * KEYPAD_COLS); bit++) { > + int idx = bit / 32; > + u32 mask = 1 << (bit % 32); > + u32 curr = kp->curr_keys[idx] & mask; > + u32 prev = kp->prev_keys[idx] & mask; > + int row = bit / KEYPAD_COLS; > + int col = bit % KEYPAD_COLS; > + int ofs = row * kp->data.cols + col; > + > + if (col >= kp->data.cols || row >= kp->data.rows) > + continue; > + > + if (curr && !prev) { > + /* Report key press */ > + if (kp->data.keynames && kp->data.keynames[ofs]) > + dev_dbg(kp->dev, "%s (%d) pressed\n", > + kp->data.keynames[ofs], ofs); > + input_report_key(kp->input_dev, > + kp->data.keymap[ofs], 1); > + } else if (!curr && prev) { > + /* Report key release */ > + if (kp->data.keynames && kp->data.keynames[ofs]) > + dev_dbg(kp->dev, "%s (%d) released\n", > + kp->data.keynames[ofs], ofs); > + input_report_key(kp->input_dev, > + kp->data.keymap[ofs], 0); > + } This is called xor. Also, instead of printing key names just send EV_MSC/MSC_SCAN - much more useful. > + } > + > + /* Update shadow copy */ > + for (i = 0; i < 3; i++) > + kp->prev_keys[i] = kp->curr_keys[i]; memcpy(kp->prev_keys, kp->curr_keys, sizeof(kp->prev_keys)); > + > + input_sync(kp->input_dev); > +} > + > +static irqreturn_t keypad_irq_press(int irq, void *data) > +{ > + struct keypad_data *kp = (struct keypad_data *)data; > + int i; > + > + for (i = 0; i < 3; i++) > + kp->curr_keys[i] = keypad_read(kp, pres[i]); > + handle_change(kp); > + keypad_write(kp, lock, 0); /* Allow hardware updates */ > + return IRQ_HANDLED; > +} > + > +static irqreturn_t keypad_irq_release(int irq, void *data) > +{ > + struct keypad_data *kp = (struct keypad_data *)data; > + int i; > + > + /* Hardware says all keys have been released */ > + for (i = 0; i < 3; i++) > + kp->curr_keys[i] = 0; memset(kp->curr_keys, 0, sizeof(kp->curr_keys)); > + handle_change(kp); > + return IRQ_HANDLED; > +} > + > +static int tnetv107x_keypad_probe(struct platform_device *pdev) > +{ > + struct tnetv107x_keypad_data *pdata = pdev->dev.platform_data; This should be const. > + struct device *dev = &pdev->dev; > + struct keypad_data *kp; > + int i, ret = 0; > + u32 rev = 0; > + > + ret = -EINVAL; > + if (!pdata) { > + dev_err(dev, "cannot find device data\n"); > + return ret; > + } Please assign error code in the error branch. I also prefer variable be called error if possible. > + > + ret = -ENOMEM; > + kp = kzalloc(sizeof(struct keypad_data), GFP_KERNEL); > + if (!kp) { > + dev_err(dev, "cannot allocate device info\n"); > + return ret; > + } > + > + dev_set_drvdata(dev, kp); > + kp->data = *pdata; > + kp->dev = dev; > + > + ret = -ENOMEM; > + kp->input_dev = input_allocate_device(); > + if (!kp->input_dev) { > + dev_err(dev, "cannot allocate input device\n"); > + goto error0; > + } > + > + ret = -ENODEV; > + kp->irq_press = platform_get_irq_byname(pdev, "press"); > + kp->irq_release = platform_get_irq_byname(pdev, "release"); > + if (kp->irq_press < 0 || kp->irq_release < 0) { > + dev_err(dev, "cannot determine device interrupts\n"); > + goto error1; > + } > + > + ret = -ENODEV; > + kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!kp->res) { > + dev_err(dev, "cannot determine register area\n"); > + goto error1; > + } > + > + ret = -EINVAL; > + if (!request_mem_region(kp->res->start, resource_size(kp->res), > + pdev->name)) { > + dev_err(dev, "cannot claim register memory\n"); > + goto error1; > + } > + > + ret = -ENOMEM; > + kp->regs = ioremap(kp->res->start, resource_size(kp->res)); > + if (!kp->regs) { > + dev_err(dev, "cannot map register memory\n"); > + goto error2; > + } > + > + ret = -EINVAL; > + kp->clk = clk_get(dev, NULL); > + if (!kp->clk) { > + dev_err(dev, "cannot claim device clock\n"); > + goto error3; > + } > + clk_enable(kp->clk); > + > + /* Initialize device registers */ > + keypad_write(kp, mode, 0); > + keypad_write(kp, mask, ~((((1 << kp->data.rows)-1) << 9) | > + (((1 << kp->data.cols)-1)))); > + keypad_write(kp, pol, 0x3ffff); > + keypad_write(kp, dclock, kp->data.debounce); > + keypad_write(kp, rclock, 4*kp->data.debounce); > + keypad_write(kp, stable_cnt, kp->data.stable); > + > + /* Enable Input */ > + keypad_write(kp, in_en, 0); > + mdelay(1); > + keypad_write(kp, in_en, 1); > + > + ret = request_irq(kp->irq_press, keypad_irq_press, 0, > + "keypad-press", kp); > + if (ret < 0) { > + dev_err(dev, "Could not allocate keypad press key irq\n"); > + goto error4; > + } > + > + ret = request_irq(kp->irq_release, keypad_irq_release, 0, > + "keypad-release", kp); > + if (ret < 0) { > + dev_err(dev, "Could not allocate keypad release key irq\n"); > + goto error5; > + } > + > + set_bit(EV_KEY, kp->input_dev->evbit); > + for (i = 0; i < kp->data.keymap_size; i++) > + set_bit(kp->data.keymap[i] & KEY_MAX, kp->input_dev->keybit); > + > + kp->input_dev->name = "tnetv107x-keypad"; > + kp->input_dev->phys = "tnetv107x-keypad/input0"; > + kp->input_dev->dev.parent = &pdev->dev; > + kp->input_dev->id.bustype = BUS_HOST; > + kp->input_dev->id.vendor = 0x0001; > + > + rev = keypad_read(kp, rev); > + kp->input_dev->id.product = ((rev >> 8) & 0x07); > + kp->input_dev->id.version = ((rev >> 16) & 0xfff); > + > + kp->input_dev->keycode = kp->data.keymap; > + kp->input_dev->keycodesize = sizeof(int); > + kp->input_dev->keycodemax = kp->data.keymap_size; Since you allow changing data keymap should be moved into per-device instance (platform data should be kept constant). > + ret = input_register_device(kp->input_dev); > + if (ret < 0) { > + dev_err(dev, "Could not register input device\n"); > + goto error6; > + } > + > + dev_info(dev, "registered keypad device\n"); Input core already emits message when new device is registered, should be enough. > + return 0; > + > +error6: > + free_irq(kp->irq_release, kp); > +error5: > + free_irq(kp->irq_press, kp); > +error4: > + clk_disable(kp->clk); > + clk_put(kp->clk); > +error3: > + iounmap(kp->regs); > +error2: > + release_mem_region(kp->res->start, resource_size(kp->res)); > +error1: > + input_free_device(kp->input_dev); > +error0: > + platform_set_drvdata(pdev, NULL); > + kfree(kp); > + return ret; > +} > + > +static int tnetv107x_keypad_remove(struct platform_device *pdev) > +{ > + struct keypad_data *kp = dev_get_drvdata(&pdev->dev); platform_get_drvdata(); > + > + if (kp) { How kp can be NULL here? > + input_unregister_device(kp->input_dev); > + free_irq(kp->irq_release, kp); > + free_irq(kp->irq_press, kp); > + clk_disable(kp->clk); > + clk_put(kp->clk); > + iounmap(kp->regs); > + release_mem_region(kp->res->start, resource_size(kp->res)); > + input_free_device(kp->input_dev); No free after unregister. > + platform_set_drvdata(pdev, NULL); > + kfree(kp); > + } > + return 0; > +} > + > +static int tnetv107x_keypad_suspend(struct platform_device *pdev, > + pm_message_t state) > +{ > + /* Nothing yet */ > + return 0; > +} > + > +static int tnetv107x_keypad_resume(struct platform_device *pdev) > +{ > + /* Nothing yet */ > + return 0; > +} If there is nothing yet - drop them. > + > +static struct platform_driver tnetv107x_keypad_driver = { > + .probe = tnetv107x_keypad_probe, > + .remove = tnetv107x_keypad_remove, > + .suspend = tnetv107x_keypad_suspend, > + .resume = tnetv107x_keypad_resume, > + .driver.name = "tnetv107x-keypad", Please assign .owner = THIS_MODULE as well. > +}; > + > +static int __init tnetv107x_keypad_init(void) > +{ > + return platform_driver_register(&tnetv107x_keypad_driver); > +} > + > +static void __exit tnetv107x_keypad_exit(void) > +{ > + platform_driver_unregister(&tnetv107x_keypad_driver); > +} > + > +module_init(tnetv107x_keypad_init); > +module_exit(tnetv107x_keypad_exit); > + > +MODULE_AUTHOR("Cyril Chemparathy"); > +MODULE_DESCRIPTION("TNETV107X Keypad Driver"); > +MODULE_LICENSE("GPL"); MODULE_ALIAS("platform: tnetv107x-keypad"); in case driver gets renamed. Thanks. -- Dmitry From dmitry.torokhov at gmail.com Mon Sep 13 20:27:04 2010 From: dmitry.torokhov at gmail.com (Dmitry Torokhov) Date: Mon, 13 Sep 2010 18:27:04 -0700 Subject: [PATCH 5/7] input: add driver for tnetv107x touchscreen controller In-Reply-To: <1284395388-32687-6-git-send-email-cyril@ti.com> References: <1284395388-32687-1-git-send-email-cyril@ti.com> <1284395388-32687-6-git-send-email-cyril@ti.com> Message-ID: <20100914012704.GE2491@core.coreip.homeip.net> On Mon, Sep 13, 2010 at 12:29:46PM -0400, Cyril Chemparathy wrote: > This patch adds support for tnetv107x's on-chip touchscreen controller. > > Signed-off-by: Cyril Chemparathy > --- > drivers/input/touchscreen/Kconfig | 6 + > drivers/input/touchscreen/Makefile | 1 + > drivers/input/touchscreen/tnetv107x-ts.c | 481 ++++++++++++++++++++++++++++++ > 3 files changed, 488 insertions(+), 0 deletions(-) > create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c > > diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig > index 0069d97..e56a170 100644 > --- a/drivers/input/touchscreen/Kconfig > +++ b/drivers/input/touchscreen/Kconfig > @@ -638,4 +638,10 @@ config TOUCHSCREEN_STMPE > To compile this driver as a module, choose M here: the > module will be called stmpe-ts. > > +config TOUCHSCREEN_TNETV107X > + tristate "TI TNETV107X touchscreen support" > + depends on ARCH_DAVINCI_TNETV107X > + help > + Say Y here if you want to use the TNETV107X touchscreen. > + To compile this driver as a module... > endif > diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile > index 28217e1..55a7db9 100644 > --- a/drivers/input/touchscreen/Makefile > +++ b/drivers/input/touchscreen/Makefile > @@ -52,3 +52,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o > obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o > obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o > obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o > +obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o Alphabetical order please. > diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c > new file mode 100644 > index 0000000..a8543c5 > --- /dev/null > +++ b/drivers/input/touchscreen/tnetv107x-ts.c > @@ -0,0 +1,481 @@ > +/* > + * Texas Instruments TNETV107X Touchscreen Driver > + * > + * Copyright (C) 2010 Texas Instruments > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed "as is" WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +/* Poll Rates */ > +#define TSC_PENUP_POLL (HZ / 5) > + > +/* > + * The first and last samples of a touch interval are usually garbage and need > + * to be filtered out with these devices. The following definitions control > + * the number of samples skipped. > + */ > +#define TSC_HEAD_SKIP 1 > +#define TSC_TAIL_SKIP 1 > +#define TSC_SKIP (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1) > +#define TSC_SAMPLES (TSC_SKIP + 1) > + > +/* Register Offsets */ > +struct tsc_regs { > + u32 rev; > + u32 tscm; > + u32 bwcm; > + u32 swc; > + u32 adcchnl; > + u32 adcdata; > + u32 chval[4]; > +}; > + > +/* TSC Mode Configuration Register (tscm) bits */ > +#define WMODE BIT(0) > +#define TSKIND BIT(1) > +#define ZMEASURE_EN BIT(2) > +#define IDLE BIT(3) > +#define TSC_EN BIT(4) > +#define STOP BIT(5) > +#define ONE_SHOT BIT(6) > +#define SINGLE BIT(7) > +#define AVG BIT(8) > +#define AVGNUM(x) (((x) & 0x03) << 9) > +#define PVSTC(x) (((x) & 0x07) << 11) > +#define PON BIT(14) > +#define PONBG BIT(15) > +#define AFERST BIT(16) > + > +/* ADC DATA Capture Register bits */ > +#define DATA_VALID BIT(16) > + > +/* Register Access Macros */ > +#define tsc_read(ts, reg) __raw_readl(&(ts)->regs->reg) > +#define tsc_write(ts, reg, val) __raw_writel(val, &(ts)->regs->reg); > +#define tsc_set_bits(ts, reg, val) \ > + tsc_write(ts, reg, tsc_read(ts, reg) | (val)) > +#define tsc_clr_bits(ts, reg, val) \ > + tsc_write(ts, reg, tsc_read(ts, reg) & ~(val)) > + > +struct sample { > + int x, y, p; > +}; > + > +struct tsc_data { > + struct tnetv107x_tsc_data data; > + struct input_dev *input_dev; > + struct resource *res; > + struct tsc_regs __iomem *regs; > + struct timer_list timer; > + spinlock_t lock; > + struct clk *clk; > + struct device *dev; > + int sample_count; > + struct sample samples[TSC_SAMPLES]; > + int tsc_irq; > + int cal[TSC_CAL_SIZE]; > +}; > + > +/* default calibration that works for most evm boards */ > +static int tscal_set; > +static int tscal[TSC_CAL_SIZE]; > +module_param_array(tscal, int, &tscal_set, 0); > + > +static inline int Let compiler decide whether it should be inline or not. Same for the rest. > +tsc_read_sample(struct tsc_data *ts, struct sample* sample) > +{ > + int x, y, z1, z2, t, p = 0; > + u32 val; > + > + val = tsc_read(ts, chval[0]); > + if (val & DATA_VALID) > + x = val & 0xffff; > + else > + return -EINVAL; > + > + y = tsc_read(ts, chval[1]) & 0xffff; > + z1 = tsc_read(ts, chval[2]) & 0xffff; > + z2 = tsc_read(ts, chval[3]) & 0xffff; > + > + if (z1) { > + t = ((600 * x) * (z2 - z1)); > + p = t / (u32) (z1 << 12); > + if (p < 0) > + p = 0; > + } > + > + sample->x = (ts->cal[2] + ts->cal[0] * x + ts->cal[1] * y); > + sample->x /= ts->cal[6]; > + sample->y = (ts->cal[5] + ts->cal[3] * x + ts->cal[4] * y); > + sample->y /= ts->cal[6]; > + sample->p = p; > + > + return 0; > +} > + > +static inline void tsc_report_up(struct tsc_data *ts) > +{ > + input_report_abs(ts->input_dev, ABS_PRESSURE, 0); > + input_report_key(ts->input_dev, BTN_TOUCH, 0); > + input_sync(ts->input_dev); > +} > + > +static inline void tsc_report(struct tsc_data *ts, int x, int y, int p) > +{ > + input_report_abs(ts->input_dev, ABS_X, x); > + input_report_abs(ts->input_dev, ABS_Y, y); > + input_report_abs(ts->input_dev, ABS_PRESSURE, p); > +} > + > +static inline void tsc_report_down(struct tsc_data *ts, bool touch) > +{ > + if (touch) > + input_report_key(ts->input_dev, BTN_TOUCH, 1); > + input_sync(ts->input_dev); > +} > + > +static inline void tsc_poll(unsigned long data) > +{ > + struct tsc_data *ts = (struct tsc_data *)data; > + unsigned long flags; > + int i, val, x, y, p; > + > + spin_lock_irqsave(&ts->lock, flags); > + > + if (ts->sample_count >= TSC_SKIP) { > + tsc_report_up(ts); > + } else if (ts->sample_count > 0) { > + /* > + * A touch event lasted less than our skip count. Salvage and > + * report anyway. > + */ > + for (i = 0, val = 0; i < ts->sample_count; i++) > + val += ts->samples[i].x; > + x = val / ts->sample_count; > + > + for (i = 0, val = 0; i < ts->sample_count; i++) > + val += ts->samples[i].y; > + y = val / ts->sample_count; > + > + for (i = 0, val = 0; i < ts->sample_count; i++) > + val += ts->samples[i].p; > + p = val / ts->sample_count; > + > + tsc_report(ts, x, y, p); > + tsc_report_down(ts, true); > + } > + > + ts->sample_count = 0; > + > + spin_unlock_irqrestore(&ts->lock, flags); > +} > + > +static irqreturn_t tsc_irq(int irq, void *dev_id) > +{ > + struct tsc_data *ts = (struct tsc_data *)dev_id; > + struct sample *sample; > + int index; > + > + spin_lock(&ts->lock); > + > + index = ts->sample_count % TSC_SAMPLES; > + sample = &ts->samples[index]; > + if (tsc_read_sample(ts, sample) >= 0) { > + ++ts->sample_count; > + > + if (ts->sample_count < TSC_SKIP) > + goto done; > + > + index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES; > + sample = &ts->samples[index]; > + > + tsc_report(ts, sample->x, sample->y, sample->y); > + tsc_report_down(ts, (ts->sample_count == TSC_SKIP)); > +done: > + mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL); > + } > + > + spin_unlock(&ts->lock); > + return IRQ_HANDLED; > +} > + > +static ssize_t tsc_cal_show(struct device *dev, struct device_attribute *attr, > + char *buf) > +{ > + struct tsc_data *ts = dev_get_drvdata(dev); > + ssize_t len = 0; > + int i; > + > + for (i = 0; i < 6; i++) > + len += snprintf(buf+len, PAGE_SIZE-len, "%d ", ts->cal[i]); > + > + len += snprintf(buf+len, PAGE_SIZE-len, "%d\n", ts->cal[6]); > + > + return len; > +} > + > +/* > + * The calibration data format is identical to the contents of tslib's > + * generated output > + */ > +static ssize_t tsc_cal_store(struct device *dev, struct device_attribute *attr, > + const char *buf, size_t count) > +{ > + struct tsc_data *ts = dev_get_drvdata(dev); > + int index = 0; > + int cal[TSC_CAL_SIZE]; > + const char *cur = buf, *end = buf + count; > + char *tmp; > + unsigned long flags; > + > + for (index = 0; index < TSC_CAL_SIZE; index++) { > + while (isspace(*cur) && cur < end) > + cur++; > + if (cur >= end) { > + dev_err(ts->dev, "premature end in calib data\n"); > + return -EINVAL; > + } > + > + if (isdigit(*cur) || *cur == '-') { > + cal[index] = simple_strtol(cur, &tmp, 0); > + cur = tmp; > + } > + } > + > + spin_lock_irqsave(&ts->lock, flags); > + memcpy(ts->cal, cal, sizeof(cal)); > + spin_unlock_irqrestore(&ts->lock, flags); > + > + return count; Calibration should be handled in userspace. Tslib soes it as far as I know. > +} > + > +static struct device_attribute tsc_attr_cal = > + __ATTR(tscal, S_IWUSR | S_IRUGO, tsc_cal_show, tsc_cal_store); > + > +static int tsc_probe(struct platform_device *pdev) > +{ > + struct tnetv107x_tsc_data *pdata = pdev->dev.platform_data; > + struct tsc_data *ts; > + int ret = 0, *cal; > + u32 rev = 0, val = 0; > + struct device *dev = &pdev->dev; > + > + if (!pdata) { > + dev_err(dev, "could not find platform data\n"); > + return -EINVAL; > + } > + > + ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL); > + if (!ts) { > + dev_err(dev, "cannot allocate device info\n"); > + return -ENOMEM; > + } > + > + ts->dev = dev; > + ts->data = *pdata; > + dev_set_drvdata(dev, ts); > + > + cal = (tscal_set == TSC_CAL_SIZE) ? tscal : ts->data.calibration_data; > + memcpy(ts->cal, cal, TSC_CAL_SIZE * sizeof(int)); > + > + ret = -ENOMEM; > + ts->input_dev = input_allocate_device(); > + if (!ts->input_dev) { > + dev_err(dev, "cannot allocate input device\n"); > + goto error0; > + } > + > + ret = -ENODEV; > + ts->tsc_irq = platform_get_irq(pdev, 0); > + if (ts->tsc_irq < 0) { > + dev_err(dev, "cannot determine device interrupt\n"); > + goto error1; > + } > + > + ret = -ENODEV; > + ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!ts->res) { > + dev_err(dev, "cannot determine register area\n"); > + goto error1; > + } > + > + ret = -EINVAL; > + if (!request_mem_region(ts->res->start, resource_size(ts->res), > + pdev->name)) { > + dev_err(dev, "cannot claim register memory\n"); > + goto error1; > + } > + > + ret = -ENOMEM; > + ts->regs = ioremap(ts->res->start, resource_size(ts->res)); > + if (!ts->regs) { > + dev_err(dev, "cannot map register memory\n"); > + goto error2; > + } > + > + ret = -EINVAL; > + ts->clk = clk_get(dev, NULL); > + if (!ts->clk) { > + dev_err(dev, "cannot claim device clock\n"); > + goto error3; > + } > + clk_enable(ts->clk); > + > + spin_lock_init(&ts->lock); > + > + init_timer(&ts->timer); > + setup_timer(&ts->timer, tsc_poll, (unsigned long)ts); init_timer() is extra if you call setu_timer(); > + > + /* Go to idle mode, before any initialization */ > + while ((tsc_read(ts, tscm) & IDLE) == 0) > + barrier(); Hm, I do not see how barrier() would help here... > + > + /* Configure the TSC Control register*/ > + val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN); > + tsc_write(ts, tscm, val); > + > + /* Bring TSC out of reset: Clear AFE reset bit */ > + val &= ~(AFERST); > + tsc_write(ts, tscm, val); > + udelay(10); > + > + /* Configure all pins for hardware control*/ > + tsc_write(ts, bwcm, 0); > + > + /* Finally enable the TSC */ > + tsc_set_bits(ts, tscm, TSC_EN); Should it be in ->open() method? > + > + ret = -EINVAL; > + if (request_irq(ts->tsc_irq, tsc_irq, 0, "tnetv107x-ts", ts)) { > + dev_err(dev, "Could not allocate ts irq\n"); > + goto error4; > + } > + > + ret = device_create_file(ts->dev, &tsc_attr_cal); > + if (ret < 0) { > + dev_err(dev, "Could not create sysfs entry!\n"); > + goto error5; > + } > + > + rev = tsc_read(ts, rev); > + ts->input_dev->name = "tnetv107x-ts"; > + ts->input_dev->phys = "tnetv107x-ts/input0"; > + ts->input_dev->id.bustype = BUS_HOST; > + ts->input_dev->id.vendor = 0x0001; > + ts->input_dev->id.product = ((rev >> 8) & 0x07); > + ts->input_dev->id.version = ((rev >> 16) & 0xfff); > + ts->input_dev->dev.parent = &pdev->dev; > + > + /* Declare capabilities */ > + set_bit(EV_KEY, ts->input_dev->evbit); > + set_bit(BTN_TOUCH, ts->input_dev->keybit); > + set_bit(EV_ABS, ts->input_dev->evbit); > + set_bit(ABS_X, ts->input_dev->absbit); > + set_bit(ABS_Y, ts->input_dev->absbit); > + set_bit(ABS_PRESSURE, ts->input_dev->absbit); > + > + input_set_abs_params(ts->input_dev, ABS_X, 0, ts->data.xres, 5, 0); > + input_set_abs_params(ts->input_dev, ABS_Y, 0, ts->data.yres, 5, 0); > + input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0); > + > + ret = input_register_device(ts->input_dev); > + if (ret < 0) > + goto error6; > + > + return 0; > + > +error6: > + device_remove_file(ts->dev, &tsc_attr_cal); > +error5: > + free_irq(ts->tsc_irq, ts); > +error4: > + clk_disable(ts->clk); > + clk_put(ts->clk); > +error3: > + iounmap(ts->regs); > +error2: > + release_mem_region(ts->res->start, resource_size(ts->res)); > +error1: > + input_free_device(ts->input_dev); > +error0: > + kfree(ts); > + dev_set_drvdata(dev, NULL); > + return ret; > +} > + > +static int tsc_remove(struct platform_device *pdev) > +{ > + struct tsc_data *ts = dev_get_drvdata(&pdev->dev); platform_get_drvdata(); > + > + if (!ts) > + return 0; Impossible. > + > + tsc_clr_bits(ts, tscm, TSC_EN); I think this should be in ->close(). > + del_timer_sync(&ts->timer); > + device_remove_file(ts->dev, &tsc_attr_cal); > + free_irq(ts->tsc_irq, ts); > + clk_disable(ts->clk); > + clk_put(ts->clk); > + iounmap(ts->regs); > + release_mem_region(ts->res->start, resource_size(ts->res)); > + input_free_device(ts->input_dev); Should be input_unregister_device(). > + kfree(ts); > + dev_set_drvdata(&pdev->dev, NULL); platform_set_drvdata(). > + return 0; > +} > + > +static int tsc_suspend(struct platform_device *pdev, pm_message_t state) > +{ > + /* Nothing yet */ > + return 0; > +} > + > +static int tsc_resume(struct platform_device *pdev) > +{ > + /* Nothing yet */ > + return 0; > +} > + Drop these. > +static struct platform_driver tsc_driver = { > + .probe = tsc_probe, > + .remove = tsc_remove, > + .suspend = tsc_suspend, > + .resume = tsc_resume, > + .driver.name = "tnetv107x-ts", Please set up driver.owner. > +}; > + > +static int __init tsc_init(void) > +{ > + return platform_driver_register(&tsc_driver); > +} > + > +static void __exit tsc_exit(void) > +{ > + platform_driver_unregister(&tsc_driver); > +} > + > +module_init(tsc_init); > +module_exit(tsc_exit); > + > +MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); > +MODULE_LICENSE("GPL"); MODULE_AUTHOR() and MODULE_ALIAS(). Thanks. -- Dmitry From dmitry.torokhov at gmail.com Thu Sep 16 13:11:56 2010 From: dmitry.torokhov at gmail.com (Dmitry Torokhov) Date: Thu, 16 Sep 2010 11:11:56 -0700 Subject: [PATCH 0/7] add tnetv107x input drivers In-Reply-To: <87vd658thn.fsf@deeprootsystems.com> References: <1284395388-32687-1-git-send-email-cyril@ti.com> <87vd658thn.fsf@deeprootsystems.com> Message-ID: <201009161111.56465.dmitry.torokhov@gmail.com> On Thursday, September 16, 2010 10:53:56 am Kevin Hilman wrote: > Cyril Chemparathy writes: > > Texas Instruments' TNETV107X is an ARM1176 based SoC, with on-chip > > touchscreen and keypad controllers. This patch series adds drivers for > > these controllers. > > Dmitry, > > With you're review/ack, I can merge these via the davinci tree so the > drivers can merge with the platform code that goes with them. That way > we can avoid potential conflicts from other davinci changes touching the > same platform files. Kevin, I am OK with the drivers coming through your tree, however I am not yet completely happy with the patches (as they were posted - their initial version). Thanks. -- Dmitry From dmitry.torokhov at gmail.com Sun Sep 19 19:03:46 2010 From: dmitry.torokhov at gmail.com (Dmitry Torokhov) Date: Sun, 19 Sep 2010 17:03:46 -0700 Subject: [PATCH v2 1/5] input: add driver for tnetv107x on-chip keypad controller In-Reply-To: <1284666884-10374-2-git-send-email-cyril@ti.com> References: <1284666884-10374-1-git-send-email-cyril@ti.com> <1284666884-10374-2-git-send-email-cyril@ti.com> Message-ID: <20100920000345.GD6565@core.coreip.homeip.net> Hi Cyril, Thank you for making changes. Some more comments below. On Thu, Sep 16, 2010 at 03:54:40PM -0400, Cyril Chemparathy wrote: > This patch adds support for tnetv107x's on-chip keypad controller. > > Signed-off-by: Cyril Chemparathy > --- > drivers/input/keyboard/Kconfig | 9 + > drivers/input/keyboard/Makefile | 1 + > drivers/input/keyboard/tnetv107x-keypad.c | 329 +++++++++++++++++++++++++++++ > 3 files changed, 339 insertions(+), 0 deletions(-) > create mode 100644 drivers/input/keyboard/tnetv107x-keypad.c > > diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig > index 9cc488d..df1facb 100644 > --- a/drivers/input/keyboard/Kconfig > +++ b/drivers/input/keyboard/Kconfig > @@ -424,6 +424,15 @@ config KEYBOARD_OMAP > To compile this driver as a module, choose M here: the > module will be called omap-keypad. > > +config KEYBOARD_TNETV107X > + tristate "TI TNETV107X keypad support" > + depends on ARCH_DAVINCI_TNETV107X > + help > + Say Y here if you want to use the TNETV107X keypad. > + > + To compile this driver as a module, choose M here: the > + module will be called tnetv107x-keypad. > + > config KEYBOARD_TWL4030 > tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" > depends on TWL4030_CORE > diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile > index 504b591..dc04518 100644 > --- a/drivers/input/keyboard/Makefile > +++ b/drivers/input/keyboard/Makefile > @@ -38,6 +38,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o > obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o > obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o > obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o > +obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o > obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o > obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o > obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o > diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c > new file mode 100644 > index 0000000..c262cb4 > --- /dev/null > +++ b/drivers/input/keyboard/tnetv107x-keypad.c > @@ -0,0 +1,329 @@ > +/* > + * Texas Instruments TNETV107X Keypad Driver > + * > + * Copyright (C) 2010 Texas Instruments > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed "as is" WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define BITS(x) (BIT(x) - 1) > + > +#define KEYPAD_ROWS 9 > +#define KEYPAD_COLS 9 > + > +#define DEBOUNCE_MIN BIT(10) > +#define DEBOUNCE_MAX BITS(30) > + > +struct keypad_regs { > + u32 rev; > + u32 mode; > + u32 mask; > + u32 pol; > + u32 dclock; > + u32 rclock; > + u32 stable_cnt; > + u32 in_en; > + u32 out; > + u32 out_en; > + u32 in; > + u32 lock; > + u32 pres[3]; > +}; > + > +#define keypad_read(kp, reg) __raw_readl(&(kp)->regs->reg) > +#define keypad_write(kp, reg, val) __raw_writel(val, &(kp)->regs->reg) > + > +struct keypad_data { > + struct input_dev *input_dev; > + struct resource *res; > + struct keypad_regs __iomem *regs; > + struct clk *clk; > + struct device *dev; > + u32 irq_press; > + u32 irq_release; > + int rows, cols, row_shift; > + int debounce_ms, active_low; > + unsigned short *keycodes; > + u32 prev_keys[3]; > +}; > + > +static irqreturn_t keypad_irq(int irq, void *data) > +{ > + struct keypad_data *kp = (struct keypad_data *)data; No need to cast. > + int i, bit, val, row, col, code; > + u32 curr_keys[3]; > + u32 change; > + > + memset(curr_keys, 0, sizeof(curr_keys)); > + if (irq == kp->irq_press) > + for (i = 0; i < 3; i++) > + curr_keys[i] = keypad_read(kp, pres[i]); > + > + for (i = 0; i < 3; i++) { > + change = curr_keys[i] ^ kp->prev_keys[i]; > + > + while (change) { > + bit = fls(change) - 1; > + change ^= BIT(bit); > + val = curr_keys[i] & BIT(bit); > + bit += i * 32; > + row = bit / KEYPAD_COLS; > + col = bit % KEYPAD_COLS; > + > + code = MATRIX_SCAN_CODE(row, col, kp->row_shift); > + input_event(kp->input_dev, EV_MSC, MSC_SCAN, code); > + input_report_key(kp->input_dev, kp->keycodes[code], > + val); > + } > + } > + input_sync(kp->input_dev); > + memcpy(kp->prev_keys, curr_keys, sizeof(curr_keys)); > + > + if (irq == kp->irq_press) > + keypad_write(kp, lock, 0); /* Allow hardware updates */ > + > + return IRQ_HANDLED; > +} > + > +static int keypad_start(struct input_dev *dev) > +{ > + struct keypad_data *kp = input_get_drvdata(dev); > + unsigned long mask, debounce, clk_rate_khz; > + int error; > + > + clk_enable(kp->clk); > + clk_rate_khz = clk_get_rate(kp->clk) / 1000; > + > + /* Initialize device registers */ > + keypad_write(kp, mode, 0); > + > + mask = BITS(kp->rows) << KEYPAD_COLS; > + mask |= BITS(kp->cols); > + keypad_write(kp, mask, ~mask); > + > + keypad_write(kp, pol, kp->active_low ? 0 : 0x3ffff); > + debounce = kp->debounce_ms * clk_rate_khz; > + debounce = min(debounce, DEBOUNCE_MAX); > + debounce = max(debounce, DEBOUNCE_MIN); debounce = clamp(debounce, DEBOUNCE_MIN, DEBOUNCE_MAX); Also I think defining DEBOUNCE_MIN and DEBOUNCE_MAX via BIT() is confusing (I was expecting to see some bitwise ops); just use a constant. > + keypad_write(kp, dclock, debounce); > + keypad_write(kp, rclock, 4 * debounce); > + keypad_write(kp, stable_cnt, 3); > + keypad_write(kp, in_en, 1); > + > + error = request_irq(kp->irq_press, keypad_irq, 0, "key-press", kp); > + if (error < 0) { > + dev_err(kp->dev, "Could not allocate keypad press key irq\n"); > + clk_disable(kp->clk); > + return error; > + } > + > + error = request_irq(kp->irq_release, keypad_irq, 0, "key-release", kp); > + if (error < 0) { > + dev_err(kp->dev, "Could not allocate keypad release key irq\n"); > + free_irq(kp->irq_press, kp); > + clk_disable(kp->clk); > + return error; > + } > + Request IRQ should go into keypad_probe(). The split is as follows - if possible probe() should leave the device fully ready (all needed resources acquired) but inactive, and open() should just activate the device. > + return 0; > +} > + > +static void keypad_stop(struct input_dev *dev) > +{ > + struct keypad_data *kp = input_get_drvdata(dev); > + > + free_irq(kp->irq_press, kp); > + free_irq(kp->irq_release, kp); > + clk_disable(kp->clk); > +} > + > +static int __devinit keypad_probe(struct platform_device *pdev) > +{ > + const struct matrix_keypad_platform_data *pdata; > + const struct matrix_keymap_data *keymap_data; > + struct device *dev = &pdev->dev; > + struct keypad_data *kp; > + int error = 0, sz; > + u32 rev = 0; > + > + pdata = pdev->dev.platform_data; > + if (!pdata) { > + dev_err(dev, "cannot find device data\n"); > + return -EINVAL; > + } > + > + keymap_data = pdata->keymap_data; > + if (!keymap_data) { > + dev_err(dev, "cannot find keymap data\n"); > + return -EINVAL; > + } > + > + kp = kzalloc(sizeof(struct keypad_data), GFP_KERNEL); > + if (!kp) { > + dev_err(dev, "cannot allocate device info\n"); > + return -ENOMEM; > + } > + > + kp->dev = dev; > + kp->rows = pdata->num_row_gpios; > + kp->cols = pdata->num_col_gpios; > + kp->row_shift = get_count_order(kp->cols); > + platform_set_drvdata(pdev, kp); > + > + sz = (kp->rows << kp->row_shift) * sizeof(*kp->keycodes); > + kp->keycodes = kzalloc(sz, GFP_KERNEL); > + if (!kp->keycodes) { > + dev_err(dev, "cannot allocate keymap info\n"); > + error = -ENOMEM; > + goto error; > + } Why don't you allocate keymap together with the keypad structure: struct keypad_data { ... u32 prev_keys[3]; unsigned short keycodes[]; }; keymap_size = (pdata->num_row_gpios << get_order(pdata->num_col_gpios)) * sizeof(unsigned short); kp = kzalloc(sizeof(struct keypad_data) + keymap_size, GFP_KERNEL); ... > + > + kp->irq_press = platform_get_irq_byname(pdev, "press"); > + kp->irq_release = platform_get_irq_byname(pdev, "release"); > + if (kp->irq_press < 0 || kp->irq_release < 0) { > + dev_err(dev, "cannot determine device interrupts\n"); > + error = -ENODEV; > + goto error; > + } > + > + kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!kp->res) { > + dev_err(dev, "cannot determine register area\n"); > + error = -ENODEV; > + goto error; > + } > + > + if (!request_mem_region(kp->res->start, resource_size(kp->res), > + pdev->name)) { > + dev_err(dev, "cannot claim register memory\n"); > + kp->res = NULL; > + error = -EINVAL; > + goto error; > + } > + > + kp->regs = ioremap(kp->res->start, resource_size(kp->res)); > + if (!kp->regs) { > + dev_err(dev, "cannot map register memory\n"); > + error = -ENOMEM; > + goto error; > + } > + > + kp->clk = clk_get(dev, NULL); > + if (!kp->clk) { > + dev_err(dev, "cannot claim device clock\n"); > + error = -EINVAL; > + goto error; > + } > + > + kp->input_dev = input_allocate_device(); > + if (!kp->input_dev) { > + dev_err(dev, "cannot allocate input device\n"); > + error = -ENOMEM; > + goto error; > + } > + input_set_drvdata(kp->input_dev, kp); > + > + kp->input_dev->name = pdev->name; > + kp->input_dev->dev.parent = &pdev->dev; > + kp->input_dev->open = keypad_start; > + kp->input_dev->close = keypad_stop; > + kp->input_dev->evbit[0] = BIT_MASK(EV_KEY); > + if (!pdata->no_autorepeat) > + kp->input_dev->evbit[0] |= BIT_MASK(EV_REP); > + > + clk_enable(kp->clk); > + rev = keypad_read(kp, rev); > + kp->input_dev->id.bustype = BUS_HOST; > + kp->input_dev->id.product = ((rev >> 8) & 0x07); > + kp->input_dev->id.version = ((rev >> 16) & 0xfff); > + clk_disable(kp->clk); > + > + kp->input_dev->keycode = kp->keycodes; > + kp->input_dev->keycodesize = sizeof(*kp->keycodes); > + kp->input_dev->keycodemax = kp->rows << kp->row_shift; > + > + matrix_keypad_build_keymap(keymap_data, kp->row_shift, kp->keycodes, > + kp->input_dev->keybit); > + > + input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN); > + > + error = input_register_device(kp->input_dev); > + if (error < 0) { > + dev_err(dev, "Could not register input device\n"); > + goto error; > + } > + > + return 0; > + > +error: > + if (kp->input_dev) > + input_free_device(kp->input_dev); > + if (kp->clk) > + clk_put(kp->clk); > + if (kp->regs) > + iounmap(kp->regs); > + if (kp->res) > + release_mem_region(kp->res->start, resource_size(kp->res)); I generally prefer having multiple error path labels instead of checking the state. > + platform_set_drvdata(pdev, NULL); > + kfree(kp->keycodes); > + kfree(kp); > + return error; > +} > + > +static int __devexit keypad_remove(struct platform_device *pdev) > +{ > + struct keypad_data *kp = platform_get_drvdata(pdev); > + > + input_unregister_device(kp->input_dev); > + clk_put(kp->clk); > + iounmap(kp->regs); > + release_mem_region(kp->res->start, resource_size(kp->res)); > + platform_set_drvdata(pdev, NULL); > + kfree(kp->keycodes); > + kfree(kp); > + > + return 0; > +} > + > +static struct platform_driver keypad_driver = { > + .probe = keypad_probe, > + .remove = keypad_remove, > + .driver.name = "tnetv107x-keypad", > + .driver.owner = THIS_MODULE, > +}; > + > +static int __init keypad_init(void) > +{ > + return platform_driver_register(&keypad_driver); > +} > + > +static void __exit keypad_exit(void) > +{ > + platform_driver_unregister(&keypad_driver); > +} > + > +module_init(keypad_init); > +module_exit(keypad_exit); > + > +MODULE_AUTHOR("Cyril Chemparathy"); > +MODULE_DESCRIPTION("TNETV107X Keypad Driver"); > +MODULE_ALIAS("platform: tnetv107x-keypad"); > +MODULE_LICENSE("GPL"); > -- > 1.7.0.4 > Thanks. -- Dmitry From dmitry.torokhov at gmail.com Sun Sep 19 19:16:14 2010 From: dmitry.torokhov at gmail.com (Dmitry Torokhov) Date: Sun, 19 Sep 2010 17:16:14 -0700 Subject: [PATCH v2 4/5] input: add driver for tnetv107x touchscreen controller In-Reply-To: <1284666884-10374-5-git-send-email-cyril@ti.com> References: <1284666884-10374-1-git-send-email-cyril@ti.com> <1284666884-10374-5-git-send-email-cyril@ti.com> Message-ID: <20100920001614.GE6565@core.coreip.homeip.net> Hi Cyril, On Thu, Sep 16, 2010 at 03:54:43PM -0400, Cyril Chemparathy wrote: > This patch adds support for tnetv107x's on-chip touchscreen controller. > Similar comments as with the keypad plus some more: > Signed-off-by: Cyril Chemparathy > --- > drivers/input/touchscreen/Kconfig | 9 + > drivers/input/touchscreen/Makefile | 1 + > drivers/input/touchscreen/tnetv107x-ts.c | 401 ++++++++++++++++++++++++++++++ > 3 files changed, 411 insertions(+), 0 deletions(-) > create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c > > diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig > index 0069d97..8d32028 100644 > --- a/drivers/input/touchscreen/Kconfig > +++ b/drivers/input/touchscreen/Kconfig > @@ -328,6 +328,15 @@ config TOUCHSCREEN_MIGOR > To compile this driver as a module, choose M here: the > module will be called migor_ts. > > +config TOUCHSCREEN_TNETV107X > + tristate "TI TNETV107X touchscreen support" > + depends on ARCH_DAVINCI_TNETV107X > + help > + Say Y here if you want to use the TNETV107X touchscreen. > + > + To compile this driver as a module, choose M here: the > + module will be called tnetv107x-ts. > + > config TOUCHSCREEN_TOUCHRIGHT > tristate "Touchright serial touchscreen" > select SERIO > diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile > index 28217e1..d41a964 100644 > --- a/drivers/input/touchscreen/Makefile > +++ b/drivers/input/touchscreen/Makefile > @@ -37,6 +37,7 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o > obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o > obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o > obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o > +obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o > obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o > obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o > obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o > diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c > new file mode 100644 > index 0000000..0d4dbc4 > --- /dev/null > +++ b/drivers/input/touchscreen/tnetv107x-ts.c > @@ -0,0 +1,401 @@ > +/* > + * Texas Instruments TNETV107X Touchscreen Driver > + * > + * Copyright (C) 2010 Texas Instruments > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed "as is" WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#define TSC_PENUP_POLL (HZ / 5) > +#define IDLE_TIMEOUT 100 /* msec */ > + > +/* > + * The first and last samples of a touch interval are usually garbage and need > + * to be filtered out with these devices. The following definitions control > + * the number of samples skipped. > + */ > +#define TSC_HEAD_SKIP 1 > +#define TSC_TAIL_SKIP 1 > +#define TSC_SKIP (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1) > +#define TSC_SAMPLES (TSC_SKIP + 1) > + > +/* Register Offsets */ > +struct tsc_regs { > + u32 rev; > + u32 tscm; > + u32 bwcm; > + u32 swc; > + u32 adcchnl; > + u32 adcdata; > + u32 chval[4]; > +}; > + > +/* TSC Mode Configuration Register (tscm) bits */ > +#define WMODE BIT(0) > +#define TSKIND BIT(1) > +#define ZMEASURE_EN BIT(2) > +#define IDLE BIT(3) > +#define TSC_EN BIT(4) > +#define STOP BIT(5) > +#define ONE_SHOT BIT(6) > +#define SINGLE BIT(7) > +#define AVG BIT(8) > +#define AVGNUM(x) (((x) & 0x03) << 9) > +#define PVSTC(x) (((x) & 0x07) << 11) > +#define PON BIT(14) > +#define PONBG BIT(15) > +#define AFERST BIT(16) > + > +/* ADC DATA Capture Register bits */ > +#define DATA_VALID BIT(16) > + > +/* Register Access Macros */ > +#define tsc_read(ts, reg) __raw_readl(&(ts)->regs->reg) > +#define tsc_write(ts, reg, val) __raw_writel(val, &(ts)->regs->reg); > +#define tsc_set_bits(ts, reg, val) \ > + tsc_write(ts, reg, tsc_read(ts, reg) | (val)) > +#define tsc_clr_bits(ts, reg, val) \ > + tsc_write(ts, reg, tsc_read(ts, reg) & ~(val)) > + > +struct sample { > + int x, y, p; > +}; > + > +struct tsc_data { > + struct input_dev *input_dev; > + struct resource *res; > + struct tsc_regs __iomem *regs; > + struct timer_list timer; > + spinlock_t lock; > + struct clk *clk; > + struct device *dev; > + int sample_count; > + struct sample samples[TSC_SAMPLES]; > + int tsc_irq; > +}; > + > +static int tsc_read_sample(struct tsc_data *ts, struct sample* sample) > +{ > + int x, y, z1, z2, t, p = 0; > + u32 val; > + > + val = tsc_read(ts, chval[0]); > + if (val & DATA_VALID) > + x = val & 0xffff; > + else > + return -EINVAL; > + > + y = tsc_read(ts, chval[1]) & 0xffff; > + z1 = tsc_read(ts, chval[2]) & 0xffff; > + z2 = tsc_read(ts, chval[3]) & 0xffff; > + > + if (z1) { > + t = ((600 * x) * (z2 - z1)); > + p = t / (u32) (z1 << 12); > + if (p < 0) > + p = 0; > + } > + > + sample->x = x; > + sample->y = y; > + sample->p = p; > + > + return 0; > +} > + > +static void tsc_poll(unsigned long data) > +{ > + struct tsc_data *ts = (struct tsc_data *)data; > + unsigned long flags; > + int i, val, x, y, p; > + > + spin_lock_irqsave(&ts->lock, flags); > + > + if (ts->sample_count >= TSC_SKIP) { > + input_report_abs(ts->input_dev, ABS_PRESSURE, 0); > + input_report_key(ts->input_dev, BTN_TOUCH, 0); > + input_sync(ts->input_dev); > + } else if (ts->sample_count > 0) { > + /* > + * A touch event lasted less than our skip count. Salvage and > + * report anyway. > + */ > + for (i = 0, val = 0; i < ts->sample_count; i++) > + val += ts->samples[i].x; > + x = val / ts->sample_count; > + > + for (i = 0, val = 0; i < ts->sample_count; i++) > + val += ts->samples[i].y; > + y = val / ts->sample_count; > + > + for (i = 0, val = 0; i < ts->sample_count; i++) > + val += ts->samples[i].p; > + p = val / ts->sample_count; > + > + input_report_abs(ts->input_dev, ABS_X, x); > + input_report_abs(ts->input_dev, ABS_Y, y); > + input_report_abs(ts->input_dev, ABS_PRESSURE, p); > + input_report_key(ts->input_dev, BTN_TOUCH, 1); > + input_sync(ts->input_dev); > + } > + > + ts->sample_count = 0; > + > + spin_unlock_irqrestore(&ts->lock, flags); > +} > + > +static irqreturn_t tsc_irq(int irq, void *dev_id) > +{ > + struct tsc_data *ts = (struct tsc_data *)dev_id; > + struct sample *sample; > + int index; > + > + spin_lock(&ts->lock); > + > + index = ts->sample_count % TSC_SAMPLES; > + sample = &ts->samples[index]; > + if (tsc_read_sample(ts, sample) >= 0) { > + ++ts->sample_count; > + > + if (ts->sample_count < TSC_SKIP) > + goto done; > + > + index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES; > + sample = &ts->samples[index]; > + > + input_report_abs(ts->input_dev, ABS_X, sample->x); > + input_report_abs(ts->input_dev, ABS_Y, sample->y); > + input_report_abs(ts->input_dev, ABS_PRESSURE, sample->p); > + if (ts->sample_count == TSC_SKIP) > + input_report_key(ts->input_dev, BTN_TOUCH, 1); > + input_sync(ts->input_dev); > +done: > + mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL); > + } > + > + spin_unlock(&ts->lock); > + return IRQ_HANDLED; > +} Extremely minor nit but I'd prefer: if (tsc_read_sample(ts, sample) < 0) goto out; if (++ts->sample_count >= TSC_SKIP) { ... } mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL); out: spin_unlock(&ts->lock); return IRQ_HANDLED; > + > +static int tsc_start(struct input_dev *dev) > +{ > + struct tsc_data *ts = input_get_drvdata(dev); > + unsigned long timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT); > + u32 val; > + int error; > + > + clk_enable(ts->clk); > + > + /* Go to idle mode, before any initialization */ > + while (time_after(timeout, jiffies)) { > + if (tsc_read(ts, tscm) & IDLE) > + break; > + } > + > + if (time_before(timeout, jiffies)) { > + dev_warn(ts->dev, "timeout waiting for idle\n"); > + clk_disable(ts->clk); > + return -EIO; > + } > + > + /* Configure TSC Control register*/ > + val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN); > + tsc_write(ts, tscm, val); > + > + /* Bring TSC out of reset: Clear AFE reset bit */ > + val &= ~(AFERST); > + tsc_write(ts, tscm, val); > + udelay(10); > + > + /* Configure all pins for hardware control*/ > + tsc_write(ts, bwcm, 0); > + > + /* Finally enable the TSC */ > + tsc_set_bits(ts, tscm, TSC_EN); > + > + error = request_irq(ts->tsc_irq, tsc_irq, 0, "tnetv107x-ts", ts); > + if (error < 0) { > + dev_err(ts->dev, "Could not allocate ts irq\n"); > + clk_disable(ts->clk); > + return error; > + } > + > + return 0; > +} > + > +static void tsc_stop(struct input_dev *dev) > +{ > + struct tsc_data *ts = input_get_drvdata(dev); > + > + tsc_clr_bits(ts, tscm, TSC_EN); > + del_timer_sync(&ts->timer); > + free_irq(ts->tsc_irq, ts); > + clk_disable(ts->clk); I think the close sequence should be: tsc_clr_bits(ts, tscm, TSC_EN); synchronize_irq(ts->tsc_irq); /* No new IRQs past this point, shut off the timer */ del_timer_sync(&ts->timer); > +} > + > +static int __devinit tsc_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct tsc_data *ts; > + int error = 0; > + u32 rev = 0; > + > + ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL); > + if (!ts) { > + dev_err(dev, "cannot allocate device info\n"); > + return -ENOMEM; > + } > + > + ts->dev = dev; > + spin_lock_init(&ts->lock); > + setup_timer(&ts->timer, tsc_poll, (unsigned long)ts); > + platform_set_drvdata(pdev, ts); > + > + ts->tsc_irq = platform_get_irq(pdev, 0); > + if (ts->tsc_irq < 0) { > + dev_err(dev, "cannot determine device interrupt\n"); > + error = -ENODEV; > + goto error; > + } > + > + ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!ts->res) { > + dev_err(dev, "cannot determine register area\n"); > + error = -ENODEV; > + goto error; > + } > + > + if (!request_mem_region(ts->res->start, resource_size(ts->res), > + pdev->name)) { > + dev_err(dev, "cannot claim register memory\n"); > + ts->res = NULL; > + error = -EINVAL; > + goto error; > + } > + > + ts->regs = ioremap(ts->res->start, resource_size(ts->res)); > + if (!ts->regs) { > + dev_err(dev, "cannot map register memory\n"); > + error = -ENOMEM; > + goto error; > + } > + > + ts->clk = clk_get(dev, NULL); > + if (!ts->clk) { > + dev_err(dev, "cannot claim device clock\n"); > + error = -EINVAL; > + goto error; > + } > + > + ts->input_dev = input_allocate_device(); > + if (!ts->input_dev) { > + dev_err(dev, "cannot allocate input device\n"); > + error = -ENOMEM; > + goto error; > + } > + input_set_drvdata(ts->input_dev, ts); > + > + ts->input_dev->name = pdev->name; > + ts->input_dev->id.bustype = BUS_HOST; > + ts->input_dev->dev.parent = &pdev->dev; > + ts->input_dev->open = tsc_start; > + ts->input_dev->close = tsc_stop; > + > + clk_enable(ts->clk); > + rev = tsc_read(ts, rev); > + ts->input_dev->id.product = ((rev >> 8) & 0x07); > + ts->input_dev->id.version = ((rev >> 16) & 0xfff); > + clk_disable(ts->clk); > + > + set_bit(EV_KEY, ts->input_dev->evbit); > + set_bit(EV_ABS, ts->input_dev->evbit); > + set_bit(BTN_TOUCH, ts->input_dev->keybit); __set_bit(); > + set_bit(ABS_X, ts->input_dev->absbit); > + set_bit(ABS_Y, ts->input_dev->absbit); > + set_bit(ABS_PRESSURE, ts->input_dev->absbit); input_set_abs_params() already takes care of setting bits. > + > + input_set_abs_params(ts->input_dev, ABS_X, 0, 0xffff, 5, 0); > + input_set_abs_params(ts->input_dev, ABS_Y, 0, 0xffff, 5, 0); > + input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0); > + > + error = input_register_device(ts->input_dev); > + if (error < 0) { > + dev_err(dev, "failed input device registration\n"); > + goto error; > + } > + > + return 0; > + > +error: > + if (ts->clk) > + clk_put(ts->clk); > + if (ts->regs) > + iounmap(ts->regs); > + if (ts->res) > + release_mem_region(ts->res->start, resource_size(ts->res)); > + if (ts->input_dev) > + input_free_device(ts->input_dev); > + platform_set_drvdata(pdev, NULL); > + kfree(ts); > + > + return error; > +} > + > +static int __devexit tsc_remove(struct platform_device *pdev) > +{ > + struct tsc_data *ts = platform_get_drvdata(pdev); > + > + input_unregister_device(ts->input_dev); > + clk_put(ts->clk); > + iounmap(ts->regs); > + release_mem_region(ts->res->start, resource_size(ts->res)); > + platform_set_drvdata(pdev, NULL); > + kfree(ts); > + > + return 0; > +} > + > +static struct platform_driver tsc_driver = { > + .probe = tsc_probe, > + .remove = tsc_remove, > + .driver.name = "tnetv107x-ts", > + .driver.owner = THIS_MODULE, > +}; > + > +static int __init tsc_init(void) > +{ > + return platform_driver_register(&tsc_driver); > +} > + > +static void __exit tsc_exit(void) > +{ > + platform_driver_unregister(&tsc_driver); > +} > + > +module_init(tsc_init); > +module_exit(tsc_exit); > + > +MODULE_AUTHOR("Cyril Chemparathy"); > +MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); > +MODULE_ALIAS("platform: tnetv107x-ts"); > +MODULE_LICENSE("GPL"); > -- > 1.7.0.4 > Thank you. -- Dmitry From alexander at dce.bg Mon Sep 20 00:43:24 2010 From: alexander at dce.bg (Alexander Enchevich) Date: Mon, 20 Sep 2010 08:43:24 +0300 Subject: RAMDISK and BUSYBOX v1.7.2 Issues Message-ID: <4C96F47C.5010601@dce.bg> Hi I was wondering if you or anyone on the list have been able to solve this problem with "Id "con" respawning too fast" ? Here's the thread: http://linux.omap.com/pipermail/davinci-linux-open-source/2007-October/004286.html I am having the same problem with busybox-1.17.2 on sh4-linux system and if you have a solution would be very interested in hearing it. In my case it happens when I start the telnetd daemon... Thanks! Alexander Enchevich Software Eng., Deltacom Electronics Ltd. From dmitry.torokhov at gmail.com Mon Sep 20 10:29:35 2010 From: dmitry.torokhov at gmail.com (Dmitry Torokhov) Date: Mon, 20 Sep 2010 08:29:35 -0700 Subject: [PATCH v3 1/5] input: add driver for tnetv107x on-chip keypad controller In-Reply-To: <1284995252-23337-2-git-send-email-cyril@ti.com> References: <1284995252-23337-1-git-send-email-cyril@ti.com> <1284995252-23337-2-git-send-email-cyril@ti.com> Message-ID: <20100920152935.GA698@core.coreip.homeip.net> Hi Cyril, On Mon, Sep 20, 2010 at 11:07:28AM -0400, Cyril Chemparathy wrote: > This patch adds support for tnetv107x's on-chip keypad controller. > There is one thing that I missed - since you have 2 separate irqs they may execute at the same time on 2 different CPUs (theoretically, if platform will ever have multiple CPUs) so you need to take a spinlock inside the interrupt handler to protect from simultaneous access to shared data. Once you add it please add Acked-by: Dmitry Torokhov and forward it to Kevin so it is merged through his tree. Thanks. -- Dmitry From dmitry.torokhov at gmail.com Mon Sep 20 10:31:39 2010 From: dmitry.torokhov at gmail.com (Dmitry Torokhov) Date: Mon, 20 Sep 2010 08:31:39 -0700 Subject: [PATCH v3 4/5] input: add driver for tnetv107x touchscreen controller In-Reply-To: <1284995252-23337-5-git-send-email-cyril@ti.com> References: <1284995252-23337-1-git-send-email-cyril@ti.com> <1284995252-23337-5-git-send-email-cyril@ti.com> Message-ID: <20100920153138.GB698@core.coreip.homeip.net> On Mon, Sep 20, 2010 at 11:07:31AM -0400, Cyril Chemparathy wrote: > This patch adds support for tnetv107x's on-chip touchscreen controller. > Thank you for makign the changes, looks good now. Acked-by: Dmitry Torokhov -- Dmitry From ben-i2c at fluff.org Tue Sep 21 19:09:16 2010 From: ben-i2c at fluff.org (Ben Dooks) Date: Wed, 22 Sep 2010 01:09:16 +0100 Subject: [PATCH v4] i2c: davinci: Fix race when setting up for TX In-Reply-To: <4C9904E6.7070608@boundarydevices.com> References: <4C97CEC9.8060602@boundarydevices.com> <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> <4C9904E6.7070608@boundarydevices.com> Message-ID: <20100922000916.GH7494@trinity.fluff.org> On Tue, Sep 21, 2010 at 12:17:58PM -0700, Troy Kisky wrote: > On 9/21/2010 4:24 AM, Sudhakar Rajashekhara wrote: > > Hi, > > > > On Tue, Sep 21, 2010 at 09:43:28, Jon Povey wrote: > >> When setting up to transmit, a race exists between the ISR and > >> i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. > >> This is mostly visible for transmits > 1 byte long. > >> > >> The hardware starts sending immediately that MDR.STT is set. IMR trickery > >> doesn't work because if we start sending, finish the first byte and an > >> XRDY event occurs before we load IMR to unmask it, we never get an > >> interrupt, and we timeout. > >> > >> Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode > >> settings before DXR for correct behaviour, so load MDR first with > >> STT cleared and later load again with STT set. > >> > >> Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 > >> > >> Signed-off-by: Jon Povey > >> CC: Sudhakar Rajashekhara > >> CC: Troy Kisky > >> --- > >> Reworked after comments by Troy and Sudhakar. > >> > >> Looking at the datasheet it seemed like setting STP without STT early > >> might cause a stray STOP to be generated, so I moved it into the second > >> MDR load. > >> > >> This passes a quick smoke test but I can't do much more testing right at > >> the moment. Sudhakar, your comments would be welcomed. > >> > > > > Looks good to me. I can test on couple of platforms I have and update the result > > by tomorrow. > > > > Thanks, > > Sudhakar > > > > > > > I like it too. I hope it works for omap. > > Thanks as well > Troy Ok, any objections to this being applied, or should I wait? -- Ben Q: What's a light-year? A: One-third less calories than a regular year. From ben at trinity.fluff.org Fri Sep 24 11:37:54 2010 From: ben at trinity.fluff.org (Ben Dooks) Date: Fri, 24 Sep 2010 17:37:54 +0100 Subject: [PATCH v4] i2c: davinci: Fix race when setting up for TX In-Reply-To: <87sk0zky28.fsf@deeprootsystems.com> References: <4C97CEC9.8060602@boundarydevices.com> <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> <87sk0zky28.fsf@deeprootsystems.com> Message-ID: <20100924163754.GH27885@trinity.fluff.org> On Fri, Sep 24, 2010 at 07:37:03AM -0700, Kevin Hilman wrote: > "Sudhakar Rajashekhara" writes: > > > On Tue, Sep 21, 2010 at 09:43:28, Jon Povey wrote: > >> When setting up to transmit, a race exists between the ISR and > >> i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. > >> This is mostly visible for transmits > 1 byte long. > >> > >> The hardware starts sending immediately that MDR.STT is set. IMR trickery > >> doesn't work because if we start sending, finish the first byte and an > >> XRDY event occurs before we load IMR to unmask it, we never get an > >> interrupt, and we timeout. > >> > >> Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode > >> settings before DXR for correct behaviour, so load MDR first with > >> STT cleared and later load again with STT set. > >> > >> Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 > >> > >> Signed-off-by: Jon Povey > >> CC: Sudhakar Rajashekhara > >> CC: Troy Kisky > >> --- > > > > Tested-by: Sudhakar Rajashekhara > > > > Tested with audio loopback on OMAP-L138, OMAP-L137 and DM365. Also tested with > > i2cdetect function which probes all the devices on the i2c bus. > > > Ben, can you queue this one for 2.6.37 with the addition of: If it is a worthwhile bugfix i'll send it for the next -rc. > Acked-by: Troy Kisky > Tested-by: Sudhakar Rajashekhara > Acked-by: Kevin Hilman > > Thanks, > > Kevin > -- -- Ben Q: What's a light-year? A: One-third less calories than a regular year. From shubhrajyoti at ti.com Tue Sep 14 01:38:42 2010 From: shubhrajyoti at ti.com (Datta, Shubhrajyoti) Date: Tue, 14 Sep 2010 12:08:42 +0530 Subject: [PATCH 5/7] input: add driver for tnetv107x touchscreen controller In-Reply-To: <1284395388-32687-6-git-send-email-cyril@ti.com> References: <1284395388-32687-1-git-send-email-cyril@ti.com> <1284395388-32687-6-git-send-email-cyril@ti.com> Message-ID: <0680EC522D0CC943BC586913CF3768C003C210EEE1@dbde02.ent.ti.com> Hi Cyril, Minor comments/doubts > -----Original Message----- > From: linux-input-owner at vger.kernel.org [mailto:linux-input- > owner at vger.kernel.org] On Behalf Of Chemparathy, Cyril > Sent: Monday, September 13, 2010 10:00 PM > To: linux-input at vger.kernel.org; davinci-linux-open- > source at linux.davincidsp.com > Cc: Chemparathy, Cyril > Subject: [PATCH 5/7] input: add driver for tnetv107x touchscreen > controller > > This patch adds support for tnetv107x's on-chip touchscreen controller. > > Signed-off-by: Cyril Chemparathy > --- > drivers/input/touchscreen/Kconfig | 6 + > drivers/input/touchscreen/Makefile | 1 + > drivers/input/touchscreen/tnetv107x-ts.c | 481 > + > +static inline void tsc_report_up(struct tsc_data *ts) > +{ > + input_report_abs(ts->input_dev, ABS_PRESSURE, 0); > + input_report_key(ts->input_dev, BTN_TOUCH, 0); > + input_sync(ts->input_dev); > +} > + > +static inline void tsc_report(struct tsc_data *ts, int x, int y, int p) > +{ > + input_report_abs(ts->input_dev, ABS_X, x); > + input_report_abs(ts->input_dev, ABS_Y, y); > + input_report_abs(ts->input_dev, ABS_PRESSURE, p); Did not understand why no sync here. > +} > + > +static inline void tsc_report_down(struct tsc_data *ts, bool touch) > +{ > + if (touch) > + input_report_key(ts->input_dev, BTN_TOUCH, 1); Even if you donot report you do a sync. > + input_sync(ts->input_dev); > +} > + > +static inline void tsc_poll(unsigned long data) > +{ > + struct tsc_data *ts = (struct tsc_data *)data; > + unsigned long flags; > + int i, val, x, y, p; > + > + spin_lock_irqsave(&ts->lock, flags); > + > + if (ts->sample_count >= TSC_SKIP) { > + tsc_report_up(ts); > + } else if (ts->sample_count > 0) { > + /* > + * A touch event lasted less than our skip count. Salvage and > + * report anyway. > + */ > + for (i = 0, val = 0; i < ts->sample_count; i++) > + val += ts->samples[i].x; > + x = val / ts->sample_count; > + > + for (i = 0, val = 0; i < ts->sample_count; i++) > + val += ts->samples[i].y; > + y = val / ts->sample_count; > + > + for (i = 0, val = 0; i < ts->sample_count; i++) > + val += ts->samples[i].p; > + p = val / ts->sample_count; > + > + tsc_report(ts, x, y, p); > + tsc_report_down(ts, true); > + } > + > + ts->sample_count = 0; > + > + spin_unlock_irqrestore(&ts->lock, flags); > +} > + > +static irqreturn_t tsc_irq(int irq, void *dev_id) > +{ > + struct tsc_data *ts = (struct tsc_data *)dev_id; > + struct sample *sample; > + int index; > + > + spin_lock(&ts->lock); > + > + index = ts->sample_count % TSC_SAMPLES; > + sample = &ts->samples[index]; > + if (tsc_read_sample(ts, sample) >= 0) { > + ++ts->sample_count; > + > + if (ts->sample_count < TSC_SKIP) > + goto done; > + > + index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES; > + sample = &ts->samples[index]; > + > + tsc_report(ts, sample->x, sample->y, sample->y); > + tsc_report_down(ts, (ts->sample_count == TSC_SKIP)); > +done: > + mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL); > + } > + > + spin_unlock(&ts->lock); > + return IRQ_HANDLED; > +} > + > +static ssize_t tsc_cal_show(struct device *dev, struct device_attribute > *attr, > + char *buf) > +{ > + struct tsc_data *ts = dev_get_drvdata(dev); > + ssize_t len = 0; > + int i; > + > + for (i = 0; i < 6; i++) > + len += snprintf(buf+len, PAGE_SIZE-len, "%d ", ts->cal[i]); > + > + len += snprintf(buf+len, PAGE_SIZE-len, "%d\n", ts->cal[6]); > + > + return len; > +} > + > +/* > + * The calibration data format is identical to the contents of tslib's > + * generated output > + */ > +static ssize_t tsc_cal_store(struct device *dev, struct device_attribute > *attr, > + const char *buf, size_t count) > +{ > + struct tsc_data *ts = dev_get_drvdata(dev); > + int index = 0; > + int cal[TSC_CAL_SIZE]; > + const char *cur = buf, *end = buf + count; > + char *tmp; > + unsigned long flags; > + > + for (index = 0; index < TSC_CAL_SIZE; index++) { > + while (isspace(*cur) && cur < end) > + cur++; > + if (cur >= end) { > + dev_err(ts->dev, "premature end in calib data\n"); > + return -EINVAL; > + } > + > + if (isdigit(*cur) || *cur == '-') { > + cal[index] = simple_strtol(cur, &tmp, 0); > + cur = tmp; > + } > + } > + > + spin_lock_irqsave(&ts->lock, flags); > + memcpy(ts->cal, cal, sizeof(cal)); > + spin_unlock_irqrestore(&ts->lock, flags); > + > + return count; > +} > + > +static struct device_attribute tsc_attr_cal = > + __ATTR(tscal, S_IWUSR | S_IRUGO, tsc_cal_show, tsc_cal_store); > + > +static int tsc_probe(struct platform_device *pdev) May consider __devinit as this memory location may not be needed afterwards. > +{ > + struct tnetv107x_tsc_data *pdata = pdev->dev.platform_data; > + struct tsc_data *ts; > + int ret = 0, *cal; > + u32 rev = 0, val = 0; > + struct device *dev = &pdev->dev; > + > + if (!pdata) { > + dev_err(dev, "could not find platform data\n"); > + return -EINVAL; > + } > + > + ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL); > + if (!ts) { > + dev_err(dev, "cannot allocate device info\n"); > + return -ENOMEM; > + } > + > + ts->dev = dev; > + ts->data = *pdata; > + dev_set_drvdata(dev, ts); > + > + cal = (tscal_set == TSC_CAL_SIZE) ? tscal : ts- > >data.calibration_data; > + memcpy(ts->cal, cal, TSC_CAL_SIZE * sizeof(int)); > + > + ret = -ENOMEM; > + ts->input_dev = input_allocate_device(); > + if (!ts->input_dev) { > + dev_err(dev, "cannot allocate input device\n"); > + goto error0; > + } > + > + ret = -ENODEV; > + ts->tsc_irq = platform_get_irq(pdev, 0); > + if (ts->tsc_irq < 0) { > + dev_err(dev, "cannot determine device interrupt\n"); > + goto error1; > + } > + > + ret = -ENODEV; > + ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!ts->res) { > + dev_err(dev, "cannot determine register area\n"); > + goto error1; > + } > + > + ret = -EINVAL; > + if (!request_mem_region(ts->res->start, resource_size(ts->res), > + pdev->name)) { > + dev_err(dev, "cannot claim register memory\n"); > + goto error1; > + } > + > + ret = -ENOMEM; > + ts->regs = ioremap(ts->res->start, resource_size(ts->res)); > + if (!ts->regs) { > + dev_err(dev, "cannot map register memory\n"); > + goto error2; > + } > + > + ret = -EINVAL; > + ts->clk = clk_get(dev, NULL); > + if (!ts->clk) { > + dev_err(dev, "cannot claim device clock\n"); > + goto error3; > + } > + clk_enable(ts->clk); > + > + spin_lock_init(&ts->lock); > + > + init_timer(&ts->timer); > + setup_timer(&ts->timer, tsc_poll, (unsigned long)ts); > + > + /* Go to idle mode, before any initialization */ > + while ((tsc_read(ts, tscm) & IDLE) == 0) > + barrier(); > + > + /* Configure the TSC Control register*/ > + val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN); > + tsc_write(ts, tscm, val); > + > + /* Bring TSC out of reset: Clear AFE reset bit */ > + val &= ~(AFERST); > + tsc_write(ts, tscm, val); > + udelay(10); > + > + /* Configure all pins for hardware control*/ > + tsc_write(ts, bwcm, 0); > + > + /* Finally enable the TSC */ > + tsc_set_bits(ts, tscm, TSC_EN); > + > + ret = -EINVAL; > + if (request_irq(ts->tsc_irq, tsc_irq, 0, "tnetv107x-ts", ts)) { > + dev_err(dev, "Could not allocate ts irq\n"); > + goto error4; > + } > + > + ret = device_create_file(ts->dev, &tsc_attr_cal); > + if (ret < 0) { > + dev_err(dev, "Could not create sysfs entry!\n"); > + goto error5; > + } > + > + rev = tsc_read(ts, rev); > + ts->input_dev->name = "tnetv107x-ts"; > + ts->input_dev->phys = "tnetv107x-ts/input0"; > + ts->input_dev->id.bustype = BUS_HOST; > + ts->input_dev->id.vendor = 0x0001; > + ts->input_dev->id.product = ((rev >> 8) & 0x07); > + ts->input_dev->id.version = ((rev >> 16) & 0xfff); > + ts->input_dev->dev.parent = &pdev->dev; > + > + /* Declare capabilities */ > + set_bit(EV_KEY, ts->input_dev->evbit); > + set_bit(BTN_TOUCH, ts->input_dev->keybit); > + set_bit(EV_ABS, ts->input_dev->evbit); > + set_bit(ABS_X, ts->input_dev->absbit); > + set_bit(ABS_Y, ts->input_dev->absbit); > + set_bit(ABS_PRESSURE, ts->input_dev->absbit); > + > + input_set_abs_params(ts->input_dev, ABS_X, 0, ts->data.xres, 5, 0); > + input_set_abs_params(ts->input_dev, ABS_Y, 0, ts->data.yres, 5, 0); > + input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0); > + > + ret = input_register_device(ts->input_dev); > + if (ret < 0) > + goto error6; > + > + return 0; > + > +error6: > + device_remove_file(ts->dev, &tsc_attr_cal); > +error5: > + free_irq(ts->tsc_irq, ts); > +error4: > + clk_disable(ts->clk); > + clk_put(ts->clk); > +error3: > + iounmap(ts->regs); > +error2: > + release_mem_region(ts->res->start, resource_size(ts->res)); > +error1: > + input_free_device(ts->input_dev); > +error0: > + kfree(ts); > + dev_set_drvdata(dev, NULL); > + return ret; > +} > + > +static int tsc_remove(struct platform_device *pdev) Same as probe. > +{ > + struct tsc_data *ts = dev_get_drvdata(&pdev->dev); > + > + if (!ts) > + return 0; > + > + tsc_clr_bits(ts, tscm, TSC_EN); > + del_timer_sync(&ts->timer); > + device_remove_file(ts->dev, &tsc_attr_cal); > + free_irq(ts->tsc_irq, ts); > + clk_disable(ts->clk); > + clk_put(ts->clk); > + iounmap(ts->regs); > + release_mem_region(ts->res->start, resource_size(ts->res)); > + input_free_device(ts->input_dev); > + kfree(ts); > + dev_set_drvdata(&pdev->dev, NULL); > + return 0; > +} > + > +static int tsc_suspend(struct platform_device *pdev, pm_message_t state) > +{ > + /* Nothing yet */ > + return 0; > +} > + > +static int tsc_resume(struct platform_device *pdev) > +{ > + /* Nothing yet */ > + return 0; > +} > + > +static struct platform_driver tsc_driver = { > + .probe = tsc_probe, > + .remove = tsc_remove, > + .suspend = tsc_suspend, > + .resume = tsc_resume, > + .driver.name = "tnetv107x-ts", > +}; > + > +static int __init tsc_init(void) > +{ > + return platform_driver_register(&tsc_driver); > +} > + > +static void __exit tsc_exit(void) > +{ > + platform_driver_unregister(&tsc_driver); > +} > + > +module_init(tsc_init); > +module_exit(tsc_exit); > + > +MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); > +MODULE_LICENSE("GPL"); > -- > 1.7.0.4 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-input" in > the body of a message to majordomo at vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html From linus.ml.walleij at gmail.com Tue Sep 28 04:13:02 2010 From: linus.ml.walleij at gmail.com (Linus Walleij) Date: Tue, 28 Sep 2010 11:13:02 +0200 Subject: [PATCH v5 1/3] ARM: add CPPI 4.1 DMA support In-Reply-To: <201005152214.53993.sshtylyov@ru.mvista.com> References: <201005152214.53993.sshtylyov@ru.mvista.com> Message-ID: 2010/5/15 Sergei Shtylyov : > Add support for Texas Instuments Communication Port Programming Interface 4.1 > (CPPI 4.1) used on OMAP-L1x/DA8xx and AM35x. Sorry for late feedback ... > +++ linux-davinci/arch/arm/common/cppi41.c Can you migrate this driver to drivers/dma/cppi41.c and use the DMAengine interface like so many DMA drivers we have created recently, or is there some very special characteristics about this DMA controller meriting it to be placed in arch/arm/*? Note: we have the support for PL08x found in ARM reference designs queued for drivers/dma/amba-pl08x.c, not arch/arm/common/*. The rationale about this is to lower the churn in arch/arm/* and put drivers into the proper subsystems, and in this case there is an appropriate subsystem to be used. Yours, Linus Walleij From shubhrajyoti at ti.com Mon Sep 20 00:38:21 2010 From: shubhrajyoti at ti.com (Datta, Shubhrajyoti) Date: Mon, 20 Sep 2010 11:08:21 +0530 Subject: [PATCH v2 4/5] input: add driver for tnetv107x touchscreen controller In-Reply-To: <1284666884-10374-5-git-send-email-cyril@ti.com> References: <1284666884-10374-1-git-send-email-cyril@ti.com> <1284666884-10374-5-git-send-email-cyril@ti.com> Message-ID: <0680EC522D0CC943BC586913CF3768C003C21EDD85@dbde02.ent.ti.com> Hi Cyril , A few minor points/queries. > -----Original Message----- > From: Chemparathy, Cyril > Sent: Friday, September 17, 2010 1:25 AM > To: linux-input at vger.kernel.org; davinci-linux-open- > source at linux.davincidsp.com > Cc: Datta, Shubhrajyoti; dmitry.torokhov at gmail.com; > khilman at deeprootsystems.com; Chemparathy, Cyril > Subject: [PATCH v2 4/5] input: add driver for tnetv107x touchscreen > controller > > This patch adds support for tnetv107x's on-chip touchscreen controller. > > Signed-off-by: Cyril Chemparathy > --- > drivers/input/touchscreen/Kconfig | 9 + > drivers/input/touchscreen/Makefile | 1 + > drivers/input/touchscreen/tnetv107x-ts.c | 401 > ++++++++++++++++++++++++++++++ > 3 files changed, 411 insertions(+), 0 deletions(-) > create mode 100644 drivers/input/touchscreen/tnetv107x-ts.c > > diff --git a/drivers/input/touchscreen/Kconfig > b/drivers/input/touchscreen/Kconfig > index 0069d97..8d32028 100644 > --- a/drivers/input/touchscreen/Kconfig > +++ b/drivers/input/touchscreen/Kconfig > @@ -328,6 +328,15 @@ config TOUCHSCREEN_MIGOR > To compile this driver as a module, choose M here: the > module will be called migor_ts. > > +config TOUCHSCREEN_TNETV107X > + tristate "TI TNETV107X touchscreen support" > + depends on ARCH_DAVINCI_TNETV107X > + help > + Say Y here if you want to use the TNETV107X touchscreen. > + > + To compile this driver as a module, choose M here: the > + module will be called tnetv107x-ts. > + > config TOUCHSCREEN_TOUCHRIGHT > tristate "Touchright serial touchscreen" > select SERIO > diff --git a/drivers/input/touchscreen/Makefile > b/drivers/input/touchscreen/Makefile > index 28217e1..d41a964 100644 > --- a/drivers/input/touchscreen/Makefile > +++ b/drivers/input/touchscreen/Makefile > @@ -37,6 +37,7 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o > obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o > obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o > obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o > +obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o > obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o > obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o > obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o > diff --git a/drivers/input/touchscreen/tnetv107x-ts.c > b/drivers/input/touchscreen/tnetv107x-ts.c > new file mode 100644 > index 0000000..0d4dbc4 > --- /dev/null > +++ b/drivers/input/touchscreen/tnetv107x-ts.c > @@ -0,0 +1,401 @@ > +/* > + * Texas Instruments TNETV107X Touchscreen Driver > + * > + * Copyright (C) 2010 Texas Instruments > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation version 2. > + * > + * This program is distributed "as is" WITHOUT ANY WARRANTY of any > + * kind, whether express or implied; without even the implied warranty > + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#define TSC_PENUP_POLL (HZ / 5) > +#define IDLE_TIMEOUT 100 /* msec */ > + > +/* > + * The first and last samples of a touch interval are usually garbage and > need > + * to be filtered out with these devices. The following definitions > control > + * the number of samples skipped. > + */ > +#define TSC_HEAD_SKIP 1 > +#define TSC_TAIL_SKIP 1 > +#define TSC_SKIP (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1) > +#define TSC_SAMPLES (TSC_SKIP + 1) > + > +/* Register Offsets */ > +struct tsc_regs { > + u32 rev; > + u32 tscm; > + u32 bwcm; > + u32 swc; > + u32 adcchnl; > + u32 adcdata; > + u32 chval[4]; > +}; > + > +/* TSC Mode Configuration Register (tscm) bits */ > +#define WMODE BIT(0) > +#define TSKIND BIT(1) > +#define ZMEASURE_EN BIT(2) > +#define IDLE BIT(3) > +#define TSC_EN BIT(4) > +#define STOP BIT(5) > +#define ONE_SHOT BIT(6) > +#define SINGLE BIT(7) > +#define AVG BIT(8) > +#define AVGNUM(x) (((x) & 0x03) << 9) > +#define PVSTC(x) (((x) & 0x07) << 11) > +#define PON BIT(14) > +#define PONBG BIT(15) > +#define AFERST BIT(16) > + > +/* ADC DATA Capture Register bits */ > +#define DATA_VALID BIT(16) > + > +/* Register Access Macros */ > +#define tsc_read(ts, reg) __raw_readl(&(ts)->regs->reg) > +#define tsc_write(ts, reg, val) __raw_writel(val, &(ts)->regs- > >reg); > +#define tsc_set_bits(ts, reg, val) \ > + tsc_write(ts, reg, tsc_read(ts, reg) | (val)) > +#define tsc_clr_bits(ts, reg, val) \ > + tsc_write(ts, reg, tsc_read(ts, reg) & ~(val)) > + > +struct sample { > + int x, y, p; > +}; > + > +struct tsc_data { > + struct input_dev *input_dev; > + struct resource *res; > + struct tsc_regs __iomem *regs; > + struct timer_list timer; > + spinlock_t lock; > + struct clk *clk; > + struct device *dev; > + int sample_count; > + struct sample samples[TSC_SAMPLES]; > + int tsc_irq; > +}; > + > +static int tsc_read_sample(struct tsc_data *ts, struct sample* sample) > +{ > + int x, y, z1, z2, t, p = 0; > + u32 val; > + > + val = tsc_read(ts, chval[0]); > + if (val & DATA_VALID) > + x = val & 0xffff; > + else > + return -EINVAL; > + > + y = tsc_read(ts, chval[1]) & 0xffff; > + z1 = tsc_read(ts, chval[2]) & 0xffff; > + z2 = tsc_read(ts, chval[3]) & 0xffff; > + > + if (z1) { > + t = ((600 * x) * (z2 - z1)); > + p = t / (u32) (z1 << 12); > + if (p < 0) > + p = 0; > + } > + > + sample->x = x; > + sample->y = y; > + sample->p = p; > + > + return 0; > +} > + > +static void tsc_poll(unsigned long data) > +{ > + struct tsc_data *ts = (struct tsc_data *)data; > + unsigned long flags; > + int i, val, x, y, p; > + > + spin_lock_irqsave(&ts->lock, flags); > + > + if (ts->sample_count >= TSC_SKIP) { > + input_report_abs(ts->input_dev, ABS_PRESSURE, 0); > + input_report_key(ts->input_dev, BTN_TOUCH, 0); > + input_sync(ts->input_dev); > + } else if (ts->sample_count > 0) { > + /* > + * A touch event lasted less than our skip count. Salvage and > + * report anyway. > + */ > + for (i = 0, val = 0; i < ts->sample_count; i++) > + val += ts->samples[i].x; > + x = val / ts->sample_count; > + > + for (i = 0, val = 0; i < ts->sample_count; i++) > + val += ts->samples[i].y; > + y = val / ts->sample_count; > + > + for (i = 0, val = 0; i < ts->sample_count; i++) > + val += ts->samples[i].p; > + p = val / ts->sample_count; > + > + input_report_abs(ts->input_dev, ABS_X, x); > + input_report_abs(ts->input_dev, ABS_Y, y); > + input_report_abs(ts->input_dev, ABS_PRESSURE, p); > + input_report_key(ts->input_dev, BTN_TOUCH, 1); > + input_sync(ts->input_dev); > + } > + > + ts->sample_count = 0; > + > + spin_unlock_irqrestore(&ts->lock, flags); > +} > + > +static irqreturn_t tsc_irq(int irq, void *dev_id) > +{ > + struct tsc_data *ts = (struct tsc_data *)dev_id; > + struct sample *sample; > + int index; > + > + spin_lock(&ts->lock); > + > + index = ts->sample_count % TSC_SAMPLES; > + sample = &ts->samples[index]; > + if (tsc_read_sample(ts, sample) >= 0) { > + ++ts->sample_count; > + > + if (ts->sample_count < TSC_SKIP) > + goto done; > + > + index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES; > + sample = &ts->samples[index]; > + > + input_report_abs(ts->input_dev, ABS_X, sample->x); > + input_report_abs(ts->input_dev, ABS_Y, sample->y); > + input_report_abs(ts->input_dev, ABS_PRESSURE, sample->p); > + if (ts->sample_count == TSC_SKIP) > + input_report_key(ts->input_dev, BTN_TOUCH, 1); > + input_sync(ts->input_dev); > +done: > + mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL); > + } > + > + spin_unlock(&ts->lock); > + return IRQ_HANDLED; > +} > + > +static int tsc_start(struct input_dev *dev) > +{ > + struct tsc_data *ts = input_get_drvdata(dev); > + unsigned long timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT); > + u32 val; > + int error; > + > + clk_enable(ts->clk); > + > + /* Go to idle mode, before any initialization */ > + while (time_after(timeout, jiffies)) { > + if (tsc_read(ts, tscm) & IDLE) > + break; > + } > + > + if (time_before(timeout, jiffies)) { > + dev_warn(ts->dev, "timeout waiting for idle\n"); > + clk_disable(ts->clk); > + return -EIO; > + } > + > + /* Configure TSC Control register*/ > + val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN); > + tsc_write(ts, tscm, val); > + > + /* Bring TSC out of reset: Clear AFE reset bit */ > + val &= ~(AFERST); > + tsc_write(ts, tscm, val); > + udelay(10); A macro may have been helpful. > + > + /* Configure all pins for hardware control*/ > + tsc_write(ts, bwcm, 0); > + > + /* Finally enable the TSC */ > + tsc_set_bits(ts, tscm, TSC_EN); > + > + error = request_irq(ts->tsc_irq, tsc_irq, 0, "tnetv107x-ts", ts); > + if (error < 0) { > + dev_err(ts->dev, "Could not allocate ts irq\n"); > + clk_disable(ts->clk); > + return error; > + } You may want to see threaded irq. You may consider moving to probe as it could be a valid reason for failing probe. > + > + return 0; > +} > + > +static void tsc_stop(struct input_dev *dev) > +{ > + struct tsc_data *ts = input_get_drvdata(dev); > + > + tsc_clr_bits(ts, tscm, TSC_EN); > + del_timer_sync(&ts->timer); > + free_irq(ts->tsc_irq, ts); > + clk_disable(ts->clk); > +} > + > +static int __devinit tsc_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct tsc_data *ts; > + int error = 0; > + u32 rev = 0; > + > + ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL); > + if (!ts) { > + dev_err(dev, "cannot allocate device info\n"); > + return -ENOMEM; > + } > + > + ts->dev = dev; > + spin_lock_init(&ts->lock); > + setup_timer(&ts->timer, tsc_poll, (unsigned long)ts); > + platform_set_drvdata(pdev, ts); > + > + ts->tsc_irq = platform_get_irq(pdev, 0); > + if (ts->tsc_irq < 0) { > + dev_err(dev, "cannot determine device interrupt\n"); > + error = -ENODEV; > + goto error; > + } > + > + ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!ts->res) { > + dev_err(dev, "cannot determine register area\n"); > + error = -ENODEV; > + goto error; > + } > + > + if (!request_mem_region(ts->res->start, resource_size(ts->res), > + pdev->name)) { > + dev_err(dev, "cannot claim register memory\n"); > + ts->res = NULL; > + error = -EINVAL; > + goto error; > + } > + > + ts->regs = ioremap(ts->res->start, resource_size(ts->res)); > + if (!ts->regs) { > + dev_err(dev, "cannot map register memory\n"); > + error = -ENOMEM; > + goto error; > + } > + > + ts->clk = clk_get(dev, NULL); > + if (!ts->clk) { > + dev_err(dev, "cannot claim device clock\n"); > + error = -EINVAL; > + goto error; > + } > + > + ts->input_dev = input_allocate_device(); > + if (!ts->input_dev) { > + dev_err(dev, "cannot allocate input device\n"); > + error = -ENOMEM; > + goto error; > + } > + input_set_drvdata(ts->input_dev, ts); > + > + ts->input_dev->name = pdev->name; > + ts->input_dev->id.bustype = BUS_HOST; > + ts->input_dev->dev.parent = &pdev->dev; > + ts->input_dev->open = tsc_start; > + ts->input_dev->close = tsc_stop; > + > + clk_enable(ts->clk); > + rev = tsc_read(ts, rev); > + ts->input_dev->id.product = ((rev >> 8) & 0x07); > + ts->input_dev->id.version = ((rev >> 16) & 0xfff); > + clk_disable(ts->clk); > + > + set_bit(EV_KEY, ts->input_dev->evbit); > + set_bit(EV_ABS, ts->input_dev->evbit); > + set_bit(BTN_TOUCH, ts->input_dev->keybit); > + set_bit(ABS_X, ts->input_dev->absbit); > + set_bit(ABS_Y, ts->input_dev->absbit); > + set_bit(ABS_PRESSURE, ts->input_dev->absbit); > + > + input_set_abs_params(ts->input_dev, ABS_X, 0, 0xffff, 5, 0); > + input_set_abs_params(ts->input_dev, ABS_Y, 0, 0xffff, 5, 0); > + input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0); > + > + error = input_register_device(ts->input_dev); > + if (error < 0) { > + dev_err(dev, "failed input device registration\n"); > + goto error; > + } > + > + return 0; > + > +error: > + if (ts->clk) > + clk_put(ts->clk); > + if (ts->regs) > + iounmap(ts->regs); > + if (ts->res) > + release_mem_region(ts->res->start, resource_size(ts->res)); > + if (ts->input_dev) > + input_free_device(ts->input_dev); This may not needed as it already has the check . > + platform_set_drvdata(pdev, NULL); > + kfree(ts); > + > + return error; > +} > + > +static int __devexit tsc_remove(struct platform_device *pdev) > +{ > + struct tsc_data *ts = platform_get_drvdata(pdev); > + > + input_unregister_device(ts->input_dev); > + clk_put(ts->clk); > + iounmap(ts->regs); > + release_mem_region(ts->res->start, resource_size(ts->res)); > + platform_set_drvdata(pdev, NULL); > + kfree(ts); > + > + return 0; > +} > + > +static struct platform_driver tsc_driver = { > + .probe = tsc_probe, > + .remove = tsc_remove, You may want to consider __devexit_p > + .driver.name = "tnetv107x-ts", > + .driver.owner = THIS_MODULE, > +}; > + > +static int __init tsc_init(void) > +{ > + return platform_driver_register(&tsc_driver); > +} > + > +static void __exit tsc_exit(void) > +{ > + platform_driver_unregister(&tsc_driver); > +} > + > +module_init(tsc_init); > +module_exit(tsc_exit); > + > +MODULE_AUTHOR("Cyril Chemparathy"); > +MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); > +MODULE_ALIAS("platform: tnetv107x-ts"); > +MODULE_LICENSE("GPL"); > -- > 1.7.0.4 From premi at ti.com Tue Sep 28 13:43:34 2010 From: premi at ti.com (Premi, Sanjeev) Date: Wed, 29 Sep 2010 00:13:34 +0530 Subject: RAMDISK and BUSYBOX v1.7.2 Issues In-Reply-To: <4C96F47C.5010601@dce.bg> References: <4C96F47C.5010601@dce.bg> Message-ID: _______________________________________ From: davinci-linux-open-source-bounces at linux.davincidsp.com [davinci-linux-open-source-bounces at linux.davincidsp.com] On Behalf Of Alexander Enchevich [alexander at dce.bg] Sent: Monday, September 20, 2010 11:13 AM To: davinci-linux-open-source at linux.davincidsp.com Cc: witucker at yahoo.com Subject: RAMDISK and BUSYBOX v1.7.2 Issues Hi I was wondering if you or anyone on the list have been able to solve this problem with "Id "con" respawning too fast" ? Here's the thread: http://linux.omap.com/pipermail/davinci-linux-open-source/2007-October/004286.html I am having the same problem with busybox-1.17.2 on sh4-linux system and if you have a solution would be very interested in hearing it. In my case it happens when I start the telnetd daemon... [sp] Did you male any change in the init script(s)? If so, can you revert it back? ~sanjeev Thanks! Alexander Enchevich Software Eng., Deltacom Electronics Ltd. _______________________________________________ Davinci-linux-open-source mailing list Davinci-linux-open-source at linux.davincidsp.com http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source From paheliprasad at gmail.com Tue Sep 28 21:48:02 2010 From: paheliprasad at gmail.com (kunal singh) Date: Wed, 29 Sep 2010 08:18:02 +0530 Subject: problem with serial console Message-ID: Hi, MY SETUP ----------------- We have a dm6446 based board & we have been using 2.6.18 (MV) Linux. Recently I tried upgrading to kernel 2.6.32 (PSP 03.01). PROBLEM ------------------- When the kernel boots I can not see any boot messages on the serial console. I assume that if the boot flow passes beyond console_init (in init/main.c) I should start to receive printk messages on the console. But it does not happen so. ADDITIONAL INFORMATION --------------------- (1) If use the printascii function (low level debug print) in the init/main.c, I can get messages on serial console. So, I assume that nothing is wrong with hardware. (2) The command line arguments (printed from kernel using printascii) show that console=ttyS0,115200n8 Any idea what could be wrong? -------------- next part -------------- An HTML attachment was scrubbed... URL: From Priya_Raghavendra at mindtree.com Wed Sep 29 05:36:28 2010 From: Priya_Raghavendra at mindtree.com (Priya Raghavendra) Date: Wed, 29 Sep 2010 10:36:28 +0000 Subject: MCASP Serializer[0] configuration for audio reception on DM6467 Message-ID: <405DFE275BD5DE40A86334BBA49AF29FB6C4@MTW02MBX03.mindtree.com> Hi, We have a custom board based on DM6467 with TVP5158 as the video codec. On the audio input path we have the following connection, LRCLK_R -> AFSR0 SD_R -> AXR0[0] BCLK_R -> ACLKR0 So basically we are receiving audio on serializer[0] of MCASP. So in sound/oss/dm646x/audio_controller.c, I have modified as below .serializer_mode[0] = CONFIGURED_AS_RX, .serializer_mode[1] = CONFIGURED_AS_INACTIVE, .serializer_mode[2] = CONFIGURED_AS_TX, .serializer_mode[3] = CONFIGURED_AS_INACTIVE, Apart from this I have modified arch/arm/mach-davinci/mcasp.c to change the PDIR register to mcasp_config.pdir = 0x00000001; I have enabled debugs in the file sound/oss/dm646x/davinci-audio-dma-intfc.c The code does not enter the function sound_dma_irq_handler. Is there any other configuration which has to be done when the serializer for reception is changed?? [audio_setup_buf]: start [audio_setup_buf]: end(0) [audio_prime_rx]: start [audio_process_dma]: start [davinci_start_sound_dma]: start [audio_set_dma_params_capture]: start : <6>audio_set_dma_params_capture channel = 90 dma _ptr = 86a04000 dma_size = c00 [audio_set_dma_params_capture]: end(0) [audio_start_dma_chain]: start [audio_start_dma_chain]: end(0) [davinci_start_sound_dma]: end(0) [davinci_start_sound_dma]: start [audio_set_dma_params_capture]: start : <6>audio_set_dma_params_capture channel = 91 dma _ptr = 86a04c00 dma_size = c00 [audio_set_dma_params_capture]: end(0) [audio_start_dma_chain]: start [audio_start_dma_chain]: end(0) [davinci_start_sound_dma]: end(0) [davinci_start_sound_dma]: start : <6>queue full [davinci_start_sound_dma]: end(4294967294) : <6>error [audio_process_dma]: end(4294967294) [audio_prime_rx]: end(0) Thanks, Priya ________________________________ http://www.mindtree.com/email/disclaimer.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From marc-andre.chenier at dalsa.com Wed Sep 29 06:04:51 2010 From: marc-andre.chenier at dalsa.com (Marc-Andre Chenier) Date: Wed, 29 Sep 2010 07:04:51 -0400 Subject: UBI crashes / fixing NAND subpage writes In-Reply-To: <70E876B0EA86DD4BAF101844BC814DFE093ED60018@Cloud.RL.local> References: <1285419347890-5569840.post@n2.nabble.com> <70E876B0EA86DD4BAF101844BC814DFE093ED60018@Cloud.RL.local> Message-ID: Hi, I found that the most elegant way to "patch" the problem is to not use sub page at all. This can be done by adding the NAND_NO_SUBPAGE_WRITE options bit exception to the NAND chip option mask. The option mask is separated into two 16 bits, the lower one for the NAND chip itself and the higher one for other custom options. This allow to force to NOT use the subpage write from your custom board NAND parameters by adding the NAND_NO_SUBPAGE_WRITE option. include/linux/mtd/nand.h: #define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR & ~NAND_NO_SUBPAGE_WRITE) your board: static struct davinci_nand_pdata nandflash_data = { .ecc_mode = NAND_ECC_HW, .ecc_bits = 4, .options = NAND_USE_FLASH_BBT | NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | NAND_NO_SUBPAGE_WRITE, }; I agree this is a patch and it does not solve the initial problem of subpage write. Pay attention to set the UBI min IO size to 2048 and the sub page size to 2048 on the host to create valid UBI partitions. The LEB size needs to be adjusted also because the 2 headers of UBI for each sector now use two pages. The UBI LEB size also need to be adjusted. The new LEB size = PEB size - (2 * 2048). When running your board, the UBI tools (ubiformat, ubiattach ...) automatically adjust the vid-hdr-offset to the UBI min IO size (nice). This worked fine for me. Regards, Marc-Andr? Ch?nier ing. Embedded software programmer DALSA Digital Imaging T?l: (514) 333-3297 x-298 marc-andre.chenier at dalsa.com http://www.dalsa.com -----Original Message----- From: Jon Povey [mailto:Jon.Povey at racelogic.co.uk] Sent: Tuesday, September 28, 2010 6:29 AM To: Alper YILDIRIM; davinci-linux-open-source at linux.davincidsp.com Subject: RE: UBI crashes / fixing NAND subpage writes davinci-linux-open-source-bounces at linux.davincidsp.com wrote: > Jon, i studied the davinci subpage write problem to find an > applicable solution, but can not come up with a good idea. Your > findings about the > cause of the > problem is totally correct but there is a question in my mind: > > Nand subpage support is added to the mainline kernel with this patch: > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.g > it;a=commit;h=29072b96078ffde36f03d51e6b5d0cff1ba8c7df > link > > Since its in mainline i guess nand subpage support is working > with other > nand > controllers, but not with davinci. There must be a way to > solve this problem > within the davinci_nand.c driver without touching the main nand API's. Unfortunately there is not a good way of doing it only within davinci that I can see. The problem is that the nand_base layer handles a subpage write by writing a whole page, with areas outside the written subpage set to FFs. The davinci layer can't tell the difference. I hacked this up by adding start offset and length parameters to all the page writing functions, which works for me but isn't going to be acceptable for mainline. Artem over on the MTD list suggested a write_subpage family of functions might be the way to go, but I haven't implemented that. http://linux.davincidsp.com/pipermail/davinci-linux-open-source/2010-September/020206.html -- Jon Povey jon.povey at racelogic.co.uk Racelogic is a limited company registered in England. Registered number 2743719 . Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB . The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the system manager. Afin de combattre les pourriels, DALSA ne retournera plus d'avis d'echec d'envoi pour les adresses invalides. Ce courriel ainsi que ses pieces jointes sont strictement reserves a l'usage de la ou du destinataire et peut contenir de l'information privilegiee et confidentielle. Si vous avez recu cette correspondance par erreur, veuillez supprimer le message. Merci. From lamiaposta71 at gmail.com Wed Sep 29 07:08:13 2010 From: lamiaposta71 at gmail.com (Raffaele Recalcati) Date: Wed, 29 Sep 2010 14:08:13 +0200 Subject: problem with serial console In-Reply-To: References: Message-ID: On Wed, Sep 29, 2010 at 4:48 AM, kunal singh wrote: > Hi, > > ?? MY SETUP > ?? ----------------- > ?? We have a dm6446 based board & we have been using 2.6.18 (MV) Linux. > Recently I tried upgrading to kernel 2.6.32 (PSP 03.01). > > ? PROBLEM > ? ------------------- > ?? When the kernel boots I can not see any boot messages on the? serial > console. I assume that if the boot flow passes beyond console_init (in > init/main.c) I should start to receive printk messages on the console. But > it does not happen so. > > ?? ADDITIONAL INFORMATION > ?? --------------------- > ?? (1) If use the printascii function (low level debug print) in the > init/main.c, I can get messages on serial console. So, I assume that nothing > is wrong with hardware. > ?? (2) The command line arguments (printed from kernel using printascii) > show that console=ttyS0,115200n8 > > ? Any idea what could be wrong? First Check your setup. I mean, with the same PC and serial port cable you can read and write to another device with 115200n8 comfiguration? Second You need to copy, in the mail, every messages you have on the serial line, from power up Third Check info here http://processors.wiki.ti.com/index.php/Category:DM644x Good work, Raffaele From b.hutchman at gmail.com Wed Sep 29 09:28:33 2010 From: b.hutchman at gmail.com (Brian Hutchinson) Date: Wed, 29 Sep 2010 10:28:33 -0400 Subject: Trying to move from 1.3x dsplink to 1.65 (does ips.h replace shm_ips.h) Message-ID: I'm trying to make the changes to our dsp application to link against the latest community dsplink 1.65. The application is currently linked against a 1.30.08.02 version of dsplink that has a header file called shm_ips.h. This header doesn't show up in 1.65. Doing some grepping I see that 1.65 has: ips.h dsplinkips.h ldrv_ips.h ... I'm guessing that ips.h in 1.65 replaces shm_ips.h in 1.30? I've looked through the moving from 1.30 - 1.40 and 1.40 - 1.50 migration guides as well as release notes and I have yet to find anything addressing or documenting these changes. Has anyone experienced anything similar moving an old app (circa 2006) to the lastest dsplink? Regards, Brian From Jon.Povey at racelogic.co.uk Wed Sep 29 22:14:53 2010 From: Jon.Povey at racelogic.co.uk (Jon Povey) Date: Thu, 30 Sep 2010 04:14:53 +0100 Subject: UBI crashes / fixing NAND subpage writes In-Reply-To: Message-ID: <70E876B0EA86DD4BAF101844BC814DFE093EE3E0B6@Cloud.RL.local> Marc-Andre Chenier wrote: > Hi, > > I found that the most elegant way to "patch" the problem is > to not use sub page at all. This can be done by adding the > NAND_NO_SUBPAGE_WRITE options bit exception to the NAND chip > option mask. This is nice and simple but makes less efficient use of the flash and may (not sure) mean slower mount times due to the scan. You can also pass a VID offset of 2048 to ubiattach to need no kernel patching.. but if you forget it, on my system at least it got locked in a loop torturing the same block again and again. -- Jon Povey jon.povey at racelogic.co.uk Racelogic is a limited company registered in England. Registered number 2743719 . Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB . The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network From paheliprasad at gmail.com Thu Sep 30 07:35:22 2010 From: paheliprasad at gmail.com (kunal singh) Date: Thu, 30 Sep 2010 18:05:22 +0530 Subject: problem with serial console In-Reply-To: References: Message-ID: Hi Raffaele, Thanks for the suggestion. (1) Console is fine. I am able to communicate with the u-boot (115200,n8). Also if I use printascii (a kernel function) I am able to output on console. (2) There is no message, after the kernel decompression (because console is not up). Here is what I see. Load address: 0x82000000 Loading: ####T ###################T ########################################## ################################################################## ######################T ############################################ ################################################################# ###################T ##############################################T ## ######T ######################################## done Bytes transferred = 1898828 (1cf94c hex) ## Booting image at 82000000 ... Image Name: Linux-2.6.32-rc2-davinci1 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1898764 Bytes = 1.8 MB Load Address: 80008000 Entry Point: 80008000 Verifying Checksum ... OK OK Starting kernel ... Uncompressing Linux........................................................................................................................... done, booting the kernel. /* AND THEN NOTHING BECAUSE CONSOLE IS NOT FUNCTIONAL, but booting goes on */ Regards, kunal On Wed, Sep 29, 2010 at 5:38 PM, Raffaele Recalcati wrote: > On Wed, Sep 29, 2010 at 4:48 AM, kunal singh > wrote: > > Hi, > > > > MY SETUP > > ----------------- > > We have a dm6446 based board & we have been using 2.6.18 (MV) Linux. > > Recently I tried upgrading to kernel 2.6.32 (PSP 03.01). > > > > PROBLEM > > ------------------- > > When the kernel boots I can not see any boot messages on the serial > > console. I assume that if the boot flow passes beyond console_init (in > > init/main.c) I should start to receive printk messages on the console. > But > > it does not happen so. > > > > ADDITIONAL INFORMATION > > --------------------- > > (1) If use the printascii function (low level debug print) in the > > init/main.c, I can get messages on serial console. So, I assume that > nothing > > is wrong with hardware. > > (2) The command line arguments (printed from kernel using printascii) > > show that console=ttyS0,115200n8 > > > > Any idea what could be wrong? > > First > Check your setup. > I mean, with the same PC and serial port cable you can read and write > to another device with 115200n8 comfiguration? > > Second > You need to copy, in the mail, every messages you have on the serial > line, from power up > > Third > Check info here http://processors.wiki.ti.com/index.php/Category:DM644x > > Good work, > Raffaele > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hemantp at ti.com Thu Sep 30 07:39:46 2010 From: hemantp at ti.com (Pedanekar, Hemant) Date: Thu, 30 Sep 2010 18:09:46 +0530 Subject: problem with serial console In-Reply-To: References: Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B0356476CAD@dbde02.ent.ti.com> What if you append "init=" e.g., something like "init=/bin/ash" as part of bootargs? You may need to have a look at /etc/inittab in your filesystem. Regards - Hemant ________________________________ From: davinci-linux-open-source-bounces at linux.davincidsp.com [mailto:davinci-linux-open-source-bounces at linux.davincidsp.com] On Behalf Of kunal singh Sent: Thursday, September 30, 2010 6:05 PM To: Raffaele Recalcati Cc: davinci-linux-open-source at linux.davincidsp.com Subject: Re: problem with serial console Hi Raffaele, Thanks for the suggestion. (1) Console is fine. I am able to communicate with the u-boot (115200,n8). Also if I use printascii (a kernel function) I am able to output on console. (2) There is no message, after the kernel decompression (because console is not up). Here is what I see. Load address: 0x82000000 Loading: ####T ###################T ########################################## ################################################################## ######################T ############################################ ################################################################# ###################T ##############################################T ## ######T ######################################## done Bytes transferred = 1898828 (1cf94c hex) ## Booting image at 82000000 ... Image Name: Linux-2.6.32-rc2-davinci1 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1898764 Bytes = 1.8 MB Load Address: 80008000 Entry Point: 80008000 Verifying Checksum ... OK OK Starting kernel ... Uncompressing Linux........................................................................................................................... done, booting the kernel. /* AND THEN NOTHING BECAUSE CONSOLE IS NOT FUNCTIONAL, but booting goes on */ Regards, kunal On Wed, Sep 29, 2010 at 5:38 PM, Raffaele Recalcati > wrote: On Wed, Sep 29, 2010 at 4:48 AM, kunal singh > wrote: > Hi, > > MY SETUP > ----------------- > We have a dm6446 based board & we have been using 2.6.18 (MV) Linux. > Recently I tried upgrading to kernel 2.6.32 (PSP 03.01). > > PROBLEM > ------------------- > When the kernel boots I can not see any boot messages on the serial > console. I assume that if the boot flow passes beyond console_init (in > init/main.c) I should start to receive printk messages on the console. But > it does not happen so. > > ADDITIONAL INFORMATION > --------------------- > (1) If use the printascii function (low level debug print) in the > init/main.c, I can get messages on serial console. So, I assume that nothing > is wrong with hardware. > (2) The command line arguments (printed from kernel using printascii) > show that console=ttyS0,115200n8 > > Any idea what could be wrong? First Check your setup. I mean, with the same PC and serial port cable you can read and write to another device with 115200n8 comfiguration? Second You need to copy, in the mail, every messages you have on the serial line, from power up Third Check info here http://processors.wiki.ti.com/index.php/Category:DM644x Good work, Raffaele -------------- next part -------------- An HTML attachment was scrubbed... URL: From nsekhar at ti.com Thu Sep 30 07:41:46 2010 From: nsekhar at ti.com (Nori, Sekhar) Date: Thu, 30 Sep 2010 18:11:46 +0530 Subject: problem with serial console In-Reply-To: References: Message-ID: Hi Kunal, On Thu, Sep 30, 2010 at 18:05:22, kunal singh wrote: > Hi Raffaele, > > Thanks for the suggestion. > > (1) Console is fine. I am able to communicate with the u-boot > (115200,n8). Also if I use printascii (a kernel function) I am able to > output on console. Can you post the boot logs with low level debug enabled? Do they indicate any error? Thanks, Sekhar From lamiaposta71 at gmail.com Thu Sep 30 07:56:48 2010 From: lamiaposta71 at gmail.com (Raffaele Recalcati) Date: Thu, 30 Sep 2010 14:56:48 +0200 Subject: problem with serial console In-Reply-To: References: Message-ID: On Thu, Sep 30, 2010 at 2:35 PM, kunal singh wrote: > Hi Raffaele, > > ? Thanks for the suggestion. > > ?(1)? Console is fine. I am able to communicate with the u-boot (115200,n8). > Also if I use printascii (a kernel function) I am able to output on console. > ?(2) There is no message, after the kernel decompression (because console is > not up). Here is what I see. > > Load address: 0x82000000 > Loading: ####T ###################T > ########################################## > ???????? ################################################################## > ???????? ######################T > ############################################ > ???????? ################################################################# > ???????? ###################T > ##############################################T ## > ???????? ######T ######################################## > done > Bytes transferred = 1898828 (1cf94c hex) > ## Booting image at 82000000 ... > ?? Image Name:?? Linux-2.6.32-rc2-davinci1 > ?? Image Type:?? ARM Linux Kernel Image (uncompressed) > ?? Data Size:??? 1898764 Bytes =? 1.8 MB > ?? Load Address: 80008000 > ?? Entry Point:? 80008000 > ?? Verifying Checksum ... OK > OK > > Starting kernel ... > > Uncompressing > Linux........................................................................................................................... > done, booting the kernel. > > /* AND THEN NOTHING BECAUSE CONSOLE IS NOT FUNCTIONAL, but booting goes on > */ How can you say that boot goes on? Can you check mem inside bootargs? For instance I have 128MB RAM and I use these bootargs. set bootargs 'console=ttyS0,115200n8 rw ip=10.39.10.183:10.39.10.169:10.39.8.1:255.255.248.0:::off root=/dev/nfs nfsroot=10.39.10.169:/home/NFS/ARAGO_DEMO_IMAGE-raf/ mem=128M video=davincifb:output=lcd:format=rgb:vid0=240x320 at 0,0:vid1=240x320 at 0,0:osd0=240x320 at 0,0:osd1=240x320 at 0,0 ' Don't copy my bootargs, only do some tests. I saw your behaviour when mem was wrong. From khilman at deeprootsystems.com Thu Sep 30 08:10:31 2010 From: khilman at deeprootsystems.com (Kevin Hilman) Date: Thu, 30 Sep 2010 06:10:31 -0700 Subject: [PATCH v4] i2c: davinci: Fix race when setting up for TX In-Reply-To: <20100922000916.GH7494@trinity.fluff.org> (Ben Dooks's message of "Wed, 22 Sep 2010 01:09:16 +0100") References: <4C97CEC9.8060602@boundarydevices.com> <1285042408-13200-1-git-send-email-jon.povey@racelogic.co.uk> <4C9904E6.7070608@boundarydevices.com> <20100922000916.GH7494@trinity.fluff.org> Message-ID: <87wrq3l6m0.fsf@deeprootsystems.com> Ben Dooks writes: > On Tue, Sep 21, 2010 at 12:17:58PM -0700, Troy Kisky wrote: >> On 9/21/2010 4:24 AM, Sudhakar Rajashekhara wrote: >> > Hi, >> > >> > On Tue, Sep 21, 2010 at 09:43:28, Jon Povey wrote: >> >> When setting up to transmit, a race exists between the ISR and >> >> i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. >> >> This is mostly visible for transmits > 1 byte long. >> >> >> >> The hardware starts sending immediately that MDR.STT is set. IMR trickery >> >> doesn't work because if we start sending, finish the first byte and an >> >> XRDY event occurs before we load IMR to unmask it, we never get an >> >> interrupt, and we timeout. >> >> >> >> Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode >> >> settings before DXR for correct behaviour, so load MDR first with >> >> STT cleared and later load again with STT set. >> >> >> >> Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 >> >> >> >> Signed-off-by: Jon Povey >> >> CC: Sudhakar Rajashekhara >> >> CC: Troy Kisky >> >> --- >> >> Reworked after comments by Troy and Sudhakar. >> >> >> >> Looking at the datasheet it seemed like setting STP without STT early >> >> might cause a stray STOP to be generated, so I moved it into the second >> >> MDR load. >> >> >> >> This passes a quick smoke test but I can't do much more testing right at >> >> the moment. Sudhakar, your comments would be welcomed. >> >> >> > >> > Looks good to me. I can test on couple of platforms I have and update the result >> > by tomorrow. >> > >> > Thanks, >> > Sudhakar >> > >> > >> > >> I like it too. I hope it works for omap. >> >> Thanks as well >> Troy > > Ok, any objections to this being applied, or should I wait? Please apply with: Acked-by: Troy Kisky Tested-by: Sudhakar Rajashekhara Acked-by: Kevin Hilman From paheliprasad at gmail.com Thu Sep 30 09:09:43 2010 From: paheliprasad at gmail.com (kunal singh) Date: Thu, 30 Sep 2010 19:39:43 +0530 Subject: problem with serial console In-Reply-To: References: Message-ID: Hi All, Thanks a lot for posting the comments here. (1) I have added some printascii() statements in function init/main.c/start_kernel() to trace the boot sequence (a) printascii() to print the command line arguments (b) printascii() before doing the console_init() (c) printascii() after doing the console_init() (2) The log (posted below) suggests that the boot sequence goes beyond console_init(). Since console_init is done I would expect that all my printk messages should start to appear on the console . But it does not. (however the printascii still works, as you can see messages in the bootlog, hence I would assume that hardware is fine) I would appreciate if you can give some suggestion on how to debug this issue further. Thanks, kunal /************* HERE IS THE BOOT LOG ****************************/ run devboot TFTP from server 10.0.0.1; our IP address is 10.0.0.3 Filename '/home/kunal/xcaster/ingenient-bsp/images/uImage'. Load address: 0x82000000 Loading: #T ################################################################ ################################################################# #################T ################################################ ################################################################## ###################T ##########T #################################### ##########################################T #### done Bytes transferred = 1898780 (1cf91c hex) ## Booting image at 82000000 ... Image Name: Linux-2.6.32-rc2-davinci1 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1898716 Bytes = 1.8 MB Load Address: 80008000 Entry Point: 80008000 Verifying Checksum ... OK OK Starting kernel ... Uncompressing Linux........................................................................................................................... done, booting the kernel. console=ttyS0,115200n8 root=/dev/nfs rw nfsroot=10.0.0.1:/home/kunal/xcaster/ingenient-bsp/rootfs/fs,udp,v3,rsize=4096,wsize=1400 ip=10.0.0.3:10.0.0.1:10.0.0.1:255.255.255.0:XCASTER5000::off mem=128M mtdparts=davinci-nand.0:96k(ubl),736k(uboot),64k(uboot-env),2m(kernel),61568k(app) eth=80:4C:EF:54:87:0A doing console init now finished console init /***************************************************************/ On Thu, Sep 30, 2010 at 6:26 PM, Raffaele Recalcati wrote: > On Thu, Sep 30, 2010 at 2:35 PM, kunal singh > wrote: > > Hi Raffaele, > > > > Thanks for the suggestion. > > > > (1) Console is fine. I am able to communicate with the u-boot > (115200,n8). > > Also if I use printascii (a kernel function) I am able to output on > console. > > (2) There is no message, after the kernel decompression (because console > is > > not up). Here is what I see. > > > > Load address: 0x82000000 > > Loading: ####T ###################T > > ########################################## > > > ################################################################## > > ######################T > > ############################################ > > > ################################################################# > > ###################T > > ##############################################T ## > > ######T ######################################## > > done > > Bytes transferred = 1898828 (1cf94c hex) > > ## Booting image at 82000000 ... > > Image Name: Linux-2.6.32-rc2-davinci1 > > Image Type: ARM Linux Kernel Image (uncompressed) > > Data Size: 1898764 Bytes = 1.8 MB > > Load Address: 80008000 > > Entry Point: 80008000 > > Verifying Checksum ... OK > > OK > > > > Starting kernel ... > > > > Uncompressing > > > Linux........................................................................................................................... > > done, booting the kernel. > > > > /* AND THEN NOTHING BECAUSE CONSOLE IS NOT FUNCTIONAL, but booting goes > on > > */ > > How can you say that boot goes on? > Can you check mem inside bootargs? > For instance I have 128MB RAM and I use these bootargs. > > set bootargs 'console=ttyS0,115200n8 rw > ip=10.39.10.183:10.39.10.169:10.39.8.1:255.255.248.0:::off > root=/dev/nfs nfsroot=10.39.10.169:/home/NFS/ARAGO_DEMO_IMAGE-raf/ > mem=128M video=davincifb:output=lcd:format=rgb:vid0=240x320 at 0 > ,0:vid1=240x320 at 0,0:osd0=240x320 at 0,0:osd1=240x320 at 0,0 > ' > > Don't copy my bootargs, only do some tests. > I saw your behaviour when mem was wrong. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From paheliprasad at gmail.com Thu Sep 30 09:09:54 2010 From: paheliprasad at gmail.com (kunal singh) Date: Thu, 30 Sep 2010 19:39:54 +0530 Subject: problem with serial console In-Reply-To: References: Message-ID: Hi All, Thanks a lot for posting the comments here. (1) I have added some printascii() statements in function init/main.c/start_kernel() to trace the boot sequence (a) printascii() to print the command line arguments (b) printascii() before doing the console_init() (c) printascii() after doing the console_init() (2) The log (posted below) suggests that the boot sequence goes beyond console_init(). Since console_init is done I would expect that all my printk messages should start to appear on the console . But it does not. (however the printascii still works, as you can see messages in the bootlog, hence I would assume that hardware is fine) I would appreciate if you can give some suggestion on how to debug this issue further. Thanks, kunal /************* HERE IS THE BOOT LOG ****************************/ run devboot TFTP from server 10.0.0.1; our IP address is 10.0.0.3 Filename '/home/kunal/xcaster/ingenient-bsp/images/uImage'. Load address: 0x82000000 Loading: #T ################################################################ ################################################################# #################T ################################################ ################################################################## ###################T ##########T #################################### ##########################################T #### done Bytes transferred = 1898780 (1cf91c hex) ## Booting image at 82000000 ... Image Name: Linux-2.6.32-rc2-davinci1 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1898716 Bytes = 1.8 MB Load Address: 80008000 Entry Point: 80008000 Verifying Checksum ... OK OK Starting kernel ... Uncompressing Linux........................................................................................................................... done, booting the kernel. console=ttyS0,115200n8 root=/dev/nfs rw nfsroot=10.0.0.1:/home/kunal/xcaster/ingenient-bsp/rootfs/fs,udp,v3,rsize=4096,wsize=1400 ip=10.0.0.3:10.0.0.1:10.0.0.1:255.255.255.0:XCASTER5000::off mem=128M mtdparts=davinci-nand.0:96k(ubl),736k(uboot),64k(uboot-env),2m(kernel),61568k(app) eth=80:4C:EF:54:87:0A doing console init now finished console init /***************************************************************/ On Thu, Sep 30, 2010 at 6:26 PM, Raffaele Recalcati wrote: > On Thu, Sep 30, 2010 at 2:35 PM, kunal singh > wrote: > > Hi Raffaele, > > > > Thanks for the suggestion. > > > > (1) Console is fine. I am able to communicate with the u-boot > (115200,n8). > > Also if I use printascii (a kernel function) I am able to output on > console. > > (2) There is no message, after the kernel decompression (because console > is > > not up). Here is what I see. > > > > Load address: 0x82000000 > > Loading: ####T ###################T > > ########################################## > > > ################################################################## > > ######################T > > ############################################ > > > ################################################################# > > ###################T > > ##############################################T ## > > ######T ######################################## > > done > > Bytes transferred = 1898828 (1cf94c hex) > > ## Booting image at 82000000 ... > > Image Name: Linux-2.6.32-rc2-davinci1 > > Image Type: ARM Linux Kernel Image (uncompressed) > > Data Size: 1898764 Bytes = 1.8 MB > > Load Address: 80008000 > > Entry Point: 80008000 > > Verifying Checksum ... OK > > OK > > > > Starting kernel ... > > > > Uncompressing > > > Linux........................................................................................................................... > > done, booting the kernel. > > > > /* AND THEN NOTHING BECAUSE CONSOLE IS NOT FUNCTIONAL, but booting goes > on > > */ > > How can you say that boot goes on? > Can you check mem inside bootargs? > For instance I have 128MB RAM and I use these bootargs. > > set bootargs 'console=ttyS0,115200n8 rw > ip=10.39.10.183:10.39.10.169:10.39.8.1:255.255.248.0:::off > root=/dev/nfs nfsroot=10.39.10.169:/home/NFS/ARAGO_DEMO_IMAGE-raf/ > mem=128M video=davincifb:output=lcd:format=rgb:vid0=240x320 at 0 > ,0:vid1=240x320 at 0,0:osd0=240x320 at 0,0:osd1=240x320 at 0,0 > ' > > Don't copy my bootargs, only do some tests. > I saw your behaviour when mem was wrong. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From hemantp at ti.com Thu Sep 30 09:49:47 2010 From: hemantp at ti.com (Pedanekar, Hemant) Date: Thu, 30 Sep 2010 20:19:47 +0530 Subject: problem with serial console In-Reply-To: References: Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B0356476D44@dbde02.ent.ti.com> Just to check: have you added "earlyprintk" to your bootargs? - Hemant ________________________________ From: kunal singh [mailto:paheliprasad at gmail.com] Sent: Thursday, September 30, 2010 7:40 PM To: Raffaele Recalcati; Nori, Sekhar; Pedanekar, Hemant Cc: davinci-linux-open-source at linux.davincidsp.com Subject: Re: problem with serial console Hi All, Thanks a lot for posting the comments here. (1) I have added some printascii() statements in function init/main.c/start_kernel() to trace the boot sequence (a) printascii() to print the command line arguments (b) printascii() before doing the console_init() (c) printascii() after doing the console_init() (2) The log (posted below) suggests that the boot sequence goes beyond console_init(). Since console_init is done I would expect that all my printk messages should start to appear on the console . But it does not. (however the printascii still works, as you can see messages in the bootlog, hence I would assume that hardware is fine) I would appreciate if you can give some suggestion on how to debug this issue further. Thanks, kunal /************* HERE IS THE BOOT LOG ****************************/ run devboot TFTP from server 10.0.0.1; our IP address is 10.0.0.3 Filename '/home/kunal/xcaster/ingenient-bsp/images/uImage'. Load address: 0x82000000 Loading: #T ################################################################ ################################################################# #################T ################################################ ################################################################## ###################T ##########T #################################### ##########################################T #### done Bytes transferred = 1898780 (1cf91c hex) ## Booting image at 82000000 ... Image Name: Linux-2.6.32-rc2-davinci1 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1898716 Bytes = 1.8 MB Load Address: 80008000 Entry Point: 80008000 Verifying Checksum ... OK OK Starting kernel ... Uncompressing Linux........................................................................................................................... done, booting the kernel. console=ttyS0,115200n8 root=/dev/nfs rw nfsroot=10.0.0.1:/home/kunal/xcaster/ingenient-bsp/rootfs/fs,udp,v3,rsize=4096,wsize=1400 ip=10.0.0.3:10.0.0.1:10.0.0.1:255.255.255.0:XCASTER5000::off mem=128M mtdparts=davinci-nand.0:96k(ubl),736k(uboot),64k(uboot-env),2m(kernel),61568k(app) eth=80:4C:EF:54:87:0A doing console init now finished console init /***************************************************************/ On Thu, Sep 30, 2010 at 6:26 PM, Raffaele Recalcati > wrote: On Thu, Sep 30, 2010 at 2:35 PM, kunal singh > wrote: > Hi Raffaele, > > Thanks for the suggestion. > > (1) Console is fine. I am able to communicate with the u-boot (115200,n8). > Also if I use printascii (a kernel function) I am able to output on console. > (2) There is no message, after the kernel decompression (because console is > not up). Here is what I see. > > Load address: 0x82000000 > Loading: ####T ###################T > ########################################## > ################################################################## > ######################T > ############################################ > ################################################################# > ###################T > ##############################################T ## > ######T ######################################## > done > Bytes transferred = 1898828 (1cf94c hex) > ## Booting image at 82000000 ... > Image Name: Linux-2.6.32-rc2-davinci1 > Image Type: ARM Linux Kernel Image (uncompressed) > Data Size: 1898764 Bytes = 1.8 MB > Load Address: 80008000 > Entry Point: 80008000 > Verifying Checksum ... OK > OK > > Starting kernel ... > > Uncompressing > Linux........................................................................................................................... > done, booting the kernel. > > /* AND THEN NOTHING BECAUSE CONSOLE IS NOT FUNCTIONAL, but booting goes on > */ How can you say that boot goes on? Can you check mem inside bootargs? For instance I have 128MB RAM and I use these bootargs. set bootargs 'console=ttyS0,115200n8 rw ip=10.39.10.183:10.39.10.169:10.39.8.1:255.255.248.0:::off root=/dev/nfs nfsroot=10.39.10.169:/home/NFS/ARAGO_DEMO_IMAGE-raf/ mem=128M video=davincifb:output=lcd:format=rgb:vid0=240x320 at 0,0:vid1=240x320 at 0,0:osd0=240x320 at 0,0:osd1=240x320 at 0,0 ' Don't copy my bootargs, only do some tests. I saw your behaviour when mem was wrong. -------------- next part -------------- An HTML attachment was scrubbed... URL: From paheliprasad at gmail.com Thu Sep 30 10:15:54 2010 From: paheliprasad at gmail.com (kunal singh) Date: Thu, 30 Sep 2010 20:45:54 +0530 Subject: problem with serial console In-Reply-To: <2A3DCF3DA181AD40BDE86A3150B27B6B0356476D44@dbde02.ent.ti.com> References: <2A3DCF3DA181AD40BDE86A3150B27B6B0356476D44@dbde02.ent.ti.com> Message-ID: Hi Hemant, No I have not added the earlyprintk. I will investigate this. Shall I add earlyprintk=serial,uart0 ? BTW, I tried to trace down the printk code flow in kernel/printk.c. (1) in the function _call_console_drivers(), __call_console_drivers() never gets called [the if() condition is never met]. (2) May be it probably explains why nothing gets printed on serial? Is this because there is no earlyprintk in bootargs? Regards, kunal On Thu, Sep 30, 2010 at 8:19 PM, Pedanekar, Hemant wrote: > Just to check: have you added "earlyprintk" to your bootargs? > > - > Hemant > > > > ------------------------------ > *From:* kunal singh [mailto:paheliprasad at gmail.com] > *Sent:* Thursday, September 30, 2010 7:40 PM > *To:* Raffaele Recalcati; Nori, Sekhar; Pedanekar, Hemant > > *Cc:* davinci-linux-open-source at linux.davincidsp.com > *Subject:* Re: problem with serial console > > Hi All, > > > Thanks a lot for posting the comments here. > > (1) I have added some printascii() statements in function > init/main.c/start_kernel() to trace the boot sequence > (a) printascii() to print the command line arguments > (b) printascii() before doing the console_init() > (c) printascii() after doing the console_init() > > (2) The log (posted below) suggests that the boot sequence goes beyond > console_init(). Since console_init is done I would expect that all my printk > messages should start to appear on the console . But it does not. (however > the printascii still works, as you can see messages in the bootlog, hence I > would assume that hardware is fine) > > I would appreciate if you can give some suggestion on how to debug this > issue further. > > Thanks, > kunal > > > /************* HERE IS THE BOOT LOG ****************************/ > run devboot > TFTP from server 10.0.0.1; our IP address is 10.0.0.3 > Filename '/home/kunal/xcaster/ingenient-bsp/images/uImage'. > Load address: 0x82000000 > Loading: #T > ################################################################ > ################################################################# > #################T > ################################################ > ################################################################## > ###################T ##########T > #################################### > ##########################################T #### > done > Bytes transferred = 1898780 (1cf91c hex) > ## Booting image at 82000000 ... > Image Name: Linux-2.6.32-rc2-davinci1 > Image Type: ARM Linux Kernel Image (uncompressed) > Data Size: 1898716 Bytes = 1.8 MB > Load Address: 80008000 > Entry Point: 80008000 > Verifying Checksum ... OK > OK > > Starting kernel ... > > Uncompressing > Linux........................................................................................................................... > done, booting the kernel. > > console=ttyS0,115200n8 root=/dev/nfs rw nfsroot=10.0.0.1:/home/kunal/xcaster/ingenient-bsp/rootfs/fs,udp,v3,rsize=4096,wsize=1400 > ip=10.0.0.3:10.0.0.1:10.0.0.1:255.255.255.0:XCASTER5000::off mem=128M > mtdparts=davinci-nand.0:96k(ubl),736k(uboot),64k(uboot-env),2m(kernel),61568k(app) > eth=80:4C:EF:54:87:0A > doing console init now > finished console init > > /***************************************************************/ > > > On Thu, Sep 30, 2010 at 6:26 PM, Raffaele Recalcati < > lamiaposta71 at gmail.com> wrote: > >> On Thu, Sep 30, 2010 at 2:35 PM, kunal singh >> wrote: >> > Hi Raffaele, >> > >> > Thanks for the suggestion. >> > >> > (1) Console is fine. I am able to communicate with the u-boot >> (115200,n8). >> > Also if I use printascii (a kernel function) I am able to output on >> console. >> > (2) There is no message, after the kernel decompression (because >> console is >> > not up). Here is what I see. >> > >> > Load address: 0x82000000 >> > Loading: ####T ###################T >> > ########################################## >> > >> ################################################################## >> > ######################T >> > ############################################ >> > >> ################################################################# >> > ###################T >> > ##############################################T ## >> > ######T ######################################## >> > done >> > Bytes transferred = 1898828 (1cf94c hex) >> > ## Booting image at 82000000 ... >> > Image Name: Linux-2.6.32-rc2-davinci1 >> > Image Type: ARM Linux Kernel Image (uncompressed) >> > Data Size: 1898764 Bytes = 1.8 MB >> > Load Address: 80008000 >> > Entry Point: 80008000 >> > Verifying Checksum ... OK >> > OK >> > >> > Starting kernel ... >> > >> > Uncompressing >> > >> Linux........................................................................................................................... >> > done, booting the kernel. >> > >> > /* AND THEN NOTHING BECAUSE CONSOLE IS NOT FUNCTIONAL, but booting goes >> on >> > */ >> >> How can you say that boot goes on? >> Can you check mem inside bootargs? >> For instance I have 128MB RAM and I use these bootargs. >> >> set bootargs 'console=ttyS0,115200n8 rw >> ip=10.39.10.183:10.39.10.169:10.39.8.1:255.255.248.0:::off >> root=/dev/nfs nfsroot=10.39.10.169:/home/NFS/ARAGO_DEMO_IMAGE-raf/ >> mem=128M video=davincifb:output=lcd:format=rgb:vid0=240x320 at 0 >> ,0:vid1=240x320 at 0,0:osd0=240x320 at 0,0:osd1=240x320 at 0,0 >> ' >> >> Don't copy my bootargs, only do some tests. >> I saw your behaviour when mem was wrong. >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From paheliprasad at gmail.com Thu Sep 30 10:48:04 2010 From: paheliprasad at gmail.com (kunal singh) Date: Thu, 30 Sep 2010 21:18:04 +0530 Subject: problem with serial console In-Reply-To: References: <2A3DCF3DA181AD40BDE86A3150B27B6B0356476D44@dbde02.ent.ti.com> Message-ID: Tried with earlyprintk, but the problem persists On Thu, Sep 30, 2010 at 8:45 PM, kunal singh wrote: > Hi Hemant, > > No I have not added the earlyprintk. I will investigate this. Shall I > add earlyprintk=serial,uart0 ? > > BTW, I tried to trace down the printk code flow in kernel/printk.c. > (1) in the function _call_console_drivers(), __call_console_drivers() > never gets called [the if() condition is never met]. > (2) May be it probably explains why nothing gets printed on serial? Is > this because there is no earlyprintk in bootargs? > > Regards, > kunal > > > > > > On Thu, Sep 30, 2010 at 8:19 PM, Pedanekar, Hemant wrote: > >> Just to check: have you added "earlyprintk" to your bootargs? >> >> - >> Hemant >> >> >> >> ------------------------------ >> *From:* kunal singh [mailto:paheliprasad at gmail.com] >> *Sent:* Thursday, September 30, 2010 7:40 PM >> *To:* Raffaele Recalcati; Nori, Sekhar; Pedanekar, Hemant >> >> *Cc:* davinci-linux-open-source at linux.davincidsp.com >> *Subject:* Re: problem with serial console >> >> Hi All, >> >> >> Thanks a lot for posting the comments here. >> >> (1) I have added some printascii() statements in function >> init/main.c/start_kernel() to trace the boot sequence >> (a) printascii() to print the command line arguments >> (b) printascii() before doing the console_init() >> (c) printascii() after doing the console_init() >> >> (2) The log (posted below) suggests that the boot sequence goes beyond >> console_init(). Since console_init is done I would expect that all my printk >> messages should start to appear on the console . But it does not. (however >> the printascii still works, as you can see messages in the bootlog, hence I >> would assume that hardware is fine) >> >> I would appreciate if you can give some suggestion on how to debug this >> issue further. >> >> Thanks, >> kunal >> >> >> /************* HERE IS THE BOOT LOG ****************************/ >> run devboot >> TFTP from server 10.0.0.1; our IP address is 10.0.0.3 >> Filename '/home/kunal/xcaster/ingenient-bsp/images/uImage'. >> Load address: 0x82000000 >> Loading: #T >> ################################################################ >> ################################################################# >> #################T >> ################################################ >> >> ################################################################## >> ###################T ##########T >> #################################### >> ##########################################T #### >> done >> Bytes transferred = 1898780 (1cf91c hex) >> ## Booting image at 82000000 ... >> Image Name: Linux-2.6.32-rc2-davinci1 >> Image Type: ARM Linux Kernel Image (uncompressed) >> Data Size: 1898716 Bytes = 1.8 MB >> Load Address: 80008000 >> Entry Point: 80008000 >> Verifying Checksum ... OK >> OK >> >> Starting kernel ... >> >> Uncompressing >> Linux........................................................................................................................... >> done, booting the kernel. >> >> console=ttyS0,115200n8 root=/dev/nfs rw nfsroot=10.0.0.1:/home/kunal/xcaster/ingenient-bsp/rootfs/fs,udp,v3,rsize=4096,wsize=1400 >> ip=10.0.0.3:10.0.0.1:10.0.0.1:255.255.255.0:XCASTER5000::off mem=128M >> mtdparts=davinci-nand.0:96k(ubl),736k(uboot),64k(uboot-env),2m(kernel),61568k(app) >> eth=80:4C:EF:54:87:0A >> doing console init now >> finished console init >> >> /***************************************************************/ >> >> >> On Thu, Sep 30, 2010 at 6:26 PM, Raffaele Recalcati < >> lamiaposta71 at gmail.com> wrote: >> >>> On Thu, Sep 30, 2010 at 2:35 PM, kunal singh >>> wrote: >>> > Hi Raffaele, >>> > >>> > Thanks for the suggestion. >>> > >>> > (1) Console is fine. I am able to communicate with the u-boot >>> (115200,n8). >>> > Also if I use printascii (a kernel function) I am able to output on >>> console. >>> > (2) There is no message, after the kernel decompression (because >>> console is >>> > not up). Here is what I see. >>> > >>> > Load address: 0x82000000 >>> > Loading: ####T ###################T >>> > ########################################## >>> > >>> ################################################################## >>> > ######################T >>> > ############################################ >>> > >>> ################################################################# >>> > ###################T >>> > ##############################################T ## >>> > ######T ######################################## >>> > done >>> > Bytes transferred = 1898828 (1cf94c hex) >>> > ## Booting image at 82000000 ... >>> > Image Name: Linux-2.6.32-rc2-davinci1 >>> > Image Type: ARM Linux Kernel Image (uncompressed) >>> > Data Size: 1898764 Bytes = 1.8 MB >>> > Load Address: 80008000 >>> > Entry Point: 80008000 >>> > Verifying Checksum ... OK >>> > OK >>> > >>> > Starting kernel ... >>> > >>> > Uncompressing >>> > >>> Linux........................................................................................................................... >>> > done, booting the kernel. >>> > >>> > /* AND THEN NOTHING BECAUSE CONSOLE IS NOT FUNCTIONAL, but booting goes >>> on >>> > */ >>> >>> How can you say that boot goes on? >>> Can you check mem inside bootargs? >>> For instance I have 128MB RAM and I use these bootargs. >>> >>> set bootargs 'console=ttyS0,115200n8 rw >>> ip=10.39.10.183:10.39.10.169:10.39.8.1:255.255.248.0:::off >>> root=/dev/nfs nfsroot=10.39.10.169:/home/NFS/ARAGO_DEMO_IMAGE-raf/ >>> mem=128M video=davincifb:output=lcd:format=rgb:vid0=240x320 at 0 >>> ,0:vid1=240x320 at 0,0:osd0=240x320 at 0,0:osd1=240x320 at 0,0 >>> ' >>> >>> Don't copy my bootargs, only do some tests. >>> I saw your behaviour when mem was wrong. >>> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vm.rod25 at gmail.com Thu Sep 30 19:50:45 2010 From: vm.rod25 at gmail.com (vm.rod25 at gmail.com) Date: Thu, 30 Sep 2010 19:50:45 -0500 Subject: [PATCH v1] davinci: sound support for Omapl138-Hawkboard Message-ID: <1285894245-26215-1-git-send-email-vm.rod25@gmail.com> From: Victor Rodriguez Hi caglar Please check this patch, I rebase your Audio patch to the latest RC from Kernel development tree for TI DaVinci I have tested it and it works perfect with ALSA utils. I will rebase some of your patches to the latest rc Please give me feedback and sign off if you want. This patch adds sound support for the Hawkboard-L138 system It is under the machine name "omapl138_hawkboard". This system is based on the da850 davinci CPU architecture. Signed-off-by: Victor Rodriguez --- Notes: This patch is based on davinci: Initial support for Omapl138-Hawkboard patch from Kernel development tree for TI DaVinci family of processors. This patch works with da8xx_omapl_defconfig In order to test it select in menuconfig like insmodule Sound card support ---> Advanced Linux Sound Architecture ---> ALSA for SoC audio support ---> SoC Audio for the TI DAVINCI chip SoC Audio support for DA850/OMAP-L138 --- arch/arm/mach-davinci/board-omapl138-hawk.c | 105 +++++++++++++++++++++++++++ arch/arm/mach-davinci/da850.c | 2 +- sound/soc/davinci/Kconfig | 4 +- sound/soc/davinci/davinci-evm.c | 6 +- 4 files changed, 112 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c index fd1f458..d752244 100644 --- a/arch/arm/mach-davinci/board-omapl138-hawk.c +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -69,6 +70,87 @@ static int __init omapl138_hawk_config_emac(void) } device_initcall(omapl138_hawk_config_emac); +static struct i2c_board_info __initdata omapl138_hawk_i2c_devices[] = { + { + I2C_BOARD_INFO("tlv320aic3x", 0x18), + }, +}; + +static struct davinci_i2c_platform_data omapl138_hawk_i2c_0_pdata = { + .bus_freq = 100, /* kHz */ + .bus_delay = 0, /* usec */ +}; + +/* davinci da850 evm audio machine driver */ +static u8 da850_iis_serializer_direction[] = { + INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, + INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, + INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, + INACTIVE_MODE, TX_MODE, RX_MODE, INACTIVE_MODE, +}; + +static struct snd_platform_data omapl138_hawk_snd_data = { + .tx_dma_offset = 0x2000, + .rx_dma_offset = 0x2000, + .op_mode = DAVINCI_MCASP_IIS_MODE, + .num_serializer = ARRAY_SIZE(da850_iis_serializer_direction), + .tdm_slots = 2, + .serial_dir = da850_iis_serializer_direction, + .asp_chan_q = EVENTQ_1, + .version = MCASP_VERSION_2, + .txnumevt = 1, + .rxnumevt = 1, +}; +/* + * The following EDMA channels/slots are not being used by drivers (for + * example: Timer, GPIO, UART events etc) on da850/omap-l138 EVM, hence + * they are being reserved for codecs on the DSP side. + */ +static const s16 da850_dma0_rsv_chans[][2] = { + /* (offset, number) */ + { 8, 6}, + {24, 4}, + {30, 2}, + {-1, -1} +}; + +static const s16 da850_dma0_rsv_slots[][2] = { + /* (offset, number) */ + { 8, 6}, + {24, 4}, + {30, 50}, + {-1, -1} +}; + +static const s16 da850_dma1_rsv_chans[][2] = { + /* (offset, number) */ + { 0, 28}, + {30, 2}, + {-1, -1} +}; + +static const s16 da850_dma1_rsv_slots[][2] = { + /* (offset, number) */ + { 0, 28}, + {30, 90}, + {-1, -1} +}; + +static struct edma_rsv_info da850_edma_cc0_rsv = { + .rsv_chans = da850_dma0_rsv_chans, + .rsv_slots = da850_dma0_rsv_slots, +}; + +static struct edma_rsv_info da850_edma_cc1_rsv = { + .rsv_chans = da850_dma1_rsv_chans, + .rsv_slots = da850_dma1_rsv_slots, +}; + +static struct edma_rsv_info *da850_edma_rsv[2] = { + &da850_edma_cc0_rsv, + &da850_edma_cc1_rsv, +}; + static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { .enabled_uarts = 0x7, }; @@ -79,6 +161,29 @@ static __init void omapl138_hawk_init(void) davinci_serial_init(&omapl138_hawk_uart_config); + + ret = da850_register_edma(da850_edma_rsv); + if (ret) + pr_warning("hawk_init: edma registration failed: %d\n", + ret); + + i2c_register_board_info(1, omapl138_hawk_i2c_devices, + ARRAY_SIZE(omapl138_hawk_i2c_devices)); + + ret = da8xx_register_i2c(0, &omapl138_hawk_i2c_0_pdata); + if (ret) + pr_warning("omapl138_hawk_init: " + "i2c0 registration failed: %d\n", + ret); + + ret = davinci_cfg_reg_list(da850_mcasp_pins); + if (ret) + pr_warning("omapl138_hawk_init: " + "mcasp mux setup failed: %d\n", + ret); + da8xx_register_mcasp(0, &omapl138_hawk_snd_data); + + ret = da8xx_register_watchdog(); if (ret) pr_warning("omapl138_hawk_init: " diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 63916b9..f033a0a 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -591,7 +591,7 @@ const short da850_cpgmac_pins[] __initdata = { const short da850_mcasp_pins[] __initdata = { DA850_AHCLKX, DA850_ACLKX, DA850_AFSX, DA850_AHCLKR, DA850_ACLKR, DA850_AFSR, DA850_AMUTE, - DA850_AXR_11, DA850_AXR_12, + DA850_AXR_11, DA850_AXR_12, DA850_AXR_13, DA850_AXR_14, -1 }; diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig index 6bbf001..cd29c81 100644 --- a/sound/soc/davinci/Kconfig +++ b/sound/soc/davinci/Kconfig @@ -76,8 +76,8 @@ config SND_DA830_SOC_EVM DA830/OMAP-L137 EVM config SND_DA850_SOC_EVM - tristate "SoC Audio support for DA850/OMAP-L138 EVM" - depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM + tristate "SoC Audio support for DA850/OMAP-L138 EVM / Hawkboard" + depends on SND_DAVINCI_SOC && (MACH_DAVINCI_DA850_EVM || MACH_OMAPL138_HAWKBOARD) select SND_DAVINCI_SOC_MCASP select SND_SOC_TLV320AIC3X help diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 97f74d6..73093eb 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -59,7 +59,8 @@ static int evm_hw_params(struct snd_pcm_substream *substream, sysclk = 12288000; else if (machine_is_davinci_da830_evm() || - machine_is_davinci_da850_evm()) + machine_is_davinci_da850_evm() || + machine_is_omapl138_hawkboard()) sysclk = 24576000; else @@ -311,7 +312,8 @@ static int __init evm_init(void) } else if (machine_is_davinci_da830_evm()) { evm_snd_dev_data = &da830_evm_snd_devdata; index = 1; - } else if (machine_is_davinci_da850_evm()) { + } else if (machine_is_davinci_da850_evm() || + machine_is_omapl138_hawkboard()) { evm_snd_dev_data = &da850_evm_snd_devdata; index = 0; } else -- 1.6.0.5 From vm.rod25 at gmail.com Thu Sep 30 20:15:55 2010 From: vm.rod25 at gmail.com (vm.rod25 at gmail.com) Date: Thu, 30 Sep 2010 20:15:55 -0500 Subject: [[RFC]PATCH v1] davinci: VGA support for Omapl138-Hawkboard Message-ID: <1285895755-29129-1-git-send-email-vm.rod25@gmail.com> From: Victor Rodriguez This patch adds VGA support for the Hawkboard-L138 system It is under the machine name "omapl138_hawkboard". This system is based on the da850 davinci CPU architecture. Signed-off-by: Victor Rodriguez --- Notes: This patch is based on davinci: Initial support for Omapl138-Hawkboard patch from Kernel development tree for TI DaVinci family of processors. This patch works with da8xx_omapl_defconfig arch/arm/mach-davinci/board-omapl138-hawk.c | 5 +++++ arch/arm/mach-davinci/devices-da8xx.c | 6 ++++++ arch/arm/mach-davinci/include/mach/da8xx.h | 1 + drivers/video/da8xx-fb.c | 15 +++++++++++++++ 4 files changed, 27 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c index d752244..ff009ad 100644 --- a/arch/arm/mach-davinci/board-omapl138-hawk.c +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c @@ -183,6 +183,11 @@ static __init void omapl138_hawk_init(void) ret); da8xx_register_mcasp(0, &omapl138_hawk_snd_data); + ret = da8xx_register_lcdc(&vga_monitor_pdata); + if (ret) + pr_warning("omapl138_hawk_init: " + "lcdc registration failed: %d\n", + ret); ret = da8xx_register_watchdog(); if (ret) diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 9eec630..ad6fac2 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -528,6 +528,12 @@ struct da8xx_lcdc_platform_data sharp_lk043t1dg01_pdata = { .type = "Sharp_LK043T1DG01", }; +struct da8xx_lcdc_platform_data vga_monitor_pdata = { + .manu_name = "vga_mon", + .controller_data = &lcd_cfg, + .type = "VGA_Monitor", +}; + static struct resource da8xx_lcdc_resources[] = { [0] = { /* registers */ .start = DA8XX_LCD_CNTRL_BASE, diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index 4247b3f..6dae1d1 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -88,6 +88,7 @@ extern struct platform_device da8xx_serial_device; extern struct emac_platform_data da8xx_emac_pdata; extern struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata; extern struct da8xx_lcdc_platform_data sharp_lk043t1dg01_pdata; +extern struct da8xx_lcdc_platform_data vga_monitor_pdata; extern struct platform_device da8xx_wdt_device; diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index cad7d45..eea7264 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -212,6 +212,21 @@ static struct da8xx_panel known_lcd_panels[] = { .pxl_clk = 7833600, .invert_pxl_clk = 0, }, + + /* CRT Monitor or LCD Screen */ + [2] = { + .name = "VGA_Monitor", + .width = 640, + .height = 480, + .hfp = 48, + .hbp = 48, + .hsw = 63, + .vfp = 11, + .vbp = 31, + .vsw = 1, + .pxl_clk = 25000000, + .invert_pxl_clk = 1, + }, }; /* Enable the Raster Engine of the LCD Controller */ -- 1.6.0.5 From 271746207 at qq.com Wed Sep 29 01:51:42 2010 From: 271746207 at qq.com (=?gbk?B?w84=?=) Date: Wed, 29 Sep 2010 14:51:42 +0800 Subject: help:problem of rebuild new linux kernel of dm355 Message-ID: hi all I am porting open source Linux kernel into DM355, but I met a problem. I am using Linux git kernel downloaded from Montavista open soure git, and I modify the code in arch/arm/mach-davinci/ for DM355 EVM, and sucessfully compiled out the uImage, but when I use u-boot's tftp;bootm method, the terminal only output: ..... Ucompressed kernel.............................................done, > start kernel. I am confused why there is no more output messages, and where is the kernel dead. Thanks and my email:kuangmengjie2003 at yahoo.com.cn -------------- next part -------------- An HTML attachment was scrubbed... URL: From threeday78 at 163.com Wed Sep 29 21:33:58 2010 From: threeday78 at 163.com (justdoit) Date: Wed, 29 Sep 2010 19:33:58 -0700 (PDT) Subject: How to set UART1 using TIOCSSERIAL IOCTL on Davinci platform? Message-ID: <1285814038686-5586395.post@n2.nabble.com> MY SETUP ----------------- We have a dm6446 EVM board, we have been using MontaVista(R) Linux(R) Professional Edition 5.0.0 with 2.6.18 kernel and LSP 2.10 DaVinci Linux Drivers. PROBLEM ------------------- UART0 works well as a console, but UART1 can not work. Refer to sprs566A document on page 113, we call funtion IOCTL(fd, TIOCSSERIAL, (serial_struct *)serial_info), the function return error. how to use the IOCTL function or serial_structor structure to config uart correctly ? what is the meaning of the number of serial_struct ? how to config them ? open uart1 always succeed. ADDITIONAL INFORMATION --------------------- Afer open uart1 correctly, we call IOCTL(fd, TIOCSSERIAL, (serial_struct *)serial_info) in a user application to config uart1, sometimes system reports illeagal seek, sometimes input/output error, sometimes Unable to handle kernel NULL pointer dereference at virtual address...... sometimes badly, console run over. -- View this message in context: http://davinci-linux-open-source.1494791.n2.nabble.com/How-to-set-UART1-using-TIOCSSERIAL-IOCTL-on-Davinci-platform-tp5586395p5586395.html Sent from the davinci-linux-open-source mailing list archive at Nabble.com.