From: wlf Date: Wed, 5 Mar 2014 01:40:45 +0000 (+0800) Subject: USB: add otg irq detect function and chip id detect function X-Git-Tag: firefly_0821_release~6210 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=88ac83bca1c34fbdbc183eb2acc61ddffe7fdf62;p=firefly-linux-kernel-4.4.55.git USB: add otg irq detect function and chip id detect function --- diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi index 06dca7ce4dfc..b1cb283fc93a 100755 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -584,7 +584,7 @@ }; dwc_control_usb: dwc-control-usb@0x200080ac { - compatible = "rockchip,dwc-control-usb"; + compatible = "rockchip,rk3188-dwc-control-usb"; reg = <0x200080ac 0x4>, <0x2000810c 0x10>, <0x2000811c 0x10>, @@ -595,6 +595,8 @@ "GRF_UOC1_BASE", "GRF_UOC2_BASE", "GRF_UOC3_BASE"; + interrupts = ; + interrupt-names = "bvalid"; gpios = <&gpio0 GPIO_C0 GPIO_ACTIVE_LOW>, <&gpio3 GPIO_D5 GPIO_ACTIVE_LOW>; clocks = <&clk_gates4 5>; clock-names = "hclk_usb_peri"; diff --git a/drivers/usb/dwc_otg_310/usbdev_rk.h b/drivers/usb/dwc_otg_310/usbdev_rk.h index cdc49c339b7c..207654a83a21 100755 --- a/drivers/usb/dwc_otg_310/usbdev_rk.h +++ b/drivers/usb/dwc_otg_310/usbdev_rk.h @@ -27,6 +27,7 @@ struct dwc_otg_platform_data { void (*power_enable)(int enable); void (*dwc_otg_uart_mode)(void* pdata, int enter_usb_uart_mode); int (*get_status)(int id); + int (*get_chip_id)(void); }; struct rkehci_platform_data{ @@ -38,6 +39,7 @@ struct rkehci_platform_data{ void (*clock_init)(void* pdata); void (*clock_enable)(void *pdata, int enable); void (*soft_reset)(void); + int (*get_chip_id)(void); int clk_status; }; @@ -50,6 +52,14 @@ struct dwc_otg_control_usb { struct gpio *host_gpios; struct gpio *otg_gpios; struct clk* hclk_usb_peri; + struct delayed_work usb_det_wakeup_work; + struct wake_lock usb_wakelock; + int chip_id; +}; + +enum { + RK3188_USB_CTLR = 0, /* rk3188 chip usb */ + RK3288_USB_CTLR, /* rk3288 chip usb */ }; #endif diff --git a/drivers/usb/dwc_otg_310/usbdev_rk30.c b/drivers/usb/dwc_otg_310/usbdev_rk30.c index 447a723eb9c9..183ff9225096 100755 --- a/drivers/usb/dwc_otg_310/usbdev_rk30.c +++ b/drivers/usb/dwc_otg_310/usbdev_rk30.c @@ -9,12 +9,22 @@ #include #include #include +#include #include +#include +#include +#include +#include #include "usbdev_rk.h" #include "dwc_otg_regs.h" static struct dwc_otg_control_usb *control_usb; +int usb_get_chip_id(void) +{ + return control_usb->chip_id; +} + int dwc_otg_check_dpdm(void) { int bus_status = 0; @@ -155,15 +165,16 @@ struct dwc_otg_platform_data usb20otg_pdata = { .ahbclk = NULL, .busclk = NULL, .phy_status = 0, - .hw_init=usb20otg_hw_init, - .phy_suspend=usb20otg_phy_suspend, - .soft_reset=usb20otg_soft_reset, - .clock_init=usb20otg_clock_init, - .clock_enable=usb20otg_clock_enable, - .get_status=usb20otg_get_status, - .power_enable=usb20otg_power_enable, + .hw_init = usb20otg_hw_init, + .phy_suspend = usb20otg_phy_suspend, + .soft_reset = usb20otg_soft_reset, + .clock_init = usb20otg_clock_init, + .clock_enable = usb20otg_clock_enable, + .get_status = usb20otg_get_status, + .get_chip_id = usb_get_chip_id, + .power_enable = usb20otg_power_enable, #ifdef CONFIG_RK_USB_UART - .dwc_otg_uart_mode=dwc_otg_uart_mode, + .dwc_otg_uart_mode = dwc_otg_uart_mode, #endif }; @@ -273,13 +284,14 @@ struct dwc_otg_platform_data usb20host_pdata = { .ahbclk = NULL, .busclk = NULL, .phy_status = 0, - .hw_init=usb20host_hw_init, - .phy_suspend=usb20host_phy_suspend, - .soft_reset=usb20host_soft_reset, - .clock_init=usb20host_clock_init, - .clock_enable=usb20host_clock_enable, - .get_status=usb20host_get_status, - .power_enable=usb20host_power_enable, + .hw_init = usb20host_hw_init, + .phy_suspend = usb20host_phy_suspend, + .soft_reset = usb20host_soft_reset, + .clock_init = usb20host_clock_init, + .clock_enable = usb20host_clock_enable, + .get_status = usb20host_get_status, + .get_chip_id = usb_get_chip_id, + .power_enable = usb20host_power_enable, }; #endif @@ -381,39 +393,123 @@ struct rkehci_platform_data rkhsic_pdata = { .clock_init = rk_hsic_clock_init, .clock_enable = rk_hsic_clock_enable, .soft_reset = rk_hsic_soft_reset, + .get_chip_id = usb_get_chip_id, }; #endif -static int dwc_otg_control_usb_probe(struct platform_device *pdev) +#ifdef CONFIG_RK_USB_DETECT_BY_OTG_BVALID +#define WAKE_LOCK_TIMEOUT (HZ * 10) + +inline static void do_wakeup(struct work_struct *work) +{ +// rk28_send_wakeup_key(); +} +#endif + +/********** handler for bvalid irq **********/ +static irqreturn_t bvalid_irq_handler(int irq, void *dev_id) +{ + unsigned int * phy_con0; + + /* clear irq */ + if( usb_get_chip_id() == RK3188_USB_CTLR){ + phy_con0 = (control_usb->grf_uoc0_base + 0xc); + *phy_con0 = (1 << 31) | (1 << 15); + } + +#ifdef CONFIG_RK_USB_UART + /* usb otg dp/dm switch to usb phy */ + dwc_otg_uart_mode(NULL, PHY_USB_MODE); +#endif + +#ifdef CONFIG_RK_USB_DETECT_BY_OTG_BVALID + wake_lock_timeout(&control_usb->usb_wakelock, WAKE_LOCK_TIMEOUT); + schedule_delayed_work(&control_usb->usb_det_wakeup_work, HZ/10); +#endif + + return IRQ_HANDLED; +} + +/********** handler for otg id rise and fall edge **********/ +static irqreturn_t id_irq_handler(int irq, void *dev_id) +{ + /* clear irq */ + if( usb_get_chip_id() == RK3288_USB_CTLR){ + + } + +#ifdef CONFIG_RK_USB_DETECT_BY_OTG_BVALID + wake_lock_timeout(&control_usb->usb_wakelock, WAKE_LOCK_TIMEOUT); + schedule_delayed_work(&control_usb->usb_det_wakeup_work, HZ/10); +#endif + + return IRQ_HANDLED; +} + +/************* register bvalid and otg_id irq **************/ +static int otg_irq_detect_init(struct platform_device *pdev) { - struct resource *res; - int gpio, err; - struct device_node *np = pdev->dev.of_node; - struct clk* hclk_usb_peri; int ret = 0; + int irq = 0; + unsigned int * phy_con0; - control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),GFP_KERNEL); - if (!control_usb) { - dev_err(&pdev->dev, "unable to alloc memory for control usb\n"); - ret = -ENOMEM; - goto err1; +#ifdef CONFIG_RK_USB_DETECT_BY_OTG_BVALID + wake_lock_init(&control_usb->usb_wakelock, WAKE_LOCK_SUSPEND, "usb_detect"); + INIT_DELAYED_WORK(&control_usb->usb_det_wakeup_work, do_wakeup); +#endif + + irq = platform_get_irq_byname(pdev, "bvalid"); + if (irq > 0) { + ret = request_irq(irq, bvalid_irq_handler, 0, "bvalid", NULL); + if(ret < 0){ + dev_err(&pdev->dev, "request_irq %d failed!\n", irq); + return ret; + } + + /* clear & enable bvalid irq */ + if( usb_get_chip_id() == RK3188_USB_CTLR){ + phy_con0 = (control_usb->grf_uoc0_base + 0xc); + *phy_con0 = (3 << 30) | (3 << 14); + } + +#ifdef CONFIG_RK_USB_DETECT_BY_OTG_BVALID + enable_irq_wake(irq); +#endif } - hclk_usb_peri = devm_clk_get(&pdev->dev, "hclk_usb_peri"); - if (IS_ERR(hclk_usb_peri)) { - dev_err(&pdev->dev, "Failed to get hclk_usb_peri\n"); - ret = -EINVAL; - goto err1; + irq = platform_get_irq_byname(pdev, "otg_id"); + if (irq > 0) { + ret = request_irq(irq, id_irq_handler, 0, "otg_id", NULL); + if(ret < 0){ + dev_err(&pdev->dev, "request_irq %d failed!\n", irq); + return ret; + } + + /* clear & enable otg_id change irq */ + /* for rk3026 & rk3288 enable and clear id_fall_irq & id_rise_irq*/ + if( usb_get_chip_id() == RK3288_USB_CTLR){ + + } + +#ifdef CONFIG_RK_USB_DETECT_BY_OTG_BVALID + enable_irq_wake(irq); +#endif } - control_usb->hclk_usb_peri = hclk_usb_peri; - clk_prepare_enable(hclk_usb_peri); + + return ret; +} + +static int usb_grf_ioremap(struct platform_device *pdev) +{ + int ret = 0; + struct resource *res; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "GRF_SOC_STATUS0"); control_usb->grf_soc_status0 = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(control_usb->grf_soc_status0)){ ret = PTR_ERR(control_usb->grf_soc_status0); - goto err2; + return ret; } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, @@ -421,7 +517,7 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev) control_usb->grf_uoc0_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(control_usb->grf_uoc0_base)){ ret = PTR_ERR(control_usb->grf_uoc0_base); - goto err2; + return ret; } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, @@ -429,7 +525,7 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev) control_usb->grf_uoc1_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(control_usb->grf_uoc1_base)){ ret = PTR_ERR(control_usb->grf_uoc1_base); - goto err2; + return ret; } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, @@ -437,7 +533,7 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev) control_usb->grf_uoc2_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(control_usb->grf_uoc2_base)){ ret = PTR_ERR(control_usb->grf_uoc2_base); - goto err2; + return ret; } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, @@ -445,6 +541,76 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev) control_usb->grf_uoc3_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(control_usb->grf_uoc3_base)){ ret = PTR_ERR(control_usb->grf_uoc3_base); + return ret; + } + + return ret; +} + +#ifdef CONFIG_OF +static struct platform_device_id rk_usb_devtype[] = { + { + .name = "rk3188-usb", + .driver_data = RK3188_USB_CTLR, + }, + { + .name = "rk3288-usb", + .driver_data = RK3288_USB_CTLR, + }, + { }, +}; +MODULE_DEVICE_TABLE(platform, rk_usb_devtype); + +static const struct of_device_id dwc_otg_control_usb_id_table[] = { + { .compatible = "rockchip,rk3188-dwc-control-usb", + .data = &rk_usb_devtype[RK3188_USB_CTLR], + }, + { + .compatible = "rockchip,rk3288-dwc-control-usb", + .data = &rk_usb_devtype[RK3288_USB_CTLR], + }, + { }, +}; +MODULE_DEVICE_TABLE(of, dwc_otg_control_usb_id_table); +#endif + +static int dwc_otg_control_usb_probe(struct platform_device *pdev) +{ + int gpio, err; + struct device_node *np = pdev->dev.of_node; + struct clk* hclk_usb_peri; + int ret = 0; + const struct of_device_id *match = + of_match_device(of_match_ptr(dwc_otg_control_usb_id_table), &pdev->dev); + + if (match) + pdev->id_entry = match->data; + else{ + ret = -EINVAL; + goto err1; + } + + control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),GFP_KERNEL); + if (!control_usb) { + dev_err(&pdev->dev, "unable to alloc memory for control usb\n"); + ret = -ENOMEM; + goto err1; + } + + control_usb->chip_id = pdev->id_entry->driver_data; + + hclk_usb_peri = devm_clk_get(&pdev->dev, "hclk_usb_peri"); + if (IS_ERR(hclk_usb_peri)) { + dev_err(&pdev->dev, "Failed to get hclk_usb_peri\n"); + ret = -EINVAL; + goto err1; + } + control_usb->hclk_usb_peri = hclk_usb_peri; + clk_prepare_enable(hclk_usb_peri); + + ret = usb_grf_ioremap(pdev); + if(ret){ + dev_err(&pdev->dev, "Failed to ioremap usb grf\n"); goto err2; } @@ -483,7 +649,11 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev) ret = err; goto err2; } - +#if 0 //disable for debug + ret = otg_irq_detect_init(pdev); + if (ret < 0) + goto err2; +#endif return 0; err2: @@ -498,14 +668,6 @@ static int dwc_otg_control_usb_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_OF -static const struct of_device_id dwc_otg_control_usb_id_table[] = { - { .compatible = "rockchip,dwc-control-usb" }, - {} -}; -MODULE_DEVICE_TABLE(of, dwc_otg_control_usb_id_table); -#endif - static struct platform_driver dwc_otg_control_usb_driver = { .probe = dwc_otg_control_usb_probe, .remove = dwc_otg_control_usb_remove, @@ -514,6 +676,7 @@ static struct platform_driver dwc_otg_control_usb_driver = { .owner = THIS_MODULE, .of_match_table = of_match_ptr(dwc_otg_control_usb_id_table), }, + .id_table = rk_usb_devtype, }; static int __init dwc_otg_control_usb_init(void)