** Linux DMA platform

  

/* linux /arch /arm /plat-s5p /s3c-pl330.c ** Copyright (C) 2010 Samsung Electronics Co. Ltd. * Jaswinder Singh < [email protected]> ** Este programa es software libre; puede redistribuirlo y /o modificarlo * según los términos de la Licencia Pública General de GNU tal como lo publica * la Free Software Foundation; ya sea la versión 2 de la Licencia, o * (a su elección) cualquier versión posterior. ** Este programa se distribuye con la esperanza de que sea útil, * pero SIN NINGUNA GARANTÍA; sin ni siquiera la garantía implícita de * MERCHANTABILITY o FITNESS PARA UN PROPÓSITO PARTICULAR. Consulte la * Licencia pública general de GNU para obtener más detalles. ** Debería haber recibido una copia de la Licencia pública general de GNU * junto con este programa; si no, escriba a Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, EE. UU. * /

#include < linux /init.h > #include < linux /module .h > #include < linux /interrupt.h > #include < linux /io.h > #include < linux /platform_device.h >

#include < asm /hardware /pl330.h >;

#include < asm /dma.h >

#include < mach /dma.h >

#include < plat /s3c-pl330-pdata .h >

struct s3c_pl330_dmac {struct pl330_info * pi; /* Número de canales actualmente ocupados * /unsigned busy_chan; /* Para adjuntar a la lista global de DMACs * /struct list_head node; /* Lista de ID de los periféricos, este DMAC puede trabajar con * /enum dma_ch * peri; /* Agrupar para asignar rápidamente xfers para todos los canales en dmac * /struct kmem_cache * kmcache;};

struct s3c_pl330_xfer {/* Para adjuntar a la lista de xfers en un canal * /struct list_head node; /* Canal propietario de este xfer * /struct s3c_pl330_chan * chan; /* Xfer ID proporcionado por el cliente * /void * token;

/* Xfer para PL330 cor e * /struct pl330_xfer px;};

struct s3c_pl330_chan {/* ID del periférico con el que este canal puede comunicarse * /enum dma_ch id; /* Para adjuntar a la lista global de canales * /struct list_head nodo; /* Puntero al último pl330_req enviado al PL330 core * /struct pl330_req * lrq;

/* Para administrar la lista de xfers en cola * /struct list_head xfer_list; /* Siempre apunta a la xfer en la parte delantera de la cola * /struct s3c_pl330_xfer * xfer_head;

/* Puntero al DMAC que administra este canal, * NULL si el canal está disponible para ser adquirido. * /struct s3c_pl330_dmac * dmac;

/* Token de un hilo de canal de hardware de PL330 DMAC * NULL si el canal está disponible para ser adquirido. * /Void * pl330_chan_id;

/* Dos solicitudes para comunicarse con el motor PL330 * /struct pl330_req req [ ,null,null,3],2];

/* Cliente de este canal * NULL si el canal está disponible para ser adquirido. * /Struct s3c2410_dma_client * cliente; /* Función de devolución de llamada al cliente * /s3c2410_dma_cbfn_t callback_fn; /* Especificaciones de opciones ed por el cliente * /unsigned int options; struct pl330_reqcfg rqcfg; /* Dirección proporcionada a través de s3c2410_dma_devconfig * /unsigned long sdaddr;};

/* Todos los DMAC en la plataforma * /static LIST_HEAD (dmac_list);

/* Todos los canales a periféricos en la plataforma * /static LIST_HEAD (chan_list);

/* Dado que agregamos recursos (DMAC y canales) al pool global, * necesitamos proteger el acceso a los recursos mediante un bloqueo global * /static DEFINE_SPINLOCK (res_lock);

/* Devuelve el canal con ID 'id' en chan_list * /static struct s3c_pl330_chan * id_to_chan (const enum dma_ch id) {struct s3c_pl330_chan * ch;

list_for_each_entry (ch, &chan_list, node) if (ch- > id == id) return ch;

return NULL;}

/* Asigne un nuevo canal con ID 'id' y agregue a chan_list * /static void chan_add (const enum dma_ch id) {struct s3c_pl330_chan * ch = id_to_chan (id);

/* Volver si el canal ya existe * /if (ch) return;

ch = kmalloc (sizeof (* ch), GFP_KERNEL); /* Regresa silenciosamente al trabajo con otros canales * /if (! ch) return;

ch- > id = id; ch- > dmac = NULL;

list_add_tail (&ch- > node, &chan_list);}

/* Si el cliente aún no ha adquirido el canal * /static bool chan_free (struct s3c_pl330_chan * ch) {if (! ch) devuelve false;

/* El canal apunta a algún DMAC solo cuando se adquiere * /return ch- > dmac? falso: verdadero;}

/*

Copyright © Conocimiento de Windows All Rights Reserved