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
KVER?=2.6.24.7-rt27
LINUX?=/acc/sys/$(CPU)/usr/src/kernels/$(KVER)
# 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:
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 @@
#include <linux/fs.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <w1.h>
#include <w1_int.h>
#include "wb_onewire.h"
#define OPENCORES_ONEWIRE_VENDOR 0x0
#define OPENCORES_ONEWIRE_DEVICE 0x1
static LIST_HEAD(wb_onewire_list);
static DEFINE_MUTEX(onewire_list_lock);
#define OCOW_REG_CSR 0x0
#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 {
int num;
int port;
int clk_div_nor;
int clk_div_ovd;
struct wb_device *wbdev;
wb_addr_t base;
struct w1_bus_master master;
struct mutex lock;
struct list_head list;
};
#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;
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)
{
uint32_t data, reg;
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));
data = ((dev->clk_div_nor & OCOW_CDR_NOR_MASK) |
((dev->clk_div_ovd << OCOW_CDR_OVD_OFS) & OCOW_CDR_OVD_MASK));
wb_writel(dev->wbdev->bus, dev->base + OCOW_REG_CDR, data);
}
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)
{
return wb_onewire_slot(dev, port, 0x1);
}
val = (((dev->port << OCOW_CSR_SEL_OFS) & OCOW_CSR_SEL_MASK) |
OCOW_CSR_CYC_MASK |
(bit & OCOW_CSR_DAT_MASK));
uint8_t wb_onewire_readbyte(struct wb_onewire_dev *dev, int port)
{
int i;
uint8_t data = 0;
for (i = 0; i < 8; i++)
data |= wb_onewire_readbit(dev, port) << i;
return data;
}
wb_writel(dev->wbdev->bus, dev->base + OCOW_REG_CSR, val);
int wb_onewire_writebyte(struct wb_onewire_dev *dev, int port, uint8_t byte)
{
int i;
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;
}
/* Wait for the CSR_CYC bit to be unset */
while (wb_readl(dev->wbdev->bus, dev->base + OCOW_REG_CSR) &
OCOW_CSR_CYC_MASK);
void wb_onewire_readblock(struct wb_onewire_dev *dev, int port, uint8_t *buf, int len)
{
int i = 0;
if (len > 160)
return;
for (i = 0; i < len; i++)
*buf++ = wb_onewire_readbyte(dev, port);
}
reg = wb_readl(dev->wbdev->bus, dev->base + OCOW_REG_CSR);
void wb_onewire_writeblock(struct wb_onewire_dev *dev, int port, uint8_t *buf, int len)
{
int i = 0;
if (len > 160)
return;
for (i = 0; i < len; i++)
wb_onewire_writebyte(dev, port, buf[i]);
return (reg & OCOW_CSR_DAT_MASK);
}
uint32_t wb_onewire_reset(struct wb_onewire_dev *dev, int port)
static u8 wb_onewire_reset(void *data)
{
uint32_t data, reg;
data = (((port<<8) & (0xf<<8)) | (1<<3) | (1<<1));
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 val;
uint32_t reg;
struct wb_onewire_dev *dev = (struct wb_onewire_dev *)data;
void ds18b20_read_serial(struct wb_onewire_dev *dev, int port, uint8_t *sbuf)
{
int i;
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);
}
val = (((dev->port << OCOW_CSR_SEL_OFS) & OCOW_CSR_SEL_MASK) |
OCOW_CSR_CYC_MASK |
OCOW_CSR_RST_MASK);
void ds18b20_access(struct wb_onewire_dev *dev, int port, uint8_t *serial)
{
int i;
wb_writel(dev->wbdev->bus, dev->base + OCOW_REG_CSR, val);
wb_onewire_reset(dev, port);
wb_onewire_writebyte(dev, port, 0x55);
for (i = 0; i < 8; i++)
serial[i] = serial[i] & 0xff;
wb_onewire_writeblock(dev, port, serial, 8);
}
/* Wait for the CSR_CYC bit to be unset */
while (wb_readl(dev->wbdev->bus, dev->base + OCOW_REG_CSR) &
OCOW_CSR_CYC_MASK);
int ds18b20_read_temp(struct wb_onewire_dev *dev, int port, uint8_t *serial)
{
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
}
reg = wb_readl(dev->wbdev->bus, dev->base + OCOW_REG_CSR);
int read_onewire_temp(struct wb_onewire_dev *dev)
{
int temp = 0;
uint8_t serial[10];
ds18b20_read_serial(dev, 0, serial);
temp = ds18b20_read_temp(dev, 0, serial);
return temp;
return (reg & OCOW_CSR_DAT_MASK);
}
static int wb_onewire_open(struct inode *inode, struct file *file)
{
return 0;
}
static struct wb_device_id wb_onewire_ids[] = {
{ OPENCORES_ONEWIRE_VENDOR, OPENCORES_ONEWIRE_DEVICE, WB_NO_CLASS },
{ 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,
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;
}
memset(&dev->master, 0, sizeof(struct w1_bus_master));
struct file_operations wb_onewire_ops = {
.open = wb_onewire_open,
.release = wb_onewire_release,
.ioctl = wb_onewire_ioctl,
};
dev->master.data = dev;
dev->master.touch_bit = &wb_onewire_touch_bit;
dev->master.reset_bus = &wb_onewire_reset;
struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "onewire",
.fops = &wb_onewire_ops,
};
ret = w1_add_master_device(&dev->master);
if (ret < 0)
return ret;
wb_onewire_init_lowlevel(dev);
static struct wb_device_id wb_onewire_ids[] = {
{ OPENCORES_ONEWIRE_VENDOR, OPENCORES_ONEWIRE_DEVICE, WB_NO_CLASS },
{ 0, },
};
return 0;
}
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);
mutex_init(&owdev->lock);
owdev->num = atomic_inc_return(&devno);
owdev->port = 0;
owdev->clk_div_nor = 624;
owdev->clk_div_ovd = 124;
wb_onewire_devinit(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);
wb_onewire_dev_init(owdev);
return 0;
}
......@@ -277,10 +178,7 @@ static int wb_onewire_remove(struct wb_device *dev)
pr_info(KBUILD_MODNAME ": %s\n", __func__);
mutex_lock(&onewire_list_lock);
list_del(&owdev->list);
mutex_unlock(&onewire_list_lock);
w1_remove_master_device(&owdev->master);
kfree(owdev);
return 0;
......@@ -297,20 +195,15 @@ static struct wb_driver wb_onewire_driver = {
static int wb_onewire_init(void)
{
int ret;
if ((ret = misc_register(&misc_dev)))
return ret;
if ((ret = wb_register_driver(&wb_onewire_driver))) {
misc_deregister(&misc_dev);
if ((ret = wb_register_driver(&wb_onewire_driver)) < 0)
return ret;
}
return 0;
}
static void wb_onewire_exit(void)
{
wb_unregister_driver(&wb_onewire_driver);
misc_deregister(&misc_dev);
}
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