1aec2927bSChris Brandt // SPDX-License-Identifier: GPL-2.0 2aec2927bSChris Brandt /* 3aec2927bSChris Brandt * Renesas USB driver RZ/A initialization and power control 4aec2927bSChris Brandt * 5aec2927bSChris Brandt * Copyright (C) 2018 Chris Brandt 6be0a42a7SYoshihiro Shimoda * Copyright (C) 2018-2019 Renesas Electronics Corporation 7aec2927bSChris Brandt */ 8aec2927bSChris Brandt 9aec2927bSChris Brandt #include <linux/delay.h> 10aec2927bSChris Brandt #include <linux/io.h> 11aec2927bSChris Brandt #include <linux/of_device.h> 12aec2927bSChris Brandt #include "common.h" 13aec2927bSChris Brandt #include "rza.h" 14aec2927bSChris Brandt 15aec2927bSChris Brandt static int usbhs_rza1_hardware_init(struct platform_device *pdev) 16aec2927bSChris Brandt { 17aec2927bSChris Brandt struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 18aec2927bSChris Brandt struct device_node *usb_x1_clk, *extal_clk; 19aec2927bSChris Brandt u32 freq_usb = 0, freq_extal = 0; 20aec2927bSChris Brandt 21aec2927bSChris Brandt /* Input Clock Selection (NOTE: ch0 controls both ch0 and ch1) */ 22aec2927bSChris Brandt usb_x1_clk = of_find_node_by_name(NULL, "usb_x1"); 23aec2927bSChris Brandt extal_clk = of_find_node_by_name(NULL, "extal"); 24aec2927bSChris Brandt of_property_read_u32(usb_x1_clk, "clock-frequency", &freq_usb); 25aec2927bSChris Brandt of_property_read_u32(extal_clk, "clock-frequency", &freq_extal); 26*9d6d5303SLiang He 27*9d6d5303SLiang He of_node_put(usb_x1_clk); 28*9d6d5303SLiang He of_node_put(extal_clk); 29*9d6d5303SLiang He 30aec2927bSChris Brandt if (freq_usb == 0) { 31aec2927bSChris Brandt if (freq_extal == 12000000) { 32aec2927bSChris Brandt /* Select 12MHz XTAL */ 33aec2927bSChris Brandt usbhs_bset(priv, SYSCFG, UCKSEL, UCKSEL); 34aec2927bSChris Brandt } else { 35aec2927bSChris Brandt dev_err(usbhs_priv_to_dev(priv), "A 48MHz USB clock or 12MHz main clock is required.\n"); 36aec2927bSChris Brandt return -EIO; 37aec2927bSChris Brandt } 38aec2927bSChris Brandt } 39aec2927bSChris Brandt 40aec2927bSChris Brandt /* Enable USB PLL (NOTE: ch0 controls both ch0 and ch1) */ 41aec2927bSChris Brandt usbhs_bset(priv, SYSCFG, UPLLE, UPLLE); 42bb09779fSYoshihiro Shimoda usleep_range(1000, 2000); 43aec2927bSChris Brandt usbhs_bset(priv, SUSPMODE, SUSPM, SUSPM); 44aec2927bSChris Brandt 45aec2927bSChris Brandt return 0; 46aec2927bSChris Brandt } 47aec2927bSChris Brandt 4876eff170SYoshihiro Shimoda const struct renesas_usbhs_platform_info usbhs_rza1_plat_info = { 4976eff170SYoshihiro Shimoda .platform_callback = { 50aec2927bSChris Brandt .hardware_init = usbhs_rza1_hardware_init, 51be0a42a7SYoshihiro Shimoda .get_id = usbhs_get_id_as_gadget, 5276eff170SYoshihiro Shimoda }, 5376eff170SYoshihiro Shimoda .driver_param = { 5476eff170SYoshihiro Shimoda .has_new_pipe_configs = 1, 5576eff170SYoshihiro Shimoda }, 56aec2927bSChris Brandt }; 57