Hey guys,
I want to programm a 1-Wire-Host-Driver for my A13-micro to use my DS18S20 temperature sensors (it's controlling everything from light, humidty, temperature for my rain forest terrarium)
I've looked at the standard w1-gpio driver, but that can't be build with the "ugly sunxi gpio" drivers. Then I'had a look at that driver and the vibrator motor driver, to get out how to controll pins on the board. But at this point I got stuck...
Does anybody have some documentation on the sunxi api, or some advise how to control ios in kernel space correctly with that board?
[Driver will be published here, when ready ;-)]
EDIT:
Now you can get all my module sources from:
https://github.com/hhornbacher/a13-kernel-modules (https://github.com/hhornbacher/a13-kernel-modules)
UPDATE:
now the driver is fixed and working (only tested on micro, modified fex/script.bin file needed!):
root@harry-a13-2:~# ls /sys/bus/w1/devices/
10-00080290847e/ w1 bus master/
root@harry-a13-2:~# ls /sys/bus/w1/devices/10-00080290847e/
driver/ id name subsystem/ uevent w1_slave
root@harry-a13-2:~# cat /sys/bus/w1/devices/10-00080290847e/w1_slave
30 00 4b 46 ff ff 0e 10 7c : crc=7c YES
30 00 4b 46 ff ff 0e 10 7c t=23875
made some success, I' working now with script.bin for config and script_parser_fetch(..), gpio_request(...), etc. from mach/sys_config.h
hi,
gpio-sunxi driver for 3.0: https://github.com/linux-sunxi/linux-sunxi/blob/stage/sunxi-3.0/drivers/gpio/gpio-sunxi.c (https://github.com/linux-sunxi/linux-sunxi/blob/stage/sunxi-3.0/drivers/gpio/gpio-sunxi.c)
gpio-sunxi driver for 3.4: https://github.com/linux-sunxi/linux-sunxi/blob/stage/sunxi-3.4/drivers/gpio/gpio-sunxi.c (https://github.com/linux-sunxi/linux-sunxi/blob/stage/sunxi-3.4/drivers/gpio/gpio-sunxi.c)
OK now I have some knowledge about GPIO API and I've modified the w1-gpio module to use this API, it compiles without errors. But when I try to load the module it says device not found:
Error: could not insert module sunxi-w1.ko: No such device
Here is my code:
sunxi-w1.c:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <mach/sys_config.h>
#include "../w1.h"
#include "../w1_int.h"
#include "sunxi-w1.h"
static unsigned gpio_handler;
static script_gpio_set_t info;
static void w1_gpio_write_bit_dir(void *data, u8 bit) {
int ret;
ret = gpio_set_one_pin_io_status(gpio_handler, 1, info.gpio_name);
if (!ret)
gpio_set_one_pin_io_status(gpio_handler, bit, info.gpio_name);
}
static void w1_gpio_write_bit_val(void *data, u8 bit) {
gpio_write_one_pin_value(gpio_handler, bit, info.gpio_name);
}
static u8 w1_gpio_read_bit(void *data) {
return gpio_read_one_pin_value(gpio_handler, info.gpio_name);
}
static int __init w1_gpio_probe(struct platform_device *pdev) {
int err = 0;
int i;
int w1_used = 0;
struct w1_bus_master *master;
struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
if (!pdata)
return -ENXIO;
master = kzalloc(sizeof (struct w1_bus_master), GFP_KERNEL);
if (!master)
return -ENOMEM;
err = script_parser_fetch("w1_para", "w1_used", &w1_used, sizeof (w1_used) / sizeof (int));
if (!w1_used || err) {
printk(KERN_INFO "%s w1-bus is not used in config\n", __FUNCTION__);
err = -1;
goto exit;
}
err = script_parser_fetch("w1_para", "w1_pin", (int *) &info, sizeof (script_gpio_set_t));
gpio_handler = gpio_request_ex("w1_para", "w1_pin");
if (!gpio_handler || err) {
printk(KERN_INFO "%s can not get \"w1_para\" \"w1_pin\" gpio handler, already used by others?", __FUNCTION__);
goto exit;
}
printk(KERN_INFO "w1-bus on w1_pins: port:%d, portnum:%d\n", info.port, info.port_num);
master->data = pdata;
master->read_bit = w1_gpio_read_bit;
if (pdata->is_open_drain) {
gpio_set_one_pin_io_status(gpio_handler, 1, info.gpio_name);
master->write_bit = w1_gpio_write_bit_val;
} else {
gpio_set_one_pin_io_status(gpio_handler, 0, info.gpio_name);
master->write_bit = w1_gpio_write_bit_dir;
}
gpio_write_one_pin_value(gpio_handler, 1, info.gpio_name);
err = w1_add_master_device(master);
if (err)
goto free_gpio;
if (pdata->enable_external_pullup)
pdata->enable_external_pullup(1);
platform_set_drvdata(pdev, master);
return 0;
free_gpio:
gpio_release(gpio_handler, 0);
free_master:
kfree(master);
return err;
return 0;
exit:
return err;
}
static int __exit w1_gpio_remove(struct platform_device *pdev) {
struct w1_bus_master *master = platform_get_drvdata(pdev);
struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
if (pdata->enable_external_pullup)
pdata->enable_external_pullup(0);
w1_remove_master_device(master);
gpio_release(gpio_handler, 0);
kfree(master);
printk(KERN_INFO "Removed: w1-bus on w1_pin [%d,%d]\n", info.port, info.port_num);
return 0;
}
static struct platform_driver w1_gpio_driver = {
.driver =
{
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
.remove = __exit_p(w1_gpio_remove),
};
static int __init w1_gpio_init(void) {
return platform_driver_probe(&w1_gpio_driver, w1_gpio_probe);
}
static void __exit w1_gpio_exit(void) {
platform_driver_unregister(&w1_gpio_driver);
}
module_init(w1_gpio_init);
module_exit(w1_gpio_exit);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
sunxi-w1.h:
#define DRIVER_AUTHOR "Harry Hornbacher <h.hornbacher@gmail.com>"
#define DRIVER_DESC "W1 driver for sunxi devices"
#define DRIVER_NAME "sunxi-w1"
#define DRV_VERSION "0.0.1"
struct w1_gpio_platform_data {
unsigned int pin;
unsigned int is_open_drain:1;
void (*enable_external_pullup)(int enable);
};
and this is the modification in the fex file:
[w1_para]
w1_used = 1
w1_pin = port:PB03<1><default><default><default>
Do you used modprobe or insmod? If this is a module outside of kernel' tree, you need to use insmod
I used insmod, with every other module I wrote it works, I think it has something to do with the
platform_driver_probe(&w1_gpio_driver, w1_gpio_probe);
BTW.: I compiled the Kernel with W1 support.
EDIT:
seems like it doesn't even get to the point of executing platform_driver_probe... -.- don't know whats the matter
I still had no success but as I said before it has something to do with the platform_driver_probe(...) function.
Is there some kernel option I need to enable to use platform_driver?
Sorry, but why you're trying to make a platform driver? Generally platform driver are made to controllers i2c, spi, uart, usb, others...
his intention would be to create client driver? ;)
I thought I have to use the platform_driver to register a w1-bus-master driver... (what i did was porting the w1-gpio.c [http://code.metager.de/source/xref/linux/stable/drivers/w1/masters/w1-gpio.c (http://code.metager.de/source/xref/linux/stable/drivers/w1/masters/w1-gpio.c)] to the a13 gpio-routines, so the w1-gpio driver used platform_driver too. and this module works on other platforms ver well)
But if i don't have to use platform-driver, would else do i have to use for a w1-master driver?
If my first post with the temperature-sensor confused you, there is allready a client module for the DS18S20, but what i need is a driver for w1-protocol on some custom pin ;-)
Alright. ;D
I ask because usually a platform driver have platform_get_resource(), request_mem_region(), ioremap() and sometimes platform_get_irq() and your friend request_irq().
Good luck.
Ah, thanks for the tip! :D
I will do some search on the functions you mentioned, maybe I'll make some success.
EDIT:
Now I've managed to load unload my w1-bus-master driver :D
I had to register a platform_device before adding the platform_driver, which I'm doing now with:
static struct platform_device *w1_sun5i_device = NULL;
...
w1_sun5i_device = platform_device_register_simple(DRIVER_NAME, 0, NULL, 0);
w1_sun5i_device->dev.platform_data = kzalloc(sizeof (struct w1_sun5i_platform_data), GFP_KERNEL);
The new code is availible at my github repository... (https://github.com/hhornbacher/a13-kernel-modules)