St-ericsson Driver

Posted By admin On 31/01/22
  • ST-Ericsson was a multinational manufacturer of wireless products and semiconductors, supplying to mobile device manufacturers. ST-Ericsson was a 50/50 joint venture of Ericsson and STMicroelectronics established on 3 February 2009 and dissolved 2 August 2013.
  • STMicroelectronics is a leading Integrated Device Manufacturer delivering solutions that are key to Smart Driving, Smart Industry, Smart Home & City and Smart Things.
  • Isp1760-hcd project will provides Linux Host Controller driver for the ISP1760 and ISP1761 based on USB High Speed ISP1760/1 Host Controller PCI ST-ERICSSON ISP1760/1 HCD - Browse Files at

What is TrustZone?

A Trusted Execution Environment (TEE) is a hardware assisted tamperproof secure environment where you can run software that are isolated from the rest of the system, such as Linux and other operating systems. The software for a TEE can be implemented in various ways, the crucial thing is to have hardware support. It could for example be an external co-processor or it could be something directly integrated on the chip. To support the TEE concept, Arm® introduced the TrustZone® technology back in 2003. TrustZone is directly integrated into the processor but also extends throughout the system via the AMBA® AXI™ bus and specific TrustZone System IP blocks. Software needed to have a full TEE environment normally consists of some piece of code running on the non-secure side, such as code running in user space in Linux and a supporting Linux kernel driver. Likewise on the secure side, you need to implement software that are running the Trusted OS.

X.Org driver for ST-Ericsson Mali DDK. Contribute to igloocommunity/xorg-x11-drv-ste development by creating an account on GitHub.

The TEE kernel driver before Linaro

Back in 2010 when ST-Ericsson was formed as an outcome of the joint venture between ST-NXP Wireless and Ericsson Mobile Platforms the security department at ST-Ericsson in Lund, Sweden was starting to work with Trusted Execution Environments. The goal was to have a TEE running alongside with Android. The company faced a couple of challenges since most of the engineers were coming from an environment where the primary focus for several years had been on OSE (real-time OS by Enea) Most of the development for OSE took place in a Microsoft Windows environment.

I and a colleague got a task of writing the Linux kernel driver for the TEE solution (back then I was working as a contractor for ST-Ericsson). We both had Linux experience so I think it was a natural choice to let us work on it. This first version of the driver [1] was just simply moving data back and forth between user space and the Trusted OS. We were only using read and write calls for all communication, which in hindsight wasn’t a very good choice. Consider that normally when using the write call, input buffers will still remain the same when returning from the call. In our case we modified that data in the kernel before returning to the caller, which feels a little bit strange. The sane choice would have been to use IOCTL from the beginning. This version of the driver was used in the first TEE solution on ST-Ericsson which was named as “TEE v1” depicted below.

A choice made early on was to implement the interfaces stated by GlobalPlatform. Back in 2012 there was much activity at GlobalPlatform with recurring “TestFests” taking place as a preparation for TEE qualification. This led us to start thinking about how to solve secure storage and secure time use cases. Secure storage is a bit interesting since the Trusted OS doesn’t have its own filesystem and we didn’t want to add one. We were inspired by the wpa_supplicant and came up with something called tee-supplicant, which serves the Trusted OS with services not necessarily available direct in the Trusted OS. To support tee-supplicant we needed to make additional changes to the TEE driver, i.e, we needed to open up a communication channel between user space and the Trusted OS. At the same time we had two different versions of the TEE driver, one for TEE v1 (u8500) and one under development for TEE v2 (u8540). A decision was taken saying that we should unify the two drivers to only have and maintain a single driver, this was a good decision! Due to the necessity of implementing all GlobalPlatform APIs for the qualification, merging two drivers and adding support for tee-supplicant the driver was almost completely re-written. Suddenly the driver started to grew in size and also started to become a bit complex. For example we needed sync points (mutexes) for messages going back and forth between the secure side and the non-secure side. A lot of GlobalPlatform related calls and data structures where showing up in the driver. In the end TEE v2 as depicted above was quite stable, but still it wasn’t upstreamed (and unfortunately I cannot find a link to this version).

STMicroelectronics maintains the code

In 2013 the owners of ST-Ericsson decided to dissolve the company. In principle the parts related to the modem went back to Ericsson and the Linux related commitment went to STMicroelectronics. Since the focus at STMicroelectronics wasn’t about mobile, they started to rework the TEE solution intended for use on set-top boxes. By doing so they also made it possible to use the TEE solution on other architectures than standard Arm TrustZone. Once again the TEE kernel driver was changed, not that much this time, but a few notable things worth mentioning are that they finally got rid of the read and write only communication and started to make use of IOCTL’s also. On the timeline we’re now approaching the date when Linaro decided to form Security Working Group (October 2013). After some initial discussions and decision made by Linaro Board we started to work with STMicroelectronics and once again a few of us was working with the old TEE solution that we had been working with in the past.

TEE kernel driver in OP-TEE

I believe most of the readers of this blog post know about OP-TEE, but let me just quickly summarize what OP-TEE is. OP-TEE is the outcome of the collaboration between STMicroelectronics and other members of Linaro where the source code originates from the proprietary TEE solution coming from ST-Ericsson. In the preparation for making it publicly available it did undergo extensive changes and cleanup. When it came to the TEE driver, we knew that STMicroelectronics internally where re-writing and splitting up the driver into two drivers, i.e, one generic driver communicating with user space and the backplane and the other driver, called backplane driver which was supposed to sit in-between the generic driver and the Trusted OS. We wanted to make use of their updated driver, but at the same time we also wanted to publish OP-TEE. We decided to take a snapshot of the original driver, clean it up and publish it on GitHub (between summer of 2014 and February 2015 this is more or less what you could find on GitHub).

Someone submits a TrustZone driver to LKML

In October 2014 Linaro got access to the reworked driver, we started to review it and use it internally. This was the version that we finally intended to upstream! The plan was to 1) review and test as much as possible on our own, 2) have a kernel maintainer at Linaro have a look at it, 3) then send patches to the kernel mailing list (LKML) for review. Almost on the same week as we had the plan ready we found out that someone just recently posted a proposal for a generic TrustZone interface in the Linux kernel. Now we basically had two choices, should we ignore that there already was a proposal on the mailing list and send our patches anyways? Or should we contact the one (Javier González) that had sent the patches available on the mailing list and asking for eventual collaboration? We ended up doing the latter. The initial contact with Javier was a couple of weeks before Connect / HKG15. Javier and I started to look into commonalities to see whether is was feasible to merge our implementations. The results of our initial exercise was a document with common APIs, differences and some open questions.

A new driver is born

At Connect we had a technical discussion in the hacking room solely about the kernel driver and what to do next. For that discussion we also invited an engineer that had been working with various TEE solutions for quite a while. We had a really good discussion that was continued by email after Connect. The outcome of the discussion was that OP-TEE’s driver was still too GlobalPlatform and OP-TEE centric even though much work had been done to make it more generic. Also we wanted to incorporate ideas from both OP-TEE and Javier’s patch set into one common solution for a generic TEE (and not only TrustZone) solution. Having that said we started to re-implement the driver taking the good ideas and concepts from the original driver from STMicroelectronics and this time we were also taking into account Javier’s ideas and from others involved in the discussion at the tee-dev mailing list. The big difference this time is that a lot of functionality has been moved from the kernel driver to user space instead which makes the kernel driver much cleaner compared to previous implementations. Also the generic part of the driver is completely free from GlobalPlatform related code which means that other implementations which are not following GlobalPlatform APIs also should be able to use this driver. The first patchset with this new implementation was sent 17th April 2015. I think it was well received and we got some good and constructive feedback. Since then we addressed the comments and we have sent both v2 and v3 are are currently waiting for feedback from kernel maintainers.

Lessons learned

So, what is the takeaway from this long story about the kernel driver supposed to support Trusted Execution Environments? Well, there are a few things to consider, most important is “submit early, submit often”. That is the key message from all kernel maintainers. I am pretty sure that if we had submitted patches from the beginning we would have had a TEE driver integrated in the kernel for quite a while now. Likewise I’m also pretty sure that the driver still would had been rewritten and extended when found in the kernel, but I don’t think it would require as many iterations as we have seen for the driver we have been working with. Another thing to consider is that you shouldn’t neglect the importance of talking and getting feedback from engineers outside of your own company. If you’re just working within your own environment and don’t get much feedback from outside, there a big risk that you become blind and eventually miss important details. So basically what I’m saying is that please, realize the importance of upstreaming and please try to convince your authorities where you are working to support you in doing upstream work!

References / Links


placeholder - general description of supported platforms, what dc is, etc.

Because it is partially shared with other operating systems, the Display CoreDriver is divided in two pieces.

  1. Display Core (DC) contains the OS-agnostic components. Things likehardware programming and resource management are handled here.
  2. Display Manager (DM) contains the OS-dependent components. Hooks to theamdgpu base driver and DRM are implemented here.

It doesn’t help that the entire package is frequently referred to as DC. Butwith the context in mind, it should be clear.

When CONFIG_DRM_AMD_DC is enabled, DC will be initialized by default forsupported ASICs. To force disable, set amdgpu.dc=0 on kernel command line.Likewise, to force enable on unsupported ASICs, set amdgpu.dc=1.

To determine if DC is loaded, search dmesg for the following entry:


AMDgpu Display Manager¶

The AMDgpu display manager, amdgpu_dm (or even simpler,dm) sits between DRM and DC. It acts as a liason, converting DRMrequests into DC requests, and DC responses into DRM responses.

St-ericsson driver salary

The root control structure is structamdgpu_display_manager.

struct irq_list_head

Linked-list for low context IRQ handlers.



The list_head within structhandler_data
A work_struct containing the deferred handler work
struct dm_compressor_info

Buffer info used by frame buffer compression



MMIO cpu addr
Pointer to the buffer object
MMIO gpu addr
struct amdgpu_dm_backlight_caps

Information about backlight



Keep the data struct with all the information about thedisplay support for HDR.
Min brightness value supported by the display
Max brightness value supported by the displayin nits.
minimum possible input in range 0-255.
maximum possible input in range 0-255.
true if these values are from the ACPI interface.
Describes if the display supports AUX backlight.


Describe the backlight support for ACPI or eDP AUX.

struct amdgpu_display_manager

Central amdgpu display manager device



Display Core control structure
DMUB service, used for controlling the DMUB on hardwarethat supports it. The pointer to the dmub_srv will beNULL on hardware that does not support it.
Framebuffer regions for the DMUB.
DMUB firmware, required on hardware that has DMUB support.
Buffer object for the DMUB.
GPU virtual address for the DMUB buffer object.
CPU address for the DMUB buffer object.
DMCUB firmware version.
The Common Graphics Services device. It provides an interface foraccessing registers.
AMDGPU base driver structure
DRM base driver structure
Max number of display streams supported
In combination with dm_atomic_state it helps manageglobal atomic state that doesn’t map cleanly into existingdrm resources, like dc_context.
Guards access to DC functions that can issue register writesequences.
Guards access to audio instance changes.
Used to notify ELD changes to sound driver.
True if the audio component has been registeredsuccessfully, false otherwise.

Low priority IRQ handler table.

It is a n*m table consisting of n IRQ sources, and m handlers per IRQsource. Low priority IRQ handlers are deferred to a workqueue to beprocessed. Hence, they can sleep.

Note that handlers are called in the same order as they wereregistered (FIFO).


High priority IRQ handler table.

It is a n*m table, same as irq_handler_list_low_tab. However,handlers in this table are not deferred and are called immediately.

St-ericsson driver ed
Page flip IRQ parameters, passed to registered handlers whentriggered.
Vertical blanking IRQ parameters, passed to registered handlers whentriggered.
DriverSt-ericsson dfu driver.rar
Vertical update IRQ parameters, passed to registered handlers whentriggered.
Synchronizes access to IRQ tables
Backlight control device

St-ericsson Driver Ed

Link on which to control backlight
Capabilities of the backlight device
Module handling freesync calculations
AMDGPU content protection queue
Caches device atomic state for suspend/resume
Cached state of content streams
Frame buffer compression buffer. See structdm_compressor_info
Reference to DMCU firmware

Samsung E2252 St-ericsson Driver

Version of the DMCU firmware
gpu_info FW provided soc bounding box struct or 0 if notavailable in FW
fake encoders used for DP MST.
set via debugfs. When set, indicates that all connecteddisplays will be forced to synchronize.


DM (and consequently DC) is registered in the amdgpu base driver as a IPblock. When CONFIG_DRM_AMD_DC is enabled, the DM device IP block is added tothe base driver’s device list to be initialized and torn down accordingly.

The functions to do so are provided as hooks in structamd_ip_funcs.

int dm_hw_init(void *handle)

Initialize DC device


The base driver device containing the amdgpu_dm device.


Initialize the structamdgpu_display_manager device. This involves callingthe initializers of each DM component, then populating the struct with them.

Although the function implies hardware initialization, both hardware andsoftware are initialized here. Splitting them out to their relevant inithooks is a future TODO item.

Some notable things that are initialized here:

  • Display Core, both software and hardware
  • DC modules that we need (freesync and color management)
  • DRM software states
  • Interrupt sources and handlers
  • Vblank support
  • Debug FS entries, if enabled
int dm_hw_fini(void *handle)

Teardown DC device


The base driver device containing the amdgpu_dm device.


Teardown components within structamdgpu_display_manager that requirecleanup. This involves cleaning up the DRM device, DC, and any modules thatwere loaded. Also flush IRQ workqueues and disable them.


DM provides another layer of IRQ management on top of what the base driveralready provides. This is something that could be cleaned up, and is afuture TODO item.

The base driver provides IRQ source registration with DRM, handlerregistration into the base driver’s IRQ table, and a handler callbackamdgpu_irq_handler(), with which DRM calls on interrupts. This generichandler looks up the IRQ table, and calls the respectiveamdgpu_irq_src_funcs.process hookups.

What DM provides on top are two IRQ tables specifically for top-half andbottom-half IRQ handling, with the bottom-half implementing workqueues:

They override the base driver’s IRQ table, and the effect can be seenin the hooks that DM provides for amdgpu_irq_src_funcs.process. Theyare all set to the DM generic handler amdgpu_dm_irq_handler(), which looks upDM’s IRQ tables. However, in order for base driver to recognize this hook, DMstill needs to register the IRQ with the base driver. Seedce110_register_irq_handlers() and dcn10_register_irq_handlers().

To expose DC’s hardware interrupt toggle to the base driver, DM implementsamdgpu_irq_src_funcs.set hooks. Base driver calls it throughamdgpu_irq_update() to enable or disable the interrupt.

struct amdgpu_dm_irq_handler_data

Data for DM interrupt handlers.



Linked list entry referencing the next/previous handler
Handler function
Argument passed to the handler when triggered
DM which this handler belongs to
DC interrupt source that this handler is registered for
void dm_irq_work_func(struct work_struct *work)

Handle an IRQ outside of the interrupt handler proper.


work struct
void * amdgpu_dm_irq_register_interrupt(struct amdgpu_device *adev, struct dc_interrupt_params *int_params, void (*ih)(void *), void *handler_args)

Register a handler within DM.


The base driver device containing the DM device.
Interrupt parameters containing the source, and handler context
Function pointer to the interrupt handler to register
Arguments passed to the handler when the interrupt occurs


Register an interrupt handler for the given IRQ source, under the givencontext. The context can either be high or low. High context handlers areexecuted directly within ISR context, while low context is executed within aworkqueue, thereby allowing operations that sleep.

Registered handlers are called in a FIFO manner, i.e. the most recentlyregistered handler will be called first.


Handler data structamdgpu_dm_irq_handler_data containing the IRQ
source, handler function, and args
void amdgpu_dm_irq_unregister_interrupt(struct amdgpu_device *adev, enum dc_irq_source irq_source, void *ih)

Remove a handler from the DM IRQ table


The base driver device containing the DM device
IRQ source to remove the given handler from
Function pointer to the interrupt handler to unregister


Go through both low and high context IRQ tables, and find the given handlerfor the given irq source. If found, remove it. Otherwise, do nothing.

int amdgpu_dm_irq_init(struct amdgpu_device *adev)

Initialize DM IRQ management


The base driver device containing the DM device


Initialize DM’s high and low context IRQ tables.

The N by M table contains N IRQ sources, with Mstructamdgpu_dm_irq_handler_data hooked together in a linked list. Thelist_heads are initialized here. When an interrupt n is triggered, all mhandlers are called in sequence, FIFO according to registration order.

The low context table requires special steps to initialize, since handlerswill be deferred to a workqueue. See structirq_list_head.

void amdgpu_dm_irq_fini(struct amdgpu_device *adev)

Tear down DM IRQ management


The base driver device containing the DM device


Flush all work within the low context IRQ table.

int amdgpu_dm_irq_handler(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry)

Generic DM IRQ handler


amdgpu base driver device containing the DM device
Data about the triggered interrupt


Calls all registered high irq work immediately, and schedules work for lowirq. The DM IRQ table is used to find the corresponding handlers.

void amdgpu_dm_hpd_init(struct amdgpu_device *adev)

hpd setup callback.


amdgpu_device pointer


Setup the hpd pins used by the card (evergreen+).Enable the pin, set the polarity, and enable the hpd interrupts.

void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)

hpd tear down callback.


amdgpu_device pointer


Tear down the hpd pins used by the card (evergreen+).Disable the hpd interrupts.

void dm_pflip_high_irq(void *interrupt_params)

Handle pageflip interrupt




Handles the pageflip interrupt by notifying all interested partiesthat the pageflip has been completed.

void dm_crtc_high_irq(void *interrupt_params)

Handles CRTC interrupt

St-ericsson Driver Updater


used for determining the CRTC instance


Handles the CRTC/VSYNC interrupt by notfying DRM’s VBLANKevent handler.

Atomic Implementation¶


void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)

AMDgpu DM’s commit tail implementation.


The atomic state to commit


This will tell DC to commit the constructed DC state from atomic_check,programming the hardware. Any failures here implies a hardware failure, sinceatomic check should have filtered anything non-kosher.

int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)

Atomic check implementation for AMDgpu DM.


The DRM device
The atomic state to commit


Validate that the given atomic state is programmable by DC into hardware.This involves constructing a structdc_state reflecting the new hardwarestate we wish to commit, then querying DC to see if it is programmable. It’simportant not to modify the existing DC state. Otherwise, atomic_checkmay unexpectedly commit hardware changes.

St-ericsson-full Speed-dfu Driver

When validating the DC state, it’s important that the right locks areacquired. For full updates case which removes/adds/updates streams on oneCRTC while flipping on another CRTC, acquiring global lock will guaranteethat any such full update commit will wait for completion of any outstandingflip using DRMs synchronization events.

Note that DM adds the affected connectors for all CRTCs in state, when thatmight not seem necessary. This is because DC stream creation requires theDC sink, which is tied to the DRM connector state. Cleaning this up shouldbe possible but non-trivial - a possible TODO item.


-Error code if validation failed.