how to declare/define hwmon sensor attributes in linux client driver at runtime - linux-kernel

I am looking for a way to create hwmon sysfs nodes at runtime from the Linux kernel driver since a client driver will not maintain sensor list in the driver.
Our Linux kernel client driver does not know the sensor attributes/list at compile time. This driver will get the list of sensors available from firmware at runtime.
Based on the sensors, client driver has to create/register sysfs nodes with hwmon driver.
I am aware of declaring/adding sysfs node with hwmon device at compile time using below code snippet.
/* In client driver */
static ssize_t show_sensor1_info(struct device *dev, struct device_attribute *da, char *buf)
{
// client driver displays sensor1 data
}
static struct sensor_device_attribute sensor_attr1 =
SENSOR_ATTR(sensor1, 0444, show_sensor1_info, NULL, 0);
struct device *hdev = hwmon_device_register(&pdev->dev);
err = device_create_file(hdev, &sensor_attr1.dev_attr);
Output
$ ls /sys/class/hwmon/hwmon*/sensor1
sensor1
Query:
Client driver will not maintain sensor list at compile time. So, how to do the same job at runtime as client driver doesn't know list of sensors available.
It will know only after this driver is loaded. Once this driver's probe is called, it requests all available sensors list from hardware monitor firmware.

I found a way to create hwmon sysfs nodes based on the runtime sensor count.
I referred this code https://elixir.bootlin.com/linux/v4.3/source/drivers/hwmon/acpi_power_meter.c#L630 and it solved my requirement. Thanks.

Related

Linux driver: MFD over PCI

I am writing a driver for a PCI device. The device is a custom development FPGA based device. The FPGA has multiple "devices" on board. I want my driver to create the proper interfaces for those devices.
A certain part of the device will use our own "part". But for I2C busses, I would like to use the already available opencores driver. In the past I had to add the I2C compatible property to the correct "device" in my DTS under my FPGA device (FPGA to CPU was SPI).
Now this has to go over PCI.
The kernel uses my FPGA driver and probes, also created the "own part" as chardev. the I2C opencores drivers ->probe() functions seems not to be called when I create a MFD-cell with the correct compatible property. The cell is added, but never probed.
I use Linux kernel v4.9 on a 64-bit ARM based CPU.
struct x_my_dev {
struct list_head x_my_dev;
struct mfd_cell *mfd_cell;
struct device_node *of_node;
struct property *compat_prop;
struct resource *irq_resource;
struct platform_devive *pdev;
};
...
struct x_my_dev *my_dev;
...
ret = mfd_add_devices(priv->dev, PLATFORM_DEVID_NONE,
my_dev->mfd_cell, 1, NULL, irq_base, NULL)
if (ret) {
dev_err(priv->dev, "Failed to add mfd cell\n");
goto err_mfd_add;
}
...
Already checked if the opencores driver is available in the kernel
The kernel /sys/class/my_fpga/device/I2C_bus/ has only 'driver_override', 'modalias', 'power', 'subsystem' and 'uevent'. Nothing that shows what drivers needs to be used.

Device Tree dependency between two nodes

I have two device tree nodes, one sets a gpio pin and the other one configures one i2c bus, ex:
&gpio2 {
en-gpio {
gpio-hog;
gpios = <5 0>;
output-high;
};
};
&i2c1 {
gpiom1: gpio#27 {
compatible = "microchip,mcp23008";
gpio-controller;
#gpio-cells = <2>;
reg = <0x27>;
};
};
How can i add a dependency between the i2c node and gpio one?
What i want to achieve is that the gpio pin should be set before the devices on i2c are initialized.
Short answer
You can't provide dependency between nodes in this case. But most likely the correct order is already taken care of in your case, and GPIO pin will be set before I2C device initialization, thanks to earlier initcall used for GPIO controller driver, and because gpio-hog is used. If you want to check it for your platform to be sure -- below are details.
Nodes relationship
As stated in Device trees II: The harder parts LWN article:
Naturally, in each case the device which provides the interrupt or GPIO will need to be initialized before it can be found and used. It wasn't very many kernel versions ago that this was a real problem. However in the 3.4 kernel, drivers gained the ability for their initialization (or probe) routine to return the error EPROBE_DEFER which would cause the initialization to be tried again later. So if a driver finds that a GPIO line is listed in the devicetree, but no driver has registered GPIOs for the target node yet, it can fail with EPROBE_DEFER and know it can try again later. This can even be used to remove the need for callbacks and delayed registration in board files, but it is really essential for devicetree, and happily it works quite well.
Alas, in your case it's probably not possible to specify dependency between nodes, so that your i2c1 or gpiom1 depends on gpio2. At least I don't see any gpios properties for I2C controllers or GPIO controllers in Documentation/devicetree/bindings/, that can be used for referencing your en-gpio. So it seems like you should rely on drivers loading order.
Driver dependencies
There are two possible dependencies between drivers:
If drivers are built-in (inside of kernel image): drivers can be initialized at different initcalls, thus being loaded in correct order
If drivers are loadable (.ko files): drivers can have dependencies, defined in kernel build system
As you didn't mention your platform, let's see how it works using BeagleBone Black board for example. You can use this as a template to find out how it's done on your platform.
Static dependencies
Let's check drivers init order:
From am33xx-l4.dtsi file we can see that:
GPIO controller: compatible = "ti,omap4-gpio"
I2C controller: compatible = "ti,omap4-i2c"
I2C device: compatible = "microchip,mcp23008"
Corresponding drivers for those compatible strings are:
GPIO controller: drivers/gpio/gpio-omap.c
I2C controller: drivers/i2c/busses/i2c-omap.c
I2C device: drivers/pinctrl/pinctrl-mcp23s08.c
Those drivers are initialized on next initcalls:
GPIO controller: postcore_initcall (=2)
I2C controller: subsys_initcall (=4)
I2C device: subsys_initcall (=4)
So GPIO controller driver will be initialized before I2C drivers.
Dynamic dependencies
What about dynamic dependencies? From corresponding Makefile and Kconfig files we can see config options and dependencies:
GPIO controller: CONFIG_GPIO_OMAP, tristate, doesn't depend on I2C stuff
I2C controller: CONFIG_I2C_OMA, tristate, doesn't depend on GPIO stuff
I2C device: CONFIG_PINCTRL_MCP23S08, tristate, depends on I2C
So if drivers are loaded in user-space as .ko files, it all depends on the order of their loading, user must take care of it in rootfs. Usually GPIO and I2C controller drivers are built-in, so no need to discuss this further, but just FYI, here is how the order is defined for modprobe tool.
Kernel Configuration
To check how drivers are built (built-in or loadable), one can check .config file. E.g. if multi_v7_defconfig is used:
CONFIG_GPIO_OMAP=y
CONFIG_I2C_OMAP=y
In that case both drivers are built-in, and we know that GPIO driver has earlier initcall than I2C one.
GPIO hogging
You did the right thing by declaring your pin as gpio-hog. You probably already know what it means, but I'll reference the explanation here for everyone else who is interested. From Documentation/devicetree/bindings/gpio/gpio.txt:
The GPIO chip may contain GPIO hog definitions. GPIO hogging is a mechanism
providing automatic GPIO request and configuration as part of the
gpio-controller's driver probe function.
So this is as early as you can get. And if your GPIO controller driver is built-in and has initcall number smaller than one for I2C drivers, you can argue that your en-gpio pin will be set before I2C device driver init.

Difference between uart_register_driver and platform_driver_register?

I am studying UART Driver in kernel code and want to know, who first comes into picture, device_register() or driver_register() call?
For difference between them follow this.
and in UART probing, we call
uart_register_driver(struct uart_driver *drv)
and after successfully registration,
uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
Please explain this in details.
That's actually two questions, but I'll try to address both of them.
who first comes into picture, device_register() or driver_register() call?
As it stated in Documentation/driver-model/binding.txt, it doesn't matter in which particular order you call device_register() and driver_register().
device_register() adds device to device list and iterates over driver list to find the match
driver_register() adds driver to driver list and iterates over device list to find the match
Once match is found, matched device and driver are binded and corresponding probe function is called in driver code.
If you are still curious which one is called first (because it doesn't matter) -- usually it's device_register(), because devices are usually being registered on initcalls from core_initcall to arch_initcall, and drivers are usually being registered on device_initcall, which executed later.
See also:
[1] From where platform device gets it name
[2] Who calls the probe() of driver
[3] module_init() vs. core_initcall() vs. early_initcall()
Difference between uart_register_driver and platform_driver_register?
As you noticed there are 2 drivers (platform driver and UART driver) for one device. But don't let this confuse you: those are just two driver APIs used in one (in fact) driver. The explanation is simple: UART driver API just lacks some functionality we need, and this functionality is implemented in platform driver API. Here is responsibility of each API in regular tty driver:
platform driver API is used for 3 things:
Matching device (described in device tree file) with driver; this way probe function will be executed for us by platform driver framework
Obtaining device information (reading from device tree)
Handling Power Management (PM) operations (suspend/resume)
UART driver API: handling actual UART functionality: read, write, etc.
Let's use drivers/tty/serial/omap-serial.c for driver reference and arch/arm/boot/dts/omap5.dtsi for device reference. Let's say, for example, we have next device described in device tree:
uart1: serial#4806a000 {
compatible = "ti,omap4-uart";
reg = <0x4806a000 0x100>;
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart1";
clock-frequency = <48000000>;
};
It will be matched with platform driver in omap-serial.c by "ti,omap4-uart" string (you can find it in driver code). Then, using that platform driver, we can read properties from device tree node above, and use them for some platform stuff (setting up clocks, handling UART interrupt, etc.).
But in order to expose our device as standard TTY device we need to use UART framework (all those uart_* functions). Hence 2 different APIs: platform driver and UART driver.

Can I query device tree items without creating a platform device?

I am writing a kernel module intended to functionally test a device driver kernel module for an ARM+FPGA SOC system. My approach involves finding which interrupts the device driver is using by querying the device tree. In the device driver itself, I register a platform driver using platform_driver_register and in the .probe function I am passed a platform_device* pointer that contains the device pointer. With this I can call of_match_device and irq_of_parse_and_map, retrieving the irq numbers.
I don't want to register a second platform driver just to query the device tree this way in the test module. Is there some other way I can query the device tree (perhaps more directly, by name perhaps?)
This is what I've found so far, and it seems to work. of_find_compatible_node does what I want. Once I have the device_node*, I can call irq_of_parse_and_map (since of_irq_get_byname doesn't seem to compile for me). I can use it something like the following:
#include <linux/of.h>
#include <linux/of_irq.h>
....
int get_dut_irq(char* dev_compatible_name)
{
struct device_node* dev_node;
int irq = -1;
dev_node = of_find_compatible_node(NULL, NULL, dev_compatible_name);
if (!dev_node)
return -1;
irq = irq_of_parse_and_map(dev_node, 0);
of_node_put(dev_node);
return irq;
}

How to handle two SPI devices in linux kernel with single SPI Platform Driver?

I have developed a SPI platform driver for a single SPI device.Which SPI device we are using,that configuration can be given in Device Tree.probe() function of SPI platform driver is called when name matching happens with name give in driver and the same present in DT.
In SPI platform driver module_init() method, we register SPI device structure (struct spi_driver spidev_spi_driver) with function call: spi_register_driver().
Please refer to the (static struct spi_driver spidev_spi_driver) in below link for example.
Link: http://lxr.free-electrons.com/source/drivers/spi/spidev.c#L664
Here Probe() is one important method registered in this call.
When probe function is called, kernel passes pointer of SPI device (e.g struct spi_device *spi) in probe() function which is further utilized in read and write operation with SPI device.
All the above procedure happens only once for a single SPI device.
Now I have query here that if I want to use more than one SPI device present in my micro controller e.g. imx6 then how I will handle this situation?
How will I receive SPI device pointers in this case?
Is the probe function will be called twice (bcoz here only I get SPI device pointers from kernel)?
Do I need to create entries such as done in spidev_dt_ids:
http://lxr.free-electrons.com/source/drivers/spi/spidev.c#L657
I haven't worked on specifically spi device, but I think I might give you some basic idea. The logic is that probe is called whenever there is matching between device->name and device_driver->name. So 2 devices can use same driver but 2 drivers should not be there for same device.
For configuring 2 devices to same driver, the 2 device will be registered on same name and hence same probe will be called. But then in probe you can differentiate. You will have access to the device struct of spi which you can use to set one parameter to distinguish and set the relevant parameters.
One more approach is like using core framework used by i2c in which general functionality functions are made and used by client driver whenever needed.
I hope this helps.

Resources