2014-05-27 20:08 GMT+02:00 Tony Lindgren <tony@xxxxxxxxxxx>: > The twl4030 PMIC needs to be configured properly for things like > warm reset and deeper idle states so the PMIC manages the regulators > properly based on the hardware triggers from the SoC. Earlier > we have configured twl4030 using platform data, but we want to > do it for device tree based booting also. > > In some cases configuring twl4030 is needed for things to work. > For example, when rebooting an OMAP3530 at 125 MHz, it hangs. > With this patch, TWL4030 will be reset when a warm reset occures, > and OMAP3530 does not hang on reboot. > > Let's add device tree support and configure things for warm reset > as the default when compatible = "ti,twl4030-power". More > complicated configurations can be added to the driver based on > other compatible flags. > > Note we now also make the pdata const like it should be. > This allows use it for match->data with the device tree > related functions. > > Based on earlier patch by Matthias Brugger <matthias.bgg@xxxxxxxxx> > and Lesly A M <leslyam@xxxxxx>. > > Cc: Matthias Brugger <matthias.bgg@xxxxxxxxx> > Cc: Robert Nelson <robertcnelson@xxxxxxxxx> > Cc: Peter De Schrijver <pdeschrijver@xxxxxxxxxx> > Cc: Samuel Ortiz <sameo@xxxxxxxxxxxxxxx> > Cc: Lee Jones <lee.jones@xxxxxxxxxx> > Signed-off-by: Tony Lindgren <tony@xxxxxxxxxxx> > --- > .../devicetree/bindings/mfd/twl4030-power.txt | 7 +- > drivers/mfd/twl4030-power.c | 109 ++++++++++++++++++--- > include/linux/i2c/twl.h | 3 + > 3 files changed, 105 insertions(+), 14 deletions(-) > > diff --git a/Documentation/devicetree/bindings/mfd/twl4030-power.txt b/Documentation/devicetree/bindings/mfd/twl4030-power.txt > index 8e15ec3..b906116 100644 > --- a/Documentation/devicetree/bindings/mfd/twl4030-power.txt > +++ b/Documentation/devicetree/bindings/mfd/twl4030-power.txt > @@ -5,7 +5,12 @@ to control the power resources, including power scripts. For now, the > binding only supports the complete shutdown of the system after poweroff. > > Required properties: > -- compatible : must be "ti,twl4030-power" > +- compatible : must be one of the following > + "ti,twl4030-power" > + "ti,twl4030-power-reset" > + > +The use of ti,twl4030-power-reset is recommended at least on > +3530 that needs a special configuration for warm reset to work. > > Optional properties: > - ti,use_poweroff: With this flag, the chip will initiates an ACTIVE-to-OFF or > diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c > index 0b037dc..cb5b0cb 100644 > --- a/drivers/mfd/twl4030-power.c > +++ b/drivers/mfd/twl4030-power.c > @@ -29,6 +29,7 @@ > #include <linux/i2c/twl.h> > #include <linux/platform_device.h> > #include <linux/of.h> > +#include <linux/of_device.h> > > #include <asm/mach-types.h> > > @@ -128,6 +129,40 @@ static u8 res_config_addrs[] = { > [RES_MAIN_REF] = 0x94, > }; > > +/* > + * Usable values for .remap_sleep and .remap_off > + * Based on table "5.3.3 Resource Operating modes" > + */ > +enum { > + TWL_REMAP_OFF = 0, > + TWL_REMAP_SLEEP = 8, > + TWL_REMAP_ACTIVE = 9, Do we really need remap active? As far as I can see it's not used anywhere. > +}; > + > +/* > + * Macros to configure the PM register states for various resources. > + * Note that we can make MSG_SINGULAR etc private to this driver once > + * omap3 has been made DT only. > + */ > +#define TWL_DFLT_DELAY 2 /* typically 2 32 KiHz cycles */ > +#define TWL_RESOURCE_SET(res, state) \ > + { MSG_SINGULAR(DEV_GRP_NULL, (res), (state)), TWL_DFLT_DELAY } > +#define TWL_RESOURCE_ON(res) TWL_RESOURCE_SET(res, RES_STATE_ACTIVE) > +#define TWL_RESOURCE_OFF(res) TWL_RESOURCE_SET(res, RES_STATE_OFF) > +#define TWL_RESOURCE_RESET(res) TWL_RESOURCE_SET(res, RES_STATE_WRST) > +/* > + * It seems that type1 and type2 is just the resource init order > + * number for the type1 and type2 group. > + */ > +#define TWL_RESOURCE_GROUP_RESET(group, type1, type2) \ > + { MSG_BROADCAST(DEV_GRP_NULL, (group), (type1), (type2), \ > + RES_STATE_WRST), TWL_DFLT_DELAY } > +#define TWL_REMAP_SLEEP(res, devgrp, typ, typ2) \ > + { .resource = (res), .devgroup = (devgrp), \ > + .type = (typ), .type2 = (typ2), \ > + .remap_off = TWL_REMAP_OFF, \ > + .remap_sleep = TWL_REMAP_SLEEP, } > + > static int twl4030_write_script_byte(u8 address, u8 byte) > { > int err; > @@ -502,7 +537,8 @@ int twl4030_remove_script(u8 flags) > return err; > } > > -static int twl4030_power_configure_scripts(struct twl4030_power_data *pdata) > +static int > +twl4030_power_configure_scripts(const struct twl4030_power_data *pdata) > { > int err; > int i; > @@ -518,7 +554,8 @@ static int twl4030_power_configure_scripts(struct twl4030_power_data *pdata) > return 0; > } > > -static int twl4030_power_configure_resources(struct twl4030_power_data *pdata) > +static int > +twl4030_power_configure_resources(const struct twl4030_power_data *pdata) > { > struct twl4030_resconfig *resconfig = pdata->resource_config; > int err; > @@ -550,7 +587,7 @@ void twl4030_power_off(void) > pr_err("TWL4030 Unable to power off\n"); > } > > -static bool twl4030_power_use_poweroff(struct twl4030_power_data *pdata, > +static bool twl4030_power_use_poweroff(const struct twl4030_power_data *pdata, > struct device_node *node) > { > if (pdata && pdata->use_poweroff) > @@ -562,10 +599,60 @@ static bool twl4030_power_use_poweroff(struct twl4030_power_data *pdata, > return false; > } > > +#ifdef CONFIG_OF > + > +/* Generic warm reset configuration for omap3 */ > + > +static struct twl4030_ins omap3_wrst_seq[] = { > + TWL_RESOURCE_OFF(RES_NRES_PWRON), > + TWL_RESOURCE_OFF(RES_RESET), > + TWL_RESOURCE_RESET(RES_MAIN_REF), > + TWL_RESOURCE_GROUP_RESET(RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2), > + TWL_RESOURCE_RESET(RES_VUSB_3V1), > + TWL_RESOURCE_GROUP_RESET(RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1), > + TWL_RESOURCE_GROUP_RESET(RES_GRP_RC, RES_TYPE_ALL, RES_TYPE2_R0), > + TWL_RESOURCE_ON(RES_RESET), > + TWL_RESOURCE_ON(RES_NRES_PWRON), > +}; > + > +static struct twl4030_script omap3_wrst_script = { > + .script = omap3_wrst_seq, > + .size = ARRAY_SIZE(omap3_wrst_seq), > + .flags = TWL4030_WRST_SCRIPT, > +}; > + > +static struct twl4030_script *omap3_reset_scripts[] = { > + &omap3_wrst_script, > +}; > + > +static struct twl4030_resconfig omap3_rconfig[] = { > + TWL_REMAP_SLEEP(RES_HFCLKOUT, DEV_GRP_P3, -1, -1), > + TWL_REMAP_SLEEP(RES_VDD1, DEV_GRP_P1, -1, -1), > + TWL_REMAP_SLEEP(RES_VDD2, DEV_GRP_P1, -1, -1), > + { 0, 0 }, > +}; > + > +static struct twl4030_power_data omap3_reset = { > + .scripts = omap3_reset_scripts, > + .num = ARRAY_SIZE(omap3_reset_scripts), > + .resource_config = omap3_rconfig, > +}; > + > +static struct of_device_id twl4030_power_of_match[] = { > + { > + .compatible = "ti,twl4030-power-reset", > + .data = &omap3_reset, > + }, > + { }, > +}; > +MODULE_DEVICE_TABLE(of, twl4030_power_of_match); > +#endif /* CONFIG_OF */ > + > static int twl4030_power_probe(struct platform_device *pdev) > { > - struct twl4030_power_data *pdata = dev_get_platdata(&pdev->dev); > + const struct twl4030_power_data *pdata = dev_get_platdata(&pdev->dev); > struct device_node *node = pdev->dev.of_node; > + const struct of_device_id *match; > int err = 0; > int err2 = 0; > u8 val; > @@ -586,8 +673,12 @@ static int twl4030_power_probe(struct platform_device *pdev) > return err; > } > > + match = of_match_device(of_match_ptr(twl4030_power_of_match), > + &pdev->dev); > + if (match && match->data) > + pdata = match->data; > + > if (pdata) { > - /* TODO: convert to device tree */ > err = twl4030_power_configure_scripts(pdata); > if (err) { > pr_err("TWL4030 failed to load scripts\n"); > @@ -637,14 +728,6 @@ static int twl4030_power_remove(struct platform_device *pdev) > return 0; > } > > -#ifdef CONFIG_OF > -static const struct of_device_id twl4030_power_of_match[] = { > - {.compatible = "ti,twl4030-power", }, > - { }, > -}; > -MODULE_DEVICE_TABLE(of, twl4030_power_of_match); > -#endif > - > static struct platform_driver twl4030_power_driver = { > .driver = { > .name = "twl4030_power", > diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h > index ade1c06..5fe0313 100644 > --- a/include/linux/i2c/twl.h > +++ b/include/linux/i2c/twl.h > @@ -486,7 +486,10 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) > #define RES_GRP_ALL 0x7 /* All resource groups */ > > #define RES_TYPE2_R0 0x0 > +#define RES_TYPE2_R1 0x1 > +#define RES_TYPE2_R2 0x2 > > +#define RES_TYPE_R0 0x0 > #define RES_TYPE_ALL 0x7 > > /* Resource states */ > -- > 1.8.1.1 > -- motzblog.wordpress.com -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html