How to use early printk functionality for ARM64? - linux

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.

Related

Using GPIOs within a kernel module

i am quiet new at writing kernel drivers and there is something bothering me a lot. It would be great if you could kcik me into the right direction.
I am writing a module for a device, that has to be powered via putting a GPIO to HIGH-State.
In Documentation/gpio/* are texts, which say i should use the new descriptor-based interface of the GPIO Framework. But how to use it?
When i make an include like #include
it compiles and i can run the driver. But using gpiod_get(...) just returns fffffffffffffffe. It makes sense somehow, as the implentation of that function within linux/gpio/consumer.h is
static inline struct gpio_desc *__must_check gpiod_get(struct device
*dev, const char *con_id,enum gpiod_flags flags){
return ERR_PTR(-ENOSYS);
}
The implementation of the function exists in drivers/gpio/devres.c as well. How can i use that one?
It looks to me as i am not supposed to use that implementation.
I hope you can help me as it is getting really irritating.
As it turned out it was just necessary to include the file gpio/gpiolib as well which delivers additional definitions.

Linux device driver for multiple busses

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.

Why device exist in /proc/devices evethough module is unloaded

I am writing a simple charcter driver scull based on ldd. For my sample character driver, evethough module is unloaded device with major number exist in /proc/devices. How to remove that?
My module exit function has
void scull_exit(void)
{
unregister_chrdev(Major, "scull1");
cdev_del(my_cdev);
printk(KERN_ALERT "Good Bye\n");
}
I could see the old device with its major number when I load new module after unloading the same.
cdev_del takes a pointer, ensure that your my_cdev is a
pointer.
void cdev_del(struct cdev *);
It is cdev_del, first and unregister_chrdev later, it seems you
have done it the other way, use cdev_del first and then unregister_chrdev_region
You have mixed up old notation of unregister_chrdev and new notation of cdev_del.
either unregister_chrdev should be used when you use register_chrdev for registering
OR
"cdev_init/cdev_add after register_chrdev_region" should be used in conjunction with "cdev_del before unregister_chrdev_region"
struct cdev has an owner field that should be set to THIS_MODULE. Make sure it is set

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