3

I'm a newbie to writing device drivers.

I want to write a device driver for a peripheral on an ARM platform.

1st question: Is it different to write a device driver for a peripheral on ARM platform than on x86 in Linux?

2nd question: I checked /proc/iomem file to view current address map of the processor. However, not all peripherals including the one to which I want to access do not exist in that file. How can I include the address range of a peripheral?

3rd question: What is the importance of a device tree in writing a device driver?

3 Answers 3

5

If the driver does not exist in the kernel source tree, and the device is memory mapped in the device address space, then the device resources (adress region, irq lines) has to be declared somewhere. In older version of the kernel, this was the responsibility of the board file, but now it has moved to the device tree.

So the main difference with x86 architecture is not how you write a driver, but rather how you match devices and driver. On x86, you have for instance pci driver, and pci devices that are discoverable. On ARM, there is generally no such self describing hardware, and to emulate the whole device / driver dance, the platform bus was created.

So a typical device driver on ARM is a platform driver, and the associated devices are platform devices. An example ethernet mac driver from the current kernel is here.

In the above linked driver, the driver code doesn't know where the device lives. This info is passed to the driver at probe time, using the platform_device object. And the platform device can be described like this (source):

static struct platform_device at91sam9260_eth_device = { .name = "macb", .id = -1, .dev = { .dma_mask = &eth_dmamask, .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = &eth_data, }, .resource = eth_resources, .num_resources = ARRAY_SIZE(eth_resources), }; 

Platform device can be created from c code as shown here, or they can be described in device tree. In both cases, you won't see anything in proc/iomem until the device has been probed by the driver. This his in contrast with the x86 world where most devices are PCI devices.

Here is the same device, but described in a device tree file :

 macb0: ethernet@fffc4000 { compatible = "cdns,at32ap7000-macb", "cdns,macb"; reg = <0xfffc4000 0x100>; interrupts = <21 IRQ_TYPE_LEVEL_HIGH 3>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_macb_rmii>; status = "disabled"; }; 
Sign up to request clarification or add additional context in comments.

Comments

4

1. As long as the peripheral is interfaced similarly to the SoC(i.e. uses the same hardware interface on both the platforms), the same driver can be used on both x86 and ARM. This is the advantage of developing modular drivers independent from the Linux kernel core.


2. If your particular peripheral does NOT exist in the current address map(/proc/iomem) then it could mean one of two possibilities :

  • The device driver is not loaded yet.
  • The device uses other form of addressing (NOT memory mapped I/O)

Any additional info about the peripheral? How is it connected to the SoC?


3. A device-tree in the Linux kernel is used to describe the numerous hardware (both-on-chip and peripherals), their inter-connectivity and the basic params applicable for their proper configuration and initialisation on a specific platform/board for which the device-tree is written.

Essentially it performs the same functions and the "board-file" found in current Linux kernel. It also reduces the dependency of bootargs for initial configuration as the same can be provided in the device-tree. More info on device trees.

6 Comments

"The device uses other form of addressing" -- Note that ARM does not have I/O instructions or I/O address space, so peripherals with direct connections have to be memory mapped. Device tree -- availability is kernel version dependent.
SoC has ARM926EJS processor and utilizes AMBA AHB system as bus organization.
At first, I want to access simple peripherals like GPIO, and then External Memory Controller (EMC) interface which provides an interface between the AHB and off-chip memory devices.
All these are NOT peripherals in the strictest sense. Rather they would be peripheral controllers already present on-board the SoC. If the Linux kernel is "officially" supported on the SoC, then you will find these drivers for the controller blocks already in the mainline source. It is just a matter of enabling them by selecting the proper configuration(defconfig).
The information in /proc/iomem comes from drivers calling request_mem_region().
|
1

To export information about address range of a device to /proc userspace interface you have to register this region in your driver to the kernel:

request_mem_region() 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.