From owner-freebsd-hackers@FreeBSD.ORG Thu Jun 13 03:36:05 2013 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id E9C85123 for ; Thu, 13 Jun 2013 03:36:05 +0000 (UTC) (envelope-from rysto32@gmail.com) Received: from mail-oa0-x22e.google.com (mail-oa0-x22e.google.com [IPv6:2607:f8b0:4003:c02::22e]) by mx1.freebsd.org (Postfix) with ESMTP id BC74E15DB for ; Thu, 13 Jun 2013 03:36:05 +0000 (UTC) Received: by mail-oa0-f46.google.com with SMTP id h1so2809047oag.19 for ; Wed, 12 Jun 2013 20:36:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:date:message-id:subject:from:to:content-type; bh=qyO7fXPznlS4kFPhJneOCsc5I41qJbxbFyijacLamRk=; b=ecLJeZvWeXxFUEfnaoatfutE34VnCDztFooYWNIoTdSXiHJFBcyD/ZNyxYQhHdGPjy n6po5X7vd/+TH+KnSUKBNrvymOofq/thTNjNJ2Kr1V/4iel5HfAOzTV9aztD7nqUGrAr HpFH/1BBcpMjUUrL6hoDkF6gs4ECIyZKfC69EKKd9qt087uJulwHhxjuvtqJE5KjR1R6 Ed3aNy6ZgETT3EmKN4pGDlkQIryAa5vG26HqhNqF98DVjh40a5WsAydIVJcWpFQfNuNe 7afoFMlx7TWG8nmkspGDdsaEyJt2ejoXa5E9PpJNVik48T4NRGvgCKkLhqP0D0lL3CF0 rQMw== MIME-Version: 1.0 X-Received: by 10.182.74.131 with SMTP id t3mr17525900obv.87.1371094565323; Wed, 12 Jun 2013 20:36:05 -0700 (PDT) Received: by 10.76.91.163 with HTTP; Wed, 12 Jun 2013 20:36:04 -0700 (PDT) Date: Wed, 12 Jun 2013 23:36:04 -0400 Message-ID: Subject: Exposing driver's GPIOs through gpiobus From: Ryan Stone To: "freebsd-hackers@freebsd.org" Content-Type: text/plain; charset=ISO-8859-1 X-Content-Filtered-By: Mailman/MimeDel 2.1.14 X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Jun 2013 03:36:06 -0000 At $WORK we have some custom boards with multi-port uarts managed by puc. The uart devices happen to provide some GPIOs, and our hardware designers have appropriated those GPIOs for various purposes entirely unrelated to the uart. I'm looking for a clean way to provide access to the GPIOs. It occurred to me that this was a problem that should be solved through newbus, and lo and behold I have discovered that FreeBSD provides a gpiobus driver that seems suitable. I've been playing around with this for a couple of days and I have a solutions that is working, but there are aspects that I am unhappy with. I also quite unfamiliar with newbus, so there easily could be better ways to approach the problem that I haven't thought of. What I ended up doing was making gpiobus and gpioc children of the puc bus. In puc_bfe_attach() I create two new child devices of the puc device with device_add_child(), one with the gpioc devclass and one with the gpiobus devclass. I then attach both children with device_probe_and_attach(). I make the puc_pci driver itself provide implementations of the various gpio methods (like gpio_pin_get) so they can be inherited by the child devices. Things start to get somewhat messy in the gpio client code. I have the same image running on many different hardware types, so I can't use device hints to create a child device of the gpiobus. Instead my kernel module tracks down the device_t for the puc, finds the gpiobus child, and uses BUS_ADD_CHILD to create a child of the gpiobus. I had to add a new gpiobus method to allocate GPIO pins to my driver instance. Once that's done, I can toggle GPIOs and whatnot using methods on my driver instance. The things that I'm most unhappy with (newbus-wise, anyway) are: 1) By default the gpioc and gpiobus drivers were claiming the uart children of the puc. I had to decrease their priority in bus_probe to BUS_PROBE_LOW_PRIORITY to work around the problem. I really don't think that was the right solution. I guess I could introduce a new device that is a child of the puc, make sure that it will not claim the uarts, and then make the gpioc and gpiobus children of this device. 2) I'm not sure how to clean up my child device when my module is unloaded. Currently I am checking if it already exists on load and reusing it if so. I may be missing something obvious here. 3) I really don't like the way that I am adding my child to gpiobus. Upon writing this it occurs to me that device_identify would be the canonical way to do this. Previously it wasn't clear to me how to fit device_identify into the current architecture of the gpio client but I see how it can be done now.