megi's PinePhone Development Log RSS

Surgenons in Gaza Surgeons in Gaza

2022–02–01: Pinephone Pro – Type C port support

Since November last year, I've been working on and off on understanding and implementing support for Type-C port on Pinephone Pro. It's a complex physical interface, so it was hard to understand how everything fits together on the Rockchip platform without going through a lot of drivers and without understanding the USB Type-C specification. I already had some grasp of the Type-C spec from implementing support for the similar functionality on original Pinephone.

So my approach with Pinephone Pro was to find all existing drivers that are related to supporting all the features of the Type-C port on RK3399 and read them top to bottom.

This gave me a nice overview of how everything can fit together eventually, and also what's missing in mainline Linux compared to Rockchip BSP Linux.

I was also interested in making Type-C support (which includes power negotiation, charging and supplying power, USB data role switching, Display Port alternate mode, power delivery and BC1.2 spec support, and similar things) work as best as possible as soon as possible, so that when Pinephone Pro got to a wider audience, all this worked as well as was possible to achieve with my limited resources in a few weaks before I was going to winter holidays.

Once I understood the drivers and their supposed interactions, I needed to make them talk together with as little code changes as possible. This meant using their existing interfaces.

Mainline Linux is moving in the direction of using in-kernel Type-C interfaces for controlling the drivers that need to listen to the Type-C port manager driver. Most drivers on the Rockchip platform don't support these interfaces, and even if they did, these interfaces currently don't support controlling multiple devices at once, which is necessary on this particular platform. Instead, Rockchip drivers mostly use extcon interface (bus, really) to communicate among each other.

So as a quick stop-gap solution I decided to write the typec-extcon driver, which adapts Type-C mux/switch/role interfaces into extcon ones the existing drivers understand. This made it possible to quickly wire things things together, and be able to start testing the hardware, and finding bugs.

It works semi-reasonably now. Interdriver communication is now solid, with my latest kernel releases for Pinephone Pro.

That doesn't mean there are no issues. The drivers themselves, that are already mainline, have several issues:

USB driver will probably be reasonably easy to fix. BSP driver does things correctly, so it can serve as an inspiration.

fusb302 will be tough to fix. The chip is not horribly complicated, but TCPM driver fusb302 serves as a backend to is, and fusb302's problem is more in the fact that it's quite low level, so you're setting comparators, dealing with D/A converters, voltages, pull-up resistor values, etc. But the higher level deals with abstract states on the CC pins. So far, issues with the driver revolve around misdetection of states of CC pins, and infinite loops, or unhandled states due to that.

Once the individual drivers are made to behave properly, it will be time to think about mainlining this work. I have some plan that involves waiting for multi consumer support for in-kernel Type-C interfaces, that is being proposed on the USB mailing list to be reviewed and accepted. This patchset will help solve the driver communication issue, in an upstreamable way, by allowing TCPM to talk to multiple drivers at once. The drivers will also need to be adapted to use the proper interfaces. This will be fairly easy at that point.

Once all that is done, it will be possible to upstream the whole work.

In the meantime there are drivers to fix.

Fixing up fusb302 is the highest priority. Identifying and solving issues in the wild, from people using the interim solution will be another one.

When working on anx7688 driver I was able to stuff it with a lot of useful debug output, that was then all printed to the kernel log. This allowed me to just ask people to send me their dmesg output, when I noticed someone had issues with things related to Type-C port, and I would not need much else from them. I gradually improved the debug output as I tracked the known issues to be able to understand them better as more people reported issues and sent the logs. This was nice, and helped stabilize the Type-C support on original Pinephone.

Compared to that, Pinephone Pro seems quite hopeless. There's almost 0 useful output in kernel log itself, useful logs are hidden deep in debugfs and sysfs in several places, etc. It's very time consuming to do debugging with users, because of that. Reading the logs is hader too, becuase they are very verbose and low-level, and are split, so there's no single timeline to skim through. They need to be cross-references manually.

I decided to not add to this difficulty, and only help users who will be able to install and run my exact kernel build for debugging. It's just too much effort to also track what subset of my patches some unknown version of the downstream Linux distribution's kernel, with no existing git tree to diff against, decided to include.

It will take maybe 4 kernel releases to clean up for the upstreaming attempt.

I'll step away from this work for a while to prepare basic device tree for Pinephone Pro and submit it mainline. Otherwise things will start getting messy pretty soon with multiple kernel trees being actively used by distributions and no shared base device tree upstream.