DaVinci SoC support improvements mainly towards an effort to

get to working USB support.
 
 - use CFGCHIP syscon device to access common registers
 
 - define platform data and device tree nodes for newly
   introduced USB phy driver
 
 - clock lookup and auxdata lookup for USB phy and also
   for LCDC (LCD controller)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJYHCFWAAoJEGFBu2jqvgRNsiMP/AtyFsKue1Y+hNm5EXUwnHVF
 kmJn1AfXzYa2xn9fPQIIrraqQxNobbl5BiEuLgFk33s6C0wrAz3/5FjnsguoJ+UD
 7BNzMpXHac4nLORRMTdKlACGv7rsrRelSrKZr6dAd0puEnKqRlSORBJTcGRCLJPh
 pqTJM5X53NsGlhJOXnk33CDxuK4Ym/nVtbvKBzi2nGBbWiIWIvn/jzwZqkNCYzdc
 iDQzIDMfeP9G8l8JkL7A947Yolf2h7hYqPDKRFhJSSvvdGUNEkbHyu4iSG7qE+B4
 z/aLvvH6sB3CPeKqum1PMAk8hEV+Mp3lsTtrdFLgxz4NsY1jcIriSIDBY+x5Fkfh
 jKOsmkniwysVHsWvta4pLJMwnamfg/SG05wCCTb/PDO4S3NFnB4L9rdslzo7A0ad
 M6ewqKUFOCMsSyxyGBEiSA1UuWblkzeKOh8dcx1Q/haYPMfJUzzeRMeaXNLpUR+l
 fAqoKQBTAA5szydu83qKJLUDugkYZxaoeIw7wIo2JhqCaubyoGUZ6rpyaDiA+M0K
 kC6KIDmSunensISvTRxHPrjkPcalLY6x6VJNDnMTMrf4CfwYCqLlA2LlqG770xjK
 Th46PAjHr6SyPbjHwLxm3EZC385eKtTTlc7wdSHF/iR9Bt/EMnIynJgqKGc0YXDC
 yNMITMhPxl09K5eR1JO4
 =tA0U
 -----END PGP SIGNATURE-----

Merge tag 'davinci-for-v4.10/soc' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci into next/soc

DaVinci SoC support improvements mainly towards an effort to
get to working USB support.

- use CFGCHIP syscon device to access common registers

- define platform data and device tree nodes for newly
  introduced USB phy driver

- clock lookup and auxdata lookup for USB phy and also
  for LCDC (LCD controller)

* tag 'davinci-for-v4.10/soc' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci:
  ARM: davinci: da8xx: register USB PHY clocks in the DT file
  ARM: davinci: da8xx: add usb phy clocks
  ARM: davinci: da8xx-dt: add OF_DEV_AUXDATA entry for USB phy
  ARM: davinci: da8xx: Add USB device names to clock lookup tables
  ARM: davinci: da8xx: Add USB PHY platform device
  ARM: davinci: da8xx-dt: add OF_DEV_AUXDATA entry for lcdc
  ARM: davinci: da8xx: Add full regulator constraints for non-DT boot
  ARM: davinci: da8xx: Add CFGCHIP syscon platform device

Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Olof Johansson 2016-11-08 12:22:33 -08:00
commit 1474f44ec8
10 changed files with 367 additions and 58 deletions

View File

@ -18,7 +18,6 @@
#include <linux/i2c.h>
#include <linux/i2c/pcf857x.h>
#include <linux/platform_data/at24.h>
#include <linux/mfd/da8xx-cfgchip.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/spi/spi.h>
@ -28,6 +27,7 @@
#include <linux/platform_data/mtd-davinci-aemif.h>
#include <linux/platform_data/spi-davinci.h>
#include <linux/platform_data/usb-davinci.h>
#include <linux/regulator/machine.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@ -107,43 +107,24 @@ static irqreturn_t da830_evm_usb_ocic_irq(int irq, void *dev_id)
static __init void da830_evm_usb_init(void)
{
u32 cfgchip2;
int ret;
/*
* Set up USB clock/mode in the CFGCHIP2 register.
* FYI: CFGCHIP2 is 0x0000ef00 initially.
*/
cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
/* USB2.0 PHY reference clock is 24 MHz */
cfgchip2 &= ~CFGCHIP2_REFFREQ_MASK;
cfgchip2 |= CFGCHIP2_REFFREQ_24MHZ;
/*
* Select internal reference clock for USB 2.0 PHY
* and use it as a clock source for USB 1.1 PHY
* (this is the default setting anyway).
*/
cfgchip2 &= ~CFGCHIP2_USB1PHYCLKMUX;
cfgchip2 |= CFGCHIP2_USB2PHYCLKMUX;
/*
* We have to override VBUS/ID signals when MUSB is configured into the
* host-only mode -- ID pin will float if no cable is connected, so the
* controller won't be able to drive VBUS thinking that it's a B-device.
* Otherwise, we want to use the OTG mode and enable VBUS comparators.
*/
cfgchip2 &= ~CFGCHIP2_OTGMODE_MASK;
#ifdef CONFIG_USB_MUSB_HOST
cfgchip2 |= CFGCHIP2_FORCE_HOST;
#else
cfgchip2 |= CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN;
#endif
__raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
/* USB_REFCLKIN is not used. */
ret = da8xx_register_usb20_phy_clk(false);
if (ret)
pr_warn("%s: USB 2.0 PHY CLK registration failed: %d\n",
__func__, ret);
ret = da8xx_register_usb11_phy_clk(false);
if (ret)
pr_warn("%s: USB 1.1 PHY CLK registration failed: %d\n",
__func__, ret);
ret = da8xx_register_usb_phy();
if (ret)
pr_warn("%s: USB PHY registration failed: %d\n",
__func__, ret);
ret = davinci_cfg_reg(DA830_USB0_DRVVBUS);
if (ret)
pr_warn("%s: USB 2.0 PinMux setup failed: %d\n", __func__, ret);
@ -589,6 +570,10 @@ static __init void da830_evm_init(void)
struct davinci_soc_info *soc_info = &davinci_soc_info;
int ret;
ret = da8xx_register_cfgchip();
if (ret)
pr_warn("%s: CFGCHIP registration failed: %d\n", __func__, ret);
ret = da830_register_gpio();
if (ret)
pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
@ -648,6 +633,8 @@ static __init void da830_evm_init(void)
ret = da8xx_register_spi_bus(0, ARRAY_SIZE(da830evm_spi_info));
if (ret)
pr_warn("%s: spi 0 registration failed: %d\n", __func__, ret);
regulator_has_full_constraints();
}
#ifdef CONFIG_SERIAL_8250_CONSOLE

View File

@ -1345,6 +1345,10 @@ static __init void da850_evm_init(void)
{
int ret;
ret = da8xx_register_cfgchip();
if (ret)
pr_warn("%s: CFGCHIP registration failed: %d\n", __func__, ret);
ret = da850_register_gpio();
if (ret)
pr_warn("%s: GPIO init failed: %d\n", __func__, ret);

View File

@ -514,6 +514,10 @@ static void __init mityomapl138_init(void)
{
int ret;
ret = da8xx_register_cfgchip();
if (ret)
pr_warn("%s: CFGCHIP registration failed: %d\n", __func__, ret);
/* for now, no special EDMA channels are reserved */
ret = da850_register_edma(NULL);
if (ret)

View File

@ -13,8 +13,8 @@
#include <linux/init.h>
#include <linux/console.h>
#include <linux/gpio.h>
#include <linux/mfd/da8xx-cfgchip.h>
#include <linux/platform_data/gpio-davinci.h>
#include <linux/regulator/machine.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@ -244,7 +244,6 @@ static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id)
static __init void omapl138_hawk_usb_init(void)
{
int ret;
u32 cfgchip2;
ret = davinci_cfg_reg_list(da850_hawk_usb11_pins);
if (ret) {
@ -252,12 +251,20 @@ static __init void omapl138_hawk_usb_init(void)
return;
}
/* Setup the Ref. clock frequency for the HAWK at 24 MHz. */
ret = da8xx_register_usb20_phy_clk(false);
if (ret)
pr_warn("%s: USB 2.0 PHY CLK registration failed: %d\n",
__func__, ret);
cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
cfgchip2 &= ~CFGCHIP2_REFFREQ_MASK;
cfgchip2 |= CFGCHIP2_REFFREQ_24MHZ;
__raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
ret = da8xx_register_usb11_phy_clk(false);
if (ret)
pr_warn("%s: USB 1.1 PHY CLK registration failed: %d\n",
__func__, ret);
ret = da8xx_register_usb_phy();
if (ret)
pr_warn("%s: USB PHY registration failed: %d\n",
__func__, ret);
ret = gpio_request_one(DA850_USB1_VBUS_PIN,
GPIOF_DIR_OUT, "USB1 VBUS");
@ -293,6 +300,10 @@ static __init void omapl138_hawk_init(void)
{
int ret;
ret = da8xx_register_cfgchip();
if (ret)
pr_warn("%s: CFGCHIP registration failed: %d\n", __func__, ret);
ret = da850_register_gpio();
if (ret)
pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
@ -318,6 +329,8 @@ static __init void omapl138_hawk_init(void)
if (ret)
pr_warn("%s: dsp/rproc registration failed: %d\n",
__func__, ret);
regulator_has_full_constraints();
}
#ifdef CONFIG_SERIAL_8250_CONSOLE

View File

@ -412,7 +412,7 @@ static struct clk_lookup da830_clks[] = {
CLK("davinci-mcasp.0", NULL, &mcasp0_clk),
CLK("davinci-mcasp.1", NULL, &mcasp1_clk),
CLK("davinci-mcasp.2", NULL, &mcasp2_clk),
CLK(NULL, "usb20", &usb20_clk),
CLK("musb-da8xx", "usb20", &usb20_clk),
CLK(NULL, "aemif", &aemif_clk),
CLK(NULL, "aintc", &aintc_clk),
CLK(NULL, "secu_mgr", &secu_mgr_clk),
@ -420,7 +420,7 @@ static struct clk_lookup da830_clks[] = {
CLK("davinci_mdio.0", "fck", &emac_clk),
CLK(NULL, "gpio", &gpio_clk),
CLK("i2c_davinci.2", NULL, &i2c1_clk),
CLK(NULL, "usb11", &usb11_clk),
CLK("ohci", "usb11", &usb11_clk),
CLK(NULL, "emif3", &emif3_clk),
CLK(NULL, "arm", &arm_clk),
CLK(NULL, "rmii", &rmii_clk),

View File

@ -503,8 +503,8 @@ static struct clk_lookup da850_clks[] = {
CLK("da830-mmc.1", NULL, &mmcsd1_clk),
CLK("ti-aemif", NULL, &aemif_clk),
CLK(NULL, "aemif", &aemif_clk),
CLK(NULL, "usb11", &usb11_clk),
CLK(NULL, "usb20", &usb20_clk),
CLK("ohci", "usb11", &usb11_clk),
CLK("musb-da8xx", "usb20", &usb20_clk),
CLK("spi_davinci.0", NULL, &spi0_clk),
CLK("spi_davinci.1", NULL, &spi1_clk),
CLK("vpif", NULL, &vpif_clk),

View File

@ -38,6 +38,10 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
NULL),
OF_DEV_AUXDATA("ti,da830-mcasp-audio", 0x01d00000, "davinci-mcasp.0", NULL),
OF_DEV_AUXDATA("ti,da850-aemif", 0x68000000, "ti-aemif", NULL),
OF_DEV_AUXDATA("ti,da850-tilcdc", 0x01e13000, "da8xx_lcdc.0", NULL),
OF_DEV_AUXDATA("ti,da830-ohci", 0x01e25000, "ohci", NULL),
OF_DEV_AUXDATA("ti,da830-musb", 0x01e00000, "musb-da8xx", NULL),
OF_DEV_AUXDATA("ti,da830-usb-phy", 0x01c1417c, "da8xx-usb-phy", NULL),
{}
};
@ -45,6 +49,17 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
static void __init da850_init_machine(void)
{
int ret;
ret = da8xx_register_usb20_phy_clk(false);
if (ret)
pr_warn("%s: registering USB 2.0 PHY clock failed: %d",
__func__, ret);
ret = da8xx_register_usb11_phy_clk(false);
if (ret)
pr_warn("%s: registering USB 1.1 PHY clock failed: %d",
__func__, ret);
of_platform_default_populate(NULL, da850_auxdata_lookup, NULL);
}

View File

@ -11,6 +11,7 @@
* (at your option) any later version.
*/
#include <linux/init.h>
#include <linux/platform_data/syscon.h>
#include <linux/platform_device.h>
#include <linux/dma-contiguous.h>
#include <linux/serial_8250.h>
@ -1060,3 +1061,30 @@ int __init da850_register_sata(unsigned long refclkpn)
return platform_device_register(&da850_sata_device);
}
#endif
static struct syscon_platform_data da8xx_cfgchip_platform_data = {
.label = "cfgchip",
};
static struct resource da8xx_cfgchip_resources[] = {
{
.start = DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP0_REG,
.end = DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP4_REG + 3,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device da8xx_cfgchip_device = {
.name = "syscon",
.id = -1,
.dev = {
.platform_data = &da8xx_cfgchip_platform_data,
},
.num_resources = ARRAY_SIZE(da8xx_cfgchip_resources),
.resource = da8xx_cfgchip_resources,
};
int __init da8xx_register_cfgchip(void)
{
return platform_device_register(&da8xx_cfgchip_device);
}

View File

@ -61,6 +61,7 @@ extern unsigned int da850_max_speed;
#define DA8XX_CFGCHIP1_REG 0x180
#define DA8XX_CFGCHIP2_REG 0x184
#define DA8XX_CFGCHIP3_REG 0x188
#define DA8XX_CFGCHIP4_REG 0x18c
#define DA8XX_SYSCFG1_BASE (IO_PHYS + 0x22C000)
#define DA8XX_SYSCFG1_VIRT(x) (da8xx_syscfg1_base + (x))
@ -88,8 +89,12 @@ int da850_register_edma(struct edma_rsv_info *rsv[2]);
int da8xx_register_i2c(int instance, struct davinci_i2c_platform_data *pdata);
int da8xx_register_spi_bus(int instance, unsigned num_chipselect);
int da8xx_register_watchdog(void);
int da8xx_register_usb_phy(void);
int da8xx_register_usb20(unsigned mA, unsigned potpgt);
int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
int da8xx_register_usb_refclkin(int rate);
int da8xx_register_usb20_phy_clk(bool use_usb_refclkin);
int da8xx_register_usb11_phy_clk(bool use_usb_refclkin);
int da8xx_register_emac(void);
int da8xx_register_uio_pruss(void);
int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata);
@ -113,6 +118,7 @@ void da8xx_rproc_reserve_cma(void);
int da8xx_register_rproc(void);
int da850_register_gpio(void);
int da830_register_gpio(void);
int da8xx_register_cfgchip(void);
extern struct platform_device da8xx_serial_device[];
extern struct emac_platform_data da8xx_emac_pdata;

View File

@ -1,21 +1,44 @@
/*
* DA8xx USB
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/mfd/da8xx-cfgchip.h>
#include <linux/phy/phy.h>
#include <linux/platform_data/usb-davinci.h>
#include <linux/platform_device.h>
#include <linux/usb/musb.h>
#include <mach/clock.h>
#include <mach/common.h>
#include <mach/cputype.h>
#include <mach/da8xx.h>
#include <mach/irqs.h>
#include "clock.h"
#define DA8XX_USB0_BASE 0x01e00000
#define DA8XX_USB1_BASE 0x01e25000
#if IS_ENABLED(CONFIG_USB_MUSB_HDRC)
static struct platform_device da8xx_usb_phy = {
.name = "da8xx-usb-phy",
.id = -1,
.dev = {
/*
* Setting init_name so that clock lookup will work in
* da8xx_register_usb11_phy_clk() even if this device is not
* registered yet.
*/
.init_name = "da8xx-usb-phy",
},
};
int __init da8xx_register_usb_phy(void)
{
return platform_device_register(&da8xx_usb_phy);
}
static struct musb_hdrc_config musb_config = {
.multipoint = true,
@ -45,10 +68,15 @@ static struct resource da8xx_usb20_resources[] = {
static u64 usb_dmamask = DMA_BIT_MASK(32);
static struct platform_device usb_dev = {
static struct platform_device da8xx_usb20_dev = {
.name = "musb-da8xx",
.id = -1,
.dev = {
/*
* Setting init_name so that clock lookup will work in
* usb20_phy_clk_enable() even if this device is not registered.
*/
.init_name = "musb-da8xx",
.platform_data = &usb_data,
.dma_mask = &usb_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
@ -62,18 +90,9 @@ int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt)
usb_data.power = mA > 510 ? 255 : mA / 2;
usb_data.potpgt = (potpgt + 1) / 2;
return platform_device_register(&usb_dev);
return platform_device_register(&da8xx_usb20_dev);
}
#else
int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt)
{
return 0;
}
#endif /* CONFIG_USB_MUSB_HDRC */
static struct resource da8xx_usb11_resources[] = {
[0] = {
.start = DA8XX_USB1_BASE,
@ -105,3 +124,236 @@ int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata)
da8xx_usb11_device.dev.platform_data = pdata;
return platform_device_register(&da8xx_usb11_device);
}
static struct clk usb_refclkin = {
.name = "usb_refclkin",
.set_rate = davinci_simple_set_rate,
};
static struct clk_lookup usb_refclkin_lookup =
CLK(NULL, "usb_refclkin", &usb_refclkin);
/**
* da8xx_register_usb_refclkin - register USB_REFCLKIN clock
*
* @rate: The clock rate in Hz
*
* This clock is only needed if the board provides an external USB_REFCLKIN
* signal, in which case it will be used as the parent of usb20_phy_clk and/or
* usb11_phy_clk.
*/
int __init da8xx_register_usb_refclkin(int rate)
{
int ret;
usb_refclkin.rate = rate;
ret = clk_register(&usb_refclkin);
if (ret)
return ret;
clkdev_add(&usb_refclkin_lookup);
return 0;
}
static void usb20_phy_clk_enable(struct clk *clk)
{
struct clk *usb20_clk;
int err;
u32 val;
u32 timeout = 500000; /* 500 msec */
val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20");
if (IS_ERR(usb20_clk)) {
pr_err("could not get usb20 clk: %ld\n", PTR_ERR(usb20_clk));
return;
}
/* The USB 2.O PLL requires that the USB 2.O PSC is enabled as well. */
err = clk_prepare_enable(usb20_clk);
if (err) {
pr_err("failed to enable usb20 clk: %d\n", err);
clk_put(usb20_clk);
return;
}
/*
* Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
* host may use the PLL clock without USB 2.0 OTG being used.
*/
val &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
val |= CFGCHIP2_PHY_PLLON;
writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
while (--timeout) {
val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
if (val & CFGCHIP2_PHYCLKGD)
goto done;
udelay(1);
}
pr_err("Timeout waiting for USB 2.0 PHY clock good\n");
done:
clk_disable_unprepare(usb20_clk);
clk_put(usb20_clk);
}
static void usb20_phy_clk_disable(struct clk *clk)
{
u32 val;
val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
val |= CFGCHIP2_PHYPWRDN;
writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
}
static int usb20_phy_clk_set_parent(struct clk *clk, struct clk *parent)
{
u32 val;
val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
/* Set the mux depending on the parent clock. */
if (parent == &usb_refclkin) {
val &= ~CFGCHIP2_USB2PHYCLKMUX;
} else if (strcmp(parent->name, "pll0_aux_clk") == 0) {
val |= CFGCHIP2_USB2PHYCLKMUX;
} else {
pr_err("Bad parent on USB 2.0 PHY clock\n");
return -EINVAL;
}
/* reference frequency also comes from parent clock */
val &= ~CFGCHIP2_REFFREQ_MASK;
switch (clk_get_rate(parent)) {
case 12000000:
val |= CFGCHIP2_REFFREQ_12MHZ;
break;
case 13000000:
val |= CFGCHIP2_REFFREQ_13MHZ;
break;
case 19200000:
val |= CFGCHIP2_REFFREQ_19_2MHZ;
break;
case 20000000:
val |= CFGCHIP2_REFFREQ_20MHZ;
break;
case 24000000:
val |= CFGCHIP2_REFFREQ_24MHZ;
break;
case 26000000:
val |= CFGCHIP2_REFFREQ_26MHZ;
break;
case 38400000:
val |= CFGCHIP2_REFFREQ_38_4MHZ;
break;
case 40000000:
val |= CFGCHIP2_REFFREQ_40MHZ;
break;
case 48000000:
val |= CFGCHIP2_REFFREQ_48MHZ;
break;
default:
pr_err("Bad parent clock rate on USB 2.0 PHY clock\n");
return -EINVAL;
}
writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
return 0;
}
static struct clk usb20_phy_clk = {
.name = "usb20_phy",
.clk_enable = usb20_phy_clk_enable,
.clk_disable = usb20_phy_clk_disable,
.set_parent = usb20_phy_clk_set_parent,
};
static struct clk_lookup usb20_phy_clk_lookup =
CLK("da8xx-usb-phy", "usb20_phy", &usb20_phy_clk);
/**
* da8xx_register_usb20_phy_clk - register USB0PHYCLKMUX clock
*
* @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
* or "pll0_aux" if false.
*/
int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
{
struct clk *parent;
int ret = 0;
parent = clk_get(NULL, use_usb_refclkin ? "usb_refclkin" : "pll0_aux");
if (IS_ERR(parent))
return PTR_ERR(parent);
usb20_phy_clk.parent = parent;
ret = clk_register(&usb20_phy_clk);
if (!ret)
clkdev_add(&usb20_phy_clk_lookup);
clk_put(parent);
return ret;
}
static int usb11_phy_clk_set_parent(struct clk *clk, struct clk *parent)
{
u32 val;
val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
/* Set the USB 1.1 PHY clock mux based on the parent clock. */
if (parent == &usb20_phy_clk) {
val &= ~CFGCHIP2_USB1PHYCLKMUX;
} else if (parent == &usb_refclkin) {
val |= CFGCHIP2_USB1PHYCLKMUX;
} else {
pr_err("Bad parent on USB 1.1 PHY clock\n");
return -EINVAL;
}
writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
return 0;
}
static struct clk usb11_phy_clk = {
.name = "usb11_phy",
.set_parent = usb11_phy_clk_set_parent,
};
static struct clk_lookup usb11_phy_clk_lookup =
CLK("da8xx-usb-phy", "usb11_phy", &usb11_phy_clk);
/**
* da8xx_register_usb11_phy_clk - register USB1PHYCLKMUX clock
*
* @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
* or "usb20_phy" if false.
*/
int __init da8xx_register_usb11_phy_clk(bool use_usb_refclkin)
{
struct clk *parent;
int ret = 0;
if (use_usb_refclkin)
parent = clk_get(NULL, "usb_refclkin");
else
parent = clk_get(&da8xx_usb_phy.dev, "usb20_phy");
if (IS_ERR(parent))
return PTR_ERR(parent);
usb11_phy_clk.parent = parent;
ret = clk_register(&usb11_phy_clk);
if (!ret)
clkdev_add(&usb11_phy_clk_lookup);
clk_put(parent);
return ret;
}