Commit 140ec595 authored by Manohar Vanga's avatar Manohar Vanga

simulation: add 1-wire wishbone driver and adc config binary

Signed-off-by: 's avatarManohar Vanga <manohar.vanga@cern.ch>
parent eaa16b31
# Trivial top-level Makefile
#LINUX ?= $(HOME)/linux-for-wbonesim
CPU?=L865 CPU?=L865
KVER?=2.6.24.7-rt27 KVER?=2.6.24.7-rt27
LINUX?=/acc/sys/$(CPU)/usr/src/kernels/$(KVER) LINUX?=/acc/sys/$(CPU)/usr/src/kernels/$(KVER)
# temporarily, use local <linux/wishbone.h> # temporarily, use local <linux/wishbone.h>
EXTRA_CFLAGS := -I$(obj)/include EXTRA_CFLAGS := -I$(obj)/include -I$(shell /bin/pwd)/drivers/w1/
obj-m = wishbone.o fakedac.o fakeadc.o fake_wb_bus.o wb_onewire.o obj-m = wishbone.o fakedac.o fakeadc.o fake_wb_bus.o wb_onewire.o wb_1wire.o
all: all:
make -C $(LINUX) M=$(shell /bin/pwd) modules make -C $(LINUX) M=$(shell /bin/pwd) modules
......
all: test1w
test1w: test1w.o
clean:
rm -rf test1w
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>
#include "../wb_onewire.h"
int main(int argc, char *argv[])
{
int fd;
int ret;
FILE *file;
int len;
char *buffer;
int num;
char devname[20];
struct wb_onewire_arg a;
if (argc != 2) {
printf("usage: %s <num>\n", argv[0]);
exit(1);
}
a.num = atoi(argv[1]);
sprintf(devname, "/dev/onewire");
fd = open(devname, O_RDWR);
if (fd < 0)
return fd;
if ((ret = ioctl(fd, READ_TEMP, &a)) < 0) {
printf("Error: %d\n", ret);
return ret;
}
printf("Temp RAW: %08x\n", a.temp);
printf("Temp: %08f\n", a.temp/16.0);
close(fd);
return 0;
}
...@@ -29,218 +29,122 @@ ...@@ -29,218 +29,122 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h>
#include <w1.h>
#include <w1_int.h>
#include "wb_onewire.h" #include "wb_onewire.h"
#define OPENCORES_ONEWIRE_VENDOR 0x0 #define OPENCORES_ONEWIRE_VENDOR 0x0
#define OPENCORES_ONEWIRE_DEVICE 0x1 #define OPENCORES_ONEWIRE_DEVICE 0x1
static LIST_HEAD(wb_onewire_list); #define OCOW_REG_CSR 0x0
static DEFINE_MUTEX(onewire_list_lock); #define OCOW_REG_CDR 0x4
#define OCOW_CSR_DAT_MASK (1<<0)
#define OCOW_CSR_RST_MASK (1<<1)
#define OCOW_CSR_OVD_MASK (1<<2)
#define OCOW_CSR_CYC_MASK (1<<3)
#define OCOW_CSR_PWR_MASK (1<<4)
#define OCOW_CSR_IRQ_MASK (1<<6)
#define OCOW_CSR_IEN_MASK (1<<7)
#define OCOW_CSR_SEL_OFS (8)
#define OCOW_CSR_SEL_MASK (0xF<<8)
#define OCOW_CSR_POWER_OFS (16)
#define OCOW_CSR_POWER_MASK (0xFFFF<<16)
#define OCOW_CDR_NOR_MASK (0xFFFF<<0)
#define OCOW_CDR_OVD_OFS (16)
#define OCOW_CDR_OVD_MASK (0XFFFF<<16)
struct wb_onewire_dev { struct wb_onewire_dev {
int num; int num;
int port;
int clk_div_nor;
int clk_div_ovd;
struct wb_device *wbdev; struct wb_device *wbdev;
wb_addr_t base; wb_addr_t base;
struct w1_bus_master master;
struct mutex lock; struct mutex lock;
struct list_head list;
}; };
#define to_wb_onewire_dev(dev) ((struct wb_onewire_dev *)wb_get_drvdata(dev)) #define to_wb_onewire_dev(dev) ((struct wb_onewire_dev *)wb_get_drvdata(dev))
void wb_onewire_devinit(struct wb_onewire_dev *dev) void wb_onewire_init_lowlevel(struct wb_onewire_dev *dev)
{ {
uint32_t data; uint32_t data;
int clk_div_nor = 624;
int clk_div_ovd = 124;
data = ((clk_div_nor&0xffff) | ((clk_div_ovd<<16) & (0xffff<<16)));
wb_writel(dev->wbdev->bus, dev->base + 0x4, data);
}
uint32_t wb_onewire_slot(struct wb_onewire_dev *dev, int port, int bit) data = ((dev->clk_div_nor & OCOW_CDR_NOR_MASK) |
{ ((dev->clk_div_ovd << OCOW_CDR_OVD_OFS) & OCOW_CDR_OVD_MASK));
uint32_t data, reg; wb_writel(dev->wbdev->bus, dev->base + OCOW_REG_CDR, data);
data = (((port<<8) & (0xf<<8)) | (1<<3) | (bit & (1<<0)));
wb_writel(dev->wbdev->bus, dev->base + 0x0, data);
while (wb_readl(dev->wbdev->bus, dev->base + 0x0) & (1 << 3));
reg = wb_readl(dev->wbdev->bus, dev->base + 0x0);
return (reg & (1 << 0));
} }
uint32_t wb_onewire_writebit(struct wb_onewire_dev *dev, int port, int bit) static u8 wb_onewire_touch_bit(void *data, u8 bit)
{ {
return wb_onewire_slot(dev, port, bit); uint32_t val;
} uint32_t reg;
struct wb_onewire_dev *dev = (struct wb_onewire_dev *)data;
uint32_t wb_onewire_readbit(struct wb_onewire_dev *dev, int port) val = (((dev->port << OCOW_CSR_SEL_OFS) & OCOW_CSR_SEL_MASK) |
{ OCOW_CSR_CYC_MASK |
return wb_onewire_slot(dev, port, 0x1); (bit & OCOW_CSR_DAT_MASK));
}
uint8_t wb_onewire_readbyte(struct wb_onewire_dev *dev, int port) wb_writel(dev->wbdev->bus, dev->base + OCOW_REG_CSR, val);
{
int i;
uint8_t data = 0;
for (i = 0; i < 8; i++)
data |= wb_onewire_readbit(dev, port) << i;
return data;
}
int wb_onewire_writebyte(struct wb_onewire_dev *dev, int port, uint8_t byte) /* Wait for the CSR_CYC bit to be unset */
{ while (wb_readl(dev->wbdev->bus, dev->base + OCOW_REG_CSR) &
int i; OCOW_CSR_CYC_MASK);
uint8_t data = 0;
uint32_t tmp;
uint8_t byte_old = byte;
for (i = 0; i < 8; i++) {
data |= ((tmp = wb_onewire_writebit(dev, port, byte & 0x1)) << i);
byte >>= 1;
}
if (byte_old != data)
return -1;
return 0;
}
void wb_onewire_readblock(struct wb_onewire_dev *dev, int port, uint8_t *buf, int len) reg = wb_readl(dev->wbdev->bus, dev->base + OCOW_REG_CSR);
{
int i = 0;
if (len > 160)
return;
for (i = 0; i < len; i++)
*buf++ = wb_onewire_readbyte(dev, port);
}
void wb_onewire_writeblock(struct wb_onewire_dev *dev, int port, uint8_t *buf, int len) return (reg & OCOW_CSR_DAT_MASK);
{
int i = 0;
if (len > 160)
return;
for (i = 0; i < len; i++)
wb_onewire_writebyte(dev, port, buf[i]);
} }
uint32_t wb_onewire_reset(struct wb_onewire_dev *dev, int port) static u8 wb_onewire_reset(void *data)
{ {
uint32_t data, reg; uint32_t val;
data = (((port<<8) & (0xf<<8)) | (1<<3) | (1<<1)); uint32_t reg;
wb_writel(dev->wbdev->bus, dev->base + 0x0, data); struct wb_onewire_dev *dev = (struct wb_onewire_dev *)data;
while (wb_readl(dev->wbdev->bus, dev->base + 0x0) & (1<<3));
reg = wb_readl(dev->wbdev->bus, dev->base + 0x0);
return ((~reg) & (1<<0));
}
void ds18b20_read_serial(struct wb_onewire_dev *dev, int port, uint8_t *sbuf) val = (((dev->port << OCOW_CSR_SEL_OFS) & OCOW_CSR_SEL_MASK) |
{ OCOW_CSR_CYC_MASK |
int i; OCOW_CSR_RST_MASK);
wb_onewire_reset(dev, port);
wb_onewire_writebyte(dev, port, 0x33);
sbuf[0] = wb_onewire_readbyte(dev, port);
for (i = 1; i <= 6; i++)
sbuf[i] = wb_onewire_readbyte(dev, port);
sbuf[7] = wb_onewire_readbyte(dev, port);
}
void ds18b20_access(struct wb_onewire_dev *dev, int port, uint8_t *serial) wb_writel(dev->wbdev->bus, dev->base + OCOW_REG_CSR, val);
{
int i;
wb_onewire_reset(dev, port); /* Wait for the CSR_CYC bit to be unset */
wb_onewire_writebyte(dev, port, 0x55); while (wb_readl(dev->wbdev->bus, dev->base + OCOW_REG_CSR) &
for (i = 0; i < 8; i++) OCOW_CSR_CYC_MASK);
serial[i] = serial[i] & 0xff;
wb_onewire_writeblock(dev, port, serial, 8);
}
int ds18b20_read_temp(struct wb_onewire_dev *dev, int port, uint8_t *serial) reg = wb_readl(dev->wbdev->bus, dev->base + OCOW_REG_CSR);
{
int i;
uint8_t data[9];
int temp;
ds18b20_access(dev, port, serial);
printk("serial: ");
for (i = 7; i >= 0; i--)
printk("%02x ", serial[i]);
printk("\n");
wb_onewire_writebyte(dev, port, 0x44);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ);
ds18b20_access(dev, port, serial);
wb_onewire_writebyte(dev, port, 0xbe);
wb_onewire_readblock(dev, port, data, 9);
printk("data: ");
for (i = 8; i >= 0; i--)
printk("%2x ", data[i]);
printk("\n");
temp = (data[1] << 8) | data[0];
if (temp & 0x1000)
temp = -0x10000 + temp;
return temp;
//temp = temp/16.0
}
int read_onewire_temp(struct wb_onewire_dev *dev) return (reg & OCOW_CSR_DAT_MASK);
{
int temp = 0;
uint8_t serial[10];
ds18b20_read_serial(dev, 0, serial);
temp = ds18b20_read_temp(dev, 0, serial);
return temp;
} }
static int wb_onewire_open(struct inode *inode, struct file *file) static struct wb_device_id wb_onewire_ids[] = {
{ { OPENCORES_ONEWIRE_VENDOR, OPENCORES_ONEWIRE_DEVICE, WB_NO_CLASS },
return 0; { 0, },
} };
static int wb_onewire_release(struct inode *inode, struct file *file) int wb_onewire_dev_init(struct wb_onewire_dev *dev)
{ {
return 0; int ret;
}
int wb_onewire_ioctl(struct inode *inode, struct file *file, memset(&dev->master, 0, sizeof(struct w1_bus_master));
unsigned int ioctl_num, unsigned long ioctl_param)
{
struct wb_onewire_dev *dev;
struct wb_onewire_dev *found = NULL;
struct wb_onewire_arg *arg = (struct wb_onewire_arg *)ioctl_param;
switch (ioctl_num) {
case READ_TEMP: {
printk("looking for device %d\n", arg->num);
mutex_lock(&onewire_list_lock);
list_for_each_entry(dev, &wb_onewire_list, list) {
if (dev->num == arg->num) {
found = dev;
break;
}
}
mutex_unlock(&onewire_list_lock);
if (!found)
return -EFAULT;
arg->temp= read_onewire_temp(found);
printk("Got temp: %08x\n", arg->temp);
break;
}
}
return 0;
}
struct file_operations wb_onewire_ops = { dev->master.data = dev;
.open = wb_onewire_open, dev->master.touch_bit = &wb_onewire_touch_bit;
.release = wb_onewire_release, dev->master.reset_bus = &wb_onewire_reset;
.ioctl = wb_onewire_ioctl,
};
struct miscdevice misc_dev = { ret = w1_add_master_device(&dev->master);
.minor = MISC_DYNAMIC_MINOR, if (ret < 0)
.name = "onewire", return ret;
.fops = &wb_onewire_ops,
};
wb_onewire_init_lowlevel(dev);
static struct wb_device_id wb_onewire_ids[] = { return 0;
{ OPENCORES_ONEWIRE_VENDOR, OPENCORES_ONEWIRE_DEVICE, WB_NO_CLASS }, }
{ 0, },
};
static int wb_onewire_probe(struct wb_device *dev) static int wb_onewire_probe(struct wb_device *dev)
{ {
...@@ -259,14 +163,11 @@ static int wb_onewire_probe(struct wb_device *dev) ...@@ -259,14 +163,11 @@ static int wb_onewire_probe(struct wb_device *dev)
wb_set_drvdata(dev, owdev); wb_set_drvdata(dev, owdev);
mutex_init(&owdev->lock); mutex_init(&owdev->lock);
owdev->num = atomic_inc_return(&devno); owdev->num = atomic_inc_return(&devno);
owdev->port = 0;
owdev->clk_div_nor = 624;
owdev->clk_div_ovd = 124;
wb_onewire_devinit(owdev); wb_onewire_dev_init(owdev);
mutex_lock(&onewire_list_lock);
list_add(&owdev->list, &wb_onewire_list);
mutex_unlock(&onewire_list_lock);
printk("registered device %d\n", owdev->num);
return 0; return 0;
} }
...@@ -277,10 +178,7 @@ static int wb_onewire_remove(struct wb_device *dev) ...@@ -277,10 +178,7 @@ static int wb_onewire_remove(struct wb_device *dev)
pr_info(KBUILD_MODNAME ": %s\n", __func__); pr_info(KBUILD_MODNAME ": %s\n", __func__);
mutex_lock(&onewire_list_lock); w1_remove_master_device(&owdev->master);
list_del(&owdev->list);
mutex_unlock(&onewire_list_lock);
kfree(owdev); kfree(owdev);
return 0; return 0;
...@@ -297,20 +195,15 @@ static struct wb_driver wb_onewire_driver = { ...@@ -297,20 +195,15 @@ static struct wb_driver wb_onewire_driver = {
static int wb_onewire_init(void) static int wb_onewire_init(void)
{ {
int ret; int ret;
if ((ret = misc_register(&misc_dev)))
return ret;
if ((ret = wb_register_driver(&wb_onewire_driver))) { if ((ret = wb_register_driver(&wb_onewire_driver)) < 0)
misc_deregister(&misc_dev);
return ret; return ret;
}
return 0; return 0;
} }
static void wb_onewire_exit(void) static void wb_onewire_exit(void)
{ {
wb_unregister_driver(&wb_onewire_driver); wb_unregister_driver(&wb_onewire_driver);
misc_deregister(&misc_dev);
} }
module_init(wb_onewire_init); module_init(wb_onewire_init);
......
#ifndef WB_ONEWIRE_H
#define WB_ONEWIRE_H
struct wb_onewire_arg {
int num;
int temp;
};
#define __WB_ONEWIRE_IOC_MAGIC 'S'
#define READ_TEMP _IOWR(__WB_ONEWIRE_IOC_MAGIC, 0, struct wb_onewire_arg *)
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment