From patchwork Sun Dec 2 15:01:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ming Lei X-Patchwork-Id: 1830941 Return-Path: X-Original-To: patchwork-linux-omap@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id EE304DF254 for ; Sun, 2 Dec 2012 15:02:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753321Ab2LBPCk (ORCPT ); Sun, 2 Dec 2012 10:02:40 -0500 Received: from mail-pb0-f46.google.com ([209.85.160.46]:56131 "EHLO mail-pb0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753233Ab2LBPCj (ORCPT ); Sun, 2 Dec 2012 10:02:39 -0500 Received: by mail-pb0-f46.google.com with SMTP id wy7so1445313pbc.19 for ; Sun, 02 Dec 2012 07:02:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=6O+XmnpvNSjsd5Nf25X38GqsU81cro4oLF8U+aOAFho=; b=zFJnReWOHOBcKazXWPGydIKF+qB0aFh8h45ksEPFhm4nVfpVEzZ3tHxtJV/4pb2upF 9LKoDInvkWBaLowUrAk0lBsgHt4Ti/VTzD6OgE256Bvc8wSiIPLBWHCQkEWU8rVEu1Nb h11ui/p0C0ZpuqiYwKVc+4mZPVg6+ebdojd7VKYzIyzvB9D0uITe4g/xa61BJwjVXgAZ 4o8aOl24D5S6hxkwUSD5+RlEuhge5ErQtPCl0ueMNmTvKryCCbcerLvuW5FjnY/LOAj8 9orj/Oa8fP4MLQgtUvLqqbxTHfXCh8H3zx3IzoFcYHwXzb/PuH/mpbr2abCsF1Unn+KL +rCA== Received: by 10.68.213.6 with SMTP id no6mr21420256pbc.113.1354460558783; Sun, 02 Dec 2012 07:02:38 -0800 (PST) Received: from localhost ([183.37.207.193]) by mx.google.com with ESMTPS id wr4sm5149605pbc.72.2012.12.02.07.02.29 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 02 Dec 2012 07:02:37 -0800 (PST) From: Ming Lei To: Alan Stern , Greg Kroah-Hartman Cc: Lan Tianyu , Sarah Sharp , "Rafael J. Wysocki" , linux-pm@vger.kernel.org, Oliver Neukum , linux-omap@vger.kernel.org, linux-usb@vger.kernel.org, Ming Lei , Andy Green , Roger Quadros , Felipe Balbi Subject: [RFC PATCH 4/5] arm: omap2: support port power on lan95xx devices Date: Sun, 2 Dec 2012 23:01:06 +0800 Message-Id: <1354460467-28006-5-git-send-email-tom.leiming@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1354460467-28006-1-git-send-email-tom.leiming@gmail.com> References: <1354460467-28006-1-git-send-email-tom.leiming@gmail.com> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org This patch defines power controller for powering on/off LAN95xx USB hub and USB ethernet devices, and implements one match function to associate the power controller with related USB port device. The big problem of this approach is that it depends on the global device ADD/DEL notifier. Another idea of associating power controller with port device is by introducing usb port driver, and move all this port power control stuff from platform code to the port driver, which is just what I think of and looks doable. The problem of the idea is that port driver is per board, so maybe cause lots of platform sort of code to be put under drivers/usb/port/, but this approach can avoid global device ADD/DEL notifier. I'd like to get some feedback about which one is better or other choice, then I may do it in next cycle. Cc: Andy Green Cc: Roger Quadros Cc: Alan Stern Cc: Felipe Balbi Signed-off-by: Ming Lei --- arch/arm/mach-omap2/board-omap4panda.c | 99 +++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 5c8e9ce..3183832 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include @@ -154,6 +156,99 @@ static struct gpio panda_ehci_gpios[] __initdata = { { GPIO_HUB_NRESET, GPIOF_OUT_INIT_LOW, "hub_nreset" }, }; +static void ehci_hub_power_on(struct power_controller *pc, struct device *dev) +{ + gpio_set_value(GPIO_HUB_NRESET, 1); + gpio_set_value(GPIO_HUB_POWER, 1); +} + +static void ehci_hub_power_off(struct power_controller *pc, struct device *dev) +{ + gpio_set_value(GPIO_HUB_NRESET, 0); + gpio_set_value(GPIO_HUB_POWER, 0); +} + +static struct usb_port_power_switch_data root_hub_port_data = { + .hub_tier = 0, + .port_number = 1, + .type = USB_PORT_CONNECT_TYPE_HARD_WIRED, +}; + +static struct usb_port_power_switch_data smsc_hub_port_data = { + .hub_tier = 1, + .port_number = 1, + .type = USB_PORT_CONNECT_TYPE_HARD_WIRED, +}; + +static struct power_controller pc = { + .name = "omap_hub_eth_pc", + .count = ATOMIC_INIT(0), + .power_on = ehci_hub_power_on, + .power_off = ehci_hub_power_off, +}; + +static inline int omap_ehci_hub_port(struct device *dev) +{ + /* we expect dev->parent points to ehcd controller */ + if (dev->parent && !strcmp(dev_name(dev->parent), "ehci-omap.0")) + return 1; + return 0; +} + +static inline int dev_pc_match(struct device *dev) +{ + struct device *anc; + int ret = 0; + + if (likely(strcmp(dev_name(dev), "port1"))) + goto exit; + + if (dev->parent && (anc = dev->parent->parent)) { + if (omap_ehci_hub_port(anc)) { + ret = 1; + goto exit; + } + + /* is it port of lan95xx hub? */ + if ((anc = anc->parent) && omap_ehci_hub_port(anc)) { + ret = 2; + goto exit; + } + } +exit: + return ret; +} + +/* + * Notifications of device registration + */ +static int device_notify(struct notifier_block *nb, unsigned long action, void *data) +{ + struct device *dev = data; + int ret; + + switch (action) { + case DEV_NOTIFY_ADD_DEVICE: + ret = dev_pc_match(dev); + if (likely(!ret)) + goto exit; + if (ret == 1) + dev_pc_bind(&pc, dev, &root_hub_port_data, sizeof(root_hub_port_data)); + else + dev_pc_bind(&pc, dev, &smsc_hub_port_data, sizeof(smsc_hub_port_data)); + break; + + case DEV_NOTIFY_DEL_DEVICE: + break; + } +exit: + return 0; +} + +static struct notifier_block usb_port_nb = { + .notifier_call = device_notify, +}; + static void __init omap4_ehci_init(void) { int ret; @@ -178,12 +273,10 @@ static void __init omap4_ehci_init(void) gpio_export(GPIO_HUB_POWER, 0); gpio_export(GPIO_HUB_NRESET, 0); - gpio_set_value(GPIO_HUB_NRESET, 1); usbhs_init(&usbhs_bdata); - /* enable power to hub */ - gpio_set_value(GPIO_HUB_POWER, 1); + dev_register_notifier(&usb_port_nb); } static struct omap_musb_board_data musb_board_data = {