Message ID | 20170305191713.49255-2-andriy.shevchenko@linux.intel.com |
---|---|
State | Superseded |
Delegated to: | Bin Meng |
Headers | show |
Hi Andy, On 5 March 2017 at 12:17, Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote: > This simple PMU driver enables access to MMC controllers during probe > so tangier_sdhci can probe and be useful. > > In the future it might be expanded to cover other Intel MID platforms, > that's why it's called intel_mid_pmu.c. > > Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> > Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Please consider my comments on the previous driver to apply to this one also. One more thing - you cannot call device_probe() from the bind function. That is breaking the rules. Instead, it should be found by the first user, perhaps using syscon or perhaps with a device_get_...() function, and that will automatically probe it. Regards,
On Sun, Mar 12, 2017 at 10:21 PM, Simon Glass <sjg@chromium.org> wrote: > Hi Andy, > > On 5 March 2017 at 12:17, Andy Shevchenko > <andriy.shevchenko@linux.intel.com> wrote: >> This simple PMU driver enables access to MMC controllers during probe >> so tangier_sdhci can probe and be useful. >> >> In the future it might be expanded to cover other Intel MID platforms, >> that's why it's called intel_mid_pmu.c. >> >> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> >> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> > > Please consider my comments on the previous driver to apply to this one also. > > One more thing - you cannot call device_probe() from the bind > function. That is breaking the rules. > > Instead, it should be found by the first user, perhaps using syscon or > perhaps with a device_get_...() function, and that will automatically > probe it. While SCU works fine with this model, PMU doesn't. MMC (sdhci) requires to power on controllers, it looks like device can't be probed at that time (too early). What do you suggest to do?
On Wed, Mar 15, 2017 at 8:01 PM, Andy Shevchenko <andy.shevchenko@gmail.com> wrote: > On Sun, Mar 12, 2017 at 10:21 PM, Simon Glass <sjg@chromium.org> wrote: >> Hi Andy, >> >> On 5 March 2017 at 12:17, Andy Shevchenko >> <andriy.shevchenko@linux.intel.com> wrote: >>> This simple PMU driver enables access to MMC controllers during probe >>> so tangier_sdhci can probe and be useful. >>> >>> In the future it might be expanded to cover other Intel MID platforms, >>> that's why it's called intel_mid_pmu.c. >>> >>> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> >>> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> >> >> Please consider my comments on the previous driver to apply to this one also. >> >> One more thing - you cannot call device_probe() from the bind >> function. That is breaking the rules. >> >> Instead, it should be found by the first user, perhaps using syscon or >> perhaps with a device_get_...() function, and that will automatically >> probe it. > > While SCU works fine with this model, PMU doesn't. > MMC (sdhci) requires to power on controllers, it looks like device > can't be probed at that time (too early). What do you suggest to do? Whoof, found three mistakes - two typos in my code and an issue in sdhci generic driver. Works now.
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6a747c332e..04310653bb 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -83,7 +83,9 @@ endchoice # subarchitectures-specific options below config INTEL_MID bool "Intel MID platform support" + select MISC select INTEL_SCU + select INTEL_MID_PMU help Select to build a U-Boot capable of supporting Intel MID (Mobile Internet Device) platform systems which do not have diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 8d81f9c51c..0222a8beed 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -168,6 +168,12 @@ config I2C_EEPROM help Enable a generic driver for EEPROMs attached via I2C. +config INTEL_MID_PMU + bool "Support for PMU on Intel MID platforms" + depends on MISC + depends on INTEL_MID + default y + config INTEL_SCU bool "Enable support for SCU on Intel MID platforms" depends on INTEL_MID diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 47551e44d6..98a58f241c 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -51,4 +51,5 @@ obj-$(CONFIG_PCA9551_LED) += pca9551_led.o obj-$(CONFIG_FSL_DEVICE_DISABLE) += fsl_devdis.o obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o obj-$(CONFIG_QFW) += qfw.o +obj-$(CONFIG_INTEL_MID_PMU) += intel_mid_pmu.o obj-$(CONFIG_INTEL_SCU) += intel_scu_ipc.o diff --git a/drivers/misc/intel_mid_pmu.c b/drivers/misc/intel_mid_pmu.c new file mode 100644 index 0000000000..0eda3b4349 --- /dev/null +++ b/drivers/misc/intel_mid_pmu.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/device.h> +#include <linux/io.h> +#include <linux/sizes.h> +#include <malloc.h> + +/* Registers */ +#define PM_STS 0x00 +#define PM_CMD 0x04 +#define PM_ICS 0x08 +#define PM_WKC(x) (0x10 + (x) * 4) +#define PM_WKS(x) (0x18 + (x) * 4) +#define PM_SSC(x) (0x20 + (x) * 4) +#define PM_SSS(x) (0x30 + (x) * 4) + +/* Bits in PM_STS */ +#define PM_STS_BUSY (1 << 8) + +/* List of Intel Tangier LSSs */ +#define PMU_LSS_TANGIER_SDIO0_01 1 + +struct pmu_mid { + void __iomem *ioaddr; +}; + +static unsigned int pmu_readl(void __iomem *base, unsigned int offset) +{ + return readl(base + offset); +} + +static void pmu_writel(void __iomem *base, unsigned int offset, + unsigned int value) +{ + writel(value, base + offset); +} + +static int pmu_read_status(struct pmu_mid *pmu) +{ + int retry = 500000; + u32 reg; + + do { + reg = pmu_readl(pmu->ioaddr, PM_STS); + if (!(reg & PM_STS_BUSY)) + return 0; + + udelay(1); + } while (--retry); + + printf("WARNING: PMU still busy\n"); + return -EBUSY; +} + +static int pmu_enable_mmc(struct pmu_mid *pmu) +{ + u32 pm_ssc0; + int ret; + + /* Check PMU status */ + ret = pmu_read_status(pmu); + if (ret) + return ret; + + /* Read PMU values */ + pm_ssc0 = pmu_readl(pmu->ioaddr, PM_SSS(0)); + + /* Modify PMU values */ + + /* Enable SDIO0, sdhci for SD card */ + pm_ssc0 &= ~(0x3 << (PMU_LSS_TANGIER_SDIO0_01 * 2)); + + /* Write modified PMU values */ + pmu_writel(pmu->ioaddr, PM_SSC(0), pm_ssc0); + + /* Update modified PMU values */ + pmu_writel(pmu->ioaddr, PM_CMD, 0x00002201); + + /* Check PMU status */ + return pmu_read_status(pmu); +} + +static int pmu_mid_bind(struct udevice *dev) +{ + /* This device is needed straight away */ + return device_probe(dev); +} + +static int pmu_mid_probe(struct udevice *dev) +{ + struct pmu_mid *pmu = dev_get_uclass_priv(dev); + fdt_addr_t base; + + base = dev_get_addr(dev); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + pmu->ioaddr = devm_ioremap(dev, base, SZ_1K); + if (!pmu->ioaddr) + return -ENOMEM; + + return pmu_enable_mmc(pmu); +} + +static const struct udevice_id pmu_mid_match[] = { + { .compatible = "intel,pmu-mid" }, + { .compatible = "intel,pmu-tangier" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(intel_mid_pmu) = { + .name = "intel_mid_pmu", + .id = UCLASS_MISC, + .of_match = pmu_mid_match, + .bind = pmu_mid_bind, + .probe = pmu_mid_probe, + .priv_auto_alloc_size = sizeof(struct pmu_mid), +};