All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kaiwan N Billimoria <kaiwan@designergraphix.com>
To: Jean Delvare <khali@linux-fr.org>
Cc: linux-kernel@vger.kernel.org
Subject: SPI <-> Parport (light) bridge code  (Re: Stuck creating sysfs hooks for a driver..)
Date: Fri, 31 Mar 2006 11:31:30 +0530	[thread overview]
Message-ID: <442CC5BA.2030901@designergraphix.com> (raw)
In-Reply-To: <20060219142311.ba0f8a38.khali@linux-fr.org>

Jean Delvare wrote:

>Hi Kaiwan,
>
>  
>
--snip--

>You must stay away from writing a driver for the board itself. What you
>must write is in fact two different drivers:
>
>1* A driver for the SPI interface of your board (basically a parallel
>port <-> SPI bridge). This driver will expose the device as an SPI bus
>to the rest of the kernel. This driver doesn't care about what chip is
>plugged on it.
>
>  
>
Hi Jean,

1. Yes, i know, long time since the above message..yet i'm happy to say 
that i have built a (lightweight version) of the
SPI<->parport bridge (file pasted below), which is based on your 
i2c-parport driver bridge code.
It is built as a header file: the driver developer basically appends 
his/her adapter entry into the adapter_parm[] data structure and 
includes this file in the device driver.

>2* A driver for the LM70 temperature sensor chip, which doesn't care
>about the chip location. This driver will use generic SPI commands as
>offered by the spi kernel interface.
>
>This modular approach makes it possible to then reuse each of the
>drivers. If you later have a similar board for a different chip, the
>first driver will still work (assuming the new board uses SPI and the
>same wiring conventions). If you later have an LM70 chip on a different
>physical interface, the second driver will still work.
>
>  
>
2. I have also done this; i now have a working driver for a specific 
chip (the NS lm70CILD-3 eval board) based on the (above mentioned) 
SPi<->parport bridge. Basically, the "type 0" entry in the 
adapter_parm[] data structure is the lm70CILD-3 entry. The driver 
handles the other things, including creation of a sysfs hook (used to 
query the temperature from userspace).

>No, just do what every other hardware monitoring chip does, so that
>support can be added for the lm70 chip in libsensors - then you win
>instant support in all hardware monitoring application which rely on
>libsensors, and even a few which do not.
>
>It's really not a matter of how many features a chip has. Look at the
>lm75 or w83l785ts driver, you'll see they have very few features as
>well. It's a matter of having a common standard for exporting the
>values to user-space, so that the same library or application can
>handle all sources with minimum effort.
>
>Thanks,
>  
>
3. I still have to work on integrating the userspace conversion into 
libsensors (as recommended by yourself & others).

4. My intention at this point of time is for you (and others) to take a 
look at the spi-parport-light.h code and pl give me your feedback. I'm 
not posting a patch at this time..

5. Also, because it's a header, am not sure what approach to take when 
patching into the kernel; i mean, i can place it under the spi tree 
(either drivers/spi or include/linux/spi) but can't add the usual
"obj-$(CONFIG_xxx) += xxx.o"
line (as it's a header). Or can I do something like this?? i'm really 
quite uncertain, forgive me.. any suggestions on how i should go about this?

Thanks very much,
Kaiwan.

PS> If you'd like to see a usage example, i can post the lm70CILD3.c 
driver code..

+++++++++++++++++++++ File spi-parport-light.h 
+++++++++++++++++++++++++++++++++++++++

---
/* 
------------------------------------------------------------------------ *
 * 
spi-parport-light.h                                                      *
 * SPI bus over parallel 
port                                               *
 * 
------------------------------------------------------------------------ *
   Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
 
   Heavily based on i2c-parport-light.c
   Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
  
   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.
 * 
------------------------------------------------------------------------ */

#ifdef DATA
#undef DATA
#endif

#define DATA    0
#define STAT    1
#define CTRL    2

struct lineop {
    u8 val;
    u8 port;
    u8 inverted;
};

struct adapter_parm {
    char *name;
    struct lineop setsda;
    struct lineop setscl;
    struct lineop setcsl;    // chip select
    struct lineop getsda;
    struct lineop getscl;
    struct lineop init;
    struct spi_device *spidev;
};

static struct adapter_parm adapter_parm[] = {
    /* type 0: National Semiconductor LM70CILD-3 evaluation board */
    {
        .name   = "lm70CILD-3",
        .setscl    = { 0x40, DATA, 0 },
        .setcsl    = { 0x20, DATA, 1 },
        .getsda    = { 0x10, STAT, 0 },    // SI/O
        .init   = { 0xFE, DATA, 0 },
    },
    /* add adapters here */
};

/*----------------Module parameters-----------------------------*/
static int type;
module_param(type, int, 0);
MODULE_PARM_DESC(type,
    "Type of adapter: (defaults to 0)\n"
    " 0 = LM70CILD-3 (National Semiconductor) evaluation board\n");
    /* add new type(s) here */

static u16 base;
module_param(base, ushort, 0);
MODULE_PARM_DESC(base, "Parport Base I/O address");
/*--------------------------------------------------------------*/

#include <linux/ioport.h>
#include <linux/delay.h>
#include <asm/io.h>

/* ----- Low-level parallel port access 
----------------------------------- */

#define DEFAULT_BASE 0x378

static inline void port_write(unsigned char p, unsigned char d)
{
    outb(d, base+p);
}

static inline unsigned char port_read(unsigned char p)
{
    return inb(base+p);
}

/* ----- Unified line operation functions 
--------------------------------- */

static inline void line_set(int state, const struct lineop *op)
{
    u8 oldval = port_read(op->port);

    /* Touch only the bit(s) needed */
    if ((op->inverted && !state) || (!op->inverted && state))
        port_write(op->port, oldval | op->val);
    else
        port_write(op->port, oldval & ~op->val);
}

static inline int line_get(const struct lineop *op)
{
    u8 oldval = port_read(op->port);

    return ((op->inverted && (oldval & op->val) != op->val)
        || (!op->inverted && (oldval & op->val) == op->val));
}

/* ----- SPI call-back functions and structures ----------------- */

static void parport_setscl(void *data, int state)
{
    line_set(state, &adapter_parm[type].setscl);
}

static void parport_setsda(void *data, int state)
{
    line_set(state, &adapter_parm[type].setsda);
}

static int parport_getscl(void *data)
{
    return line_get(&adapter_parm[type].getscl);
}

static int parport_getsda(void *data)
{
    return line_get(&adapter_parm[type].getsda);
}

static void parport_setcsl(void *data, int state)
{
    line_set(state, &adapter_parm[type].setcsl);
}

/* ----- Module init and 
exit---------------------------------------------- */

/* Module init : to be called from the specific driver init routine */
static int spi_parport_init(char *name)
{
    /* adapter_parm set in the spi-parport-light.h header; type is a 
module parameter */
    if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
        printk(KERN_WARNING "%s: invalid parameter \"type\" (%d)\n\
defaulting to type 0\n", name, type);
        type = 0;
    }

    if (base == 0)
        base = DEFAULT_BASE;

    if (!request_region(base, 3, "spi-parport-light"))
        return -EBUSY;

    /* Reset hardware to a sane state (SCL and SDA high) */
    parport_setsda(NULL, 1);
    parport_setscl(NULL, 1);
    /* Other init if needed (power on...) */
    if (adapter_parm[type].init.val)
        line_set(1, &adapter_parm[type].init);
    /* CS deselect, if necessary.. */
    if (adapter_parm[type].setcsl.val)
        line_set(0, &adapter_parm[type].setcsl);

    /* Memory for the spi_device struct for this adapter */
    adapter_parm[type].spidev = kzalloc(sizeof(struct spi_device), 
GFP_KERNEL);
    if (!adapter_parm[type].spidev) {
        printk(KERN_ERR "%s: out of memory\n", name);
        release_region(base, 3);
        return -ENOMEM;
    }

    printk(KERN_INFO "%s loaded: adapter type %d (device '%s'), using 
base address 0x%x\n",
            name, type, adapter_parm[type].name, base);

    return 0;
}

/* Module exit : to be called from the specific driver cleanup routine */
static void spi_parport_exit(char *name)
{
    if (adapter_parm[type].spidev)
        kfree (adapter_parm[type].spidev);

    /* Un-init if needed (power off...) */
    if (adapter_parm[type].init.val)
        line_set(0, &adapter_parm[type].init);
   
    release_region(base, 3);
    printk(KERN_INFO "%s unloaded.\n", name);
}

      parent reply	other threads:[~2006-03-31  6:00 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-02-15  7:54 Stuck creating sysfs hooks for a driver Kaiwan N Billimoria
2006-02-15 22:13 ` Greg KH
2006-02-16 11:33   ` Kaiwan N Billimoria
2006-02-16 12:16     ` Arjan van de Ven
2006-02-16 16:41     ` Greg KH
2006-02-19 13:23     ` Jean Delvare
2006-02-21  6:18       ` Kaiwan N Billimoria
2006-03-31  6:01       ` Kaiwan N Billimoria [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=442CC5BA.2030901@designergraphix.com \
    --to=kaiwan@designergraphix.com \
    --cc=khali@linux-fr.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.