Linux device driver for multiple busses - linux

I am trying to get I2C bus driver working for my embedded product.
The driver is currently working fine for bus 0 but it is not working for bus 1.
I see that there is a file named i2c-product.c (I have replaced the name of the chip i2c controller with 'product') and I believe that is the driver for the controller.
It has a function product_i2c_probe(struct platform_device *pd). I see that this is a callback assigned in the platform_driver structure to .probe member. I guess kernel calls into it to setup the driver. Makes sense.
Inside the product_i2c_probe(struct platform_device *pd) function there are following lines to setup the adapter:
drv_data->adapter.dev.parent = &pd->dev;
drv_data->adapter.algo = &product_i2c_algo;
drv_data->adapter.owner = THIS_MODULE;
drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout);
drv_data->adapter.nr = pd->id;
From exploring the code in i2c-core.c and i2c-dev.c, it appears like nr member of the adapter needs to contain the bus id, because that is what gets the minor from the device node. Note I have also created the node using mknod command for both buses. So I have a device /dev/i2c-0 and /dev/i2c-1.
Later in the product_i2c_probe(struct platform_device *pd) function, it adds the adapter to the device using i2c_add_numbered_adapter(&drv_data->adapter).
At the end of the file, I see it registers the device:
static int __init
product_i2c_init(void)
{
return platform_driver_register(&product_i2c_driver);
}
And finally
module_init(product_i2c_init);
So my question is, who calls into the probe() function and passes the platform_device *pd. Clearly this object has the pd->id value that becomes the bus id for the adapter in the line:
drv_data->adapter.nr = pd->id;
Is there a configuration file somewhere? I searched all over but could not find it including the menuconfig.
Any help will be appreciated. As you can probably guess, I am a newbie to device drivers. Am I on the right track, or totally off?
Thanks.

Related

How to use early printk functionality for ARM64?

I am trying to use early printk for arm64 architecture but there is no such functionality.There is something called as earlycon in arm64 that replaces earlyprintk, but its usage is not known to me. I need to print the messages to serial console before real console is initialized. Is there any way to do that in arm64 using earlycon. I applied a patch called arm64: Add simple earlyprintk support to kernel 3.18 but it did not apply successfully. And what is used in arm64 instead of printch?
One can link the functional uart driver either using device tree chosen node or using boot argument.
Before getting into how to use it, you should check whether the platform UART driver supports EARLYCON. For example, directly copied from owl-uart.c
static int __init
owl_uart_early_console_setup(struct earlycon_device *device, const char *opt)
{
if (!device->port.membase)
return -ENODEV;
device->con->write = owl_uart_early_console_write;
return 0;
}
OF_EARLYCON_DECLARE(owl, "actions,owl-uart",
owl_uart_early_console_setup);
Here you can see the UART driver registers it's early console functionality, which will be called by ARCH init code (which runs before start_kernel).
Two options,
Using DTS entry: Use "stdout-path" option in chosen node to specify the serial/uart driver to use
uart3: serial#e0126000 {
compatible = "actions,s900-uart", "actions,owl-uart";
reg = <0x0 0xe0126000 0x0 0x2000>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
status = "okay";
};
aliases {
serial3 = &uart3;
};
chosen {
stdout-path = "serial3:115200n8";
};
Again the example is for Actions SoC from here. With this entry in place, one need to give bootargs as "earlycon" either from u-boot or using the same chosen node "bootargs" option.
Another way is to explicitly specify the driver name using "earlycon" as bootargs like earlyprink. earlycon=owl-uart,e0126000 will ask the kernel to use the earylconsole definition in UART driver and uses the base address for Virtual and physical address mapping.
You can find more details here.

dev_err() function definition

I can see that dev_*() family of functions such as dev_err() are given as prototype in include/linux/device.h, but no where I could find its definition. I have visited sites like lxr.free-electrons, but without success. Used tags in the source code of linux kernel, even then failed.
What I am trying to find is how the dev_err(const struct device *dev, const char *fmt, ...) is able to get the device information such as pci bus, etc from just giving const struct device *dev as argument to print in logs.
Description of the device is constructed in function create_syslog_header, defined in drivers/base/core.c. The function just extracts some fields from struct device object, and emits them via snprintf() into the string.
The function dev_err is implemented via define_dev_printk_level macro in the same file (drivers/base/core.c).

How do you link a device to a custom sysfs class?

I'm writing drivers for several pieces of custom hardware. All of the devices are attached via PCIe to a host computer. For convenience I would like to group all of these custom devices together into a sysfs class (which I believe is an acceptable thing to do?). Unfortunately the information in LDD3 is way out of date and I'm having trouble finding current documentation that discusses what I'm attempting to do.
Creating my custom class is easy enough:
struct class MY_CLASS = class_create(THIS_MODULE, "myclass")
And inside of my probe calls I've got access to the struct dev:
static int probe(struct pci_dev *pcidev, const struct pci_device_id *id)
{
...
struct dev *my_dev = &pcidev->dev;
...
}
My question is this: now that I've got the class and the dev, how do I create a link between the two?
The device_create() basically does what I want, but since I've already got a struct dev my understanding is that I shouldn't call device_create (i.e. create a new device) again.
I've done a little more tracing and found that device_add() which is called by device_create(), calls device_add_class_symlinks() (not exported unfortunately) which does something like this:
...
sysfs_create_link(&dev->class->p->subsys.kobj,&dev->kobj, dev_name(dev));
...
I tried something like this directly in my drivers to create the links I want but I can't get it to compile because struct subsys_private (the "p" member in the class struct) is not exposed anywhere?
Any help is greatly appreciated!
Are your drivers sitting on the specific bus? If no, what purpose of the specific class?
Anyway, for starter
struct class devclass = {…}
probe()
{
struct device *dev = …
dev->class = &devclass;
}
init()
{
class_register(&devclass);
}
I've encountered the same issue.
if i called device_register with my class pointer assigned to the device class member. it will create a subsystem in my device directory, which is what device_add_class_symlinks do. but in my device directory there is already subsystem directory which is the link to the bus my device is attached to.
don't know if you got a method

What "compatible" key to use in device tree?

I'm trying to write a device tree overlay to recognize a SPI-based enc28j60 module to my BeagleBone Black. This module doesn't show up in /kernel-dev/Documentation/devicetree/bindings but there does exist a driver for it in the kernel.
Does the lack of documentation indicate that the device tree binding is missing? Without being able to say something like compatible = "microchip,enc28j60", I'm wondering how else I can use the device tree overlay to load the enc28j60.ko driver?
After some research and grep'ing it appears that devicetree-compatible drivers have a piece of code that looks like:
static struct of_device_id enc28j60_of_match[] __devinitdata = {
{ .compatible = "microchip,enc28j60", },
{}
};
Which is then included in the platform_driver struct. This instructs the kernel how to react if it encounters a compatible = "microchip,enc28j60" in the devicetree overlay.

Probe in Linux DevFreq Driver Not Being Called

I am trying to set up a devfreq driver for a peripheral on Linux. My init method for the driver looks as follows:
static struct platform_driver zynq_csortfreq_driver = {
.probe = zynq_csortfreq_probe,
.driver = {
.name = "ZYNQ_CSORT_DEVFREQ",
.owner = THIS_MODULE,
},
};
static int __init zynq_csortfreq_init(void)
{
return platform_driver_register(&zynq_csortfreq_driver);
}
late_initcall(zynq_csortfreq_init);
However, the probe function (zynq_csortfreq_probe) in my driver never seems to get called. I've read that in order for the probe call to work correctly, the .name value of the driver must match the name of the device - where can I find the name of the device?
In order for the probe function to be called, you must add a device from a machine file or via the device tree. This is typically done with platform_device_register() or platform_add_devices() in machine files. Alternatively, of_platform_populate() is used for the device tree model, but code does not use this directly. The platform device documentation has information for your Linux kernel version. It seems that your Linux uses the device tree model. The documentation in the cpufree devicetree will have some helpful information on activating your driver for this board with device trees.
The dtsi file needs something like,
soc {
zyncfreq#addr {
compatible="xxxx"
/* Other platform data */
Which will define the device for your machine. I would suggest that first you modify your machine files init_machine entry and use platform_device_register() to associate your driver with a device. Then you can later attempt to get the device tree mechanism working if you wish.
If you can view this closed question, my answer might be helpful if the Linux device-model documentation is not completely clear. However, I think for your case the Linux docs are sufficient.
SOLVED:
Problem is in the makefile system. A "dummy" object file must be created and the two "real" files must be combined into the "dummy" object file.
So, new makefile:
#
# Makefile for the mcp3202 driver.
#
obj-$(CONFIG_MCP3202) := mcp3202.o
mcp3202-objs := mcp3202_core.o mcp3202_pru.o
The original "mcp3202.c" was renamed to "mcp3202_core.c". The listed "mcp3202.o" does not need a corresponding .c file since it is created "out of thin air" by the make system by combining mcp3202_core.o and mcp3202_pru.o.
Not very elegant but explains why there's a lot of "_core.c" files strung through out the KERNEL build system. Sounds like an value-added opportunity for a Kernel guru to work on...

Resources