Enable wifi on pandaboard
Subsystems (6)
cover Enable wifi on pandaboard
On the pandaboard the wifi isn't recognized because clk32kg was never enabled. The code to handle the clock got removed successively because it was not used. For now I've reverted the respective commits although I'm not sure if this is acceptable. If it needs to be converted to the clock API some pointers in the right direction would be appreciated, as I'm not familiar with it. Thanks!
Stefan Assmann (2):
dts: regulator-clk32kg should always be enabled
regulator: twl: Re-add clk32kg to get wifi working
.../bindings/regulator/twl-regulator.txt | 1 + arch/arm/boot/dts/twl6030.dtsi | 1 + drivers/regulator/twl-regulator.c | 23 ++++++++++++++++++++++ 3 files changed, 25 insertions(+)
Signature · 1 line
1.9.3
RFC PATCH 1/2 dts: regulator-clk32kg should always be enabled
This clock needs to be turned on for the wifi to work properly.
--- arch/arm/boot/dts/twl6030.dtsi | 1 + 1 file changed, 1 insertion(+)
arch/arm/boot/dts/twl6030.dtsi +1 -0
@@ -85,6 +85,7 @@ clk32kg: regulator-clk32kg { compatible = "ti,twl6030-clk32kg"; + regulator-always-on; }; twl_usb_comparator: usb-comparator {
Signature · 1 line
1.9.3
RFC PATCH 2/2 regulator: twl: Re-add clk32kg to get wifi working
In reply to Stefan AssmannThis partly reverts the following commits to get the wifi working on the Pandaboard OMAP4430 ES2.2.
0e8e5c34cf1a8beaaf0a6a05c053592693bf8cb4 regulator: twl: Remove references to 32kHz clock from DT bindings d1924519fe1dada0cfd9a228bf2ff1ea15840c84 regulator: twl: Remove TWL6030_FIXED_RESOURCE 029dd3cefa46ecdd879f9b4e2df3bdf4371cc22c regulator: twl: Remove another unused variable warning e76ab829cc2d8b6350a3f01fffb208df4d7d8c1b regulator: twl: Remove references to the twl4030 regulator
--- .../bindings/regulator/twl-regulator.txt | 1 + drivers/regulator/twl-regulator.c | 23 ++++++++++++++++++++++ 2 files changed, 24 insertions(+)
Documentation/devicetree/bindings/regulator/twl-regulator.txt +1 -0
@@ -15,6 +15,7 @@ For twl6030 regulators/LDOs - "ti,twl6030-vusb" for VUSB LDO - "ti,twl6030-v1v8" for V1V8 LDO - "ti,twl6030-v2v1" for V2V1 LDO + - "ti,twl6030-clk32kg" for CLK32KG RESOURCE - "ti,twl6030-vdd1" for VDD1 SMPS - "ti,twl6030-vdd2" for VDD2 SMPS - "ti,twl6030-vdd3" for VDD3 SMPS
drivers/regulator/twl-regulator.c +23 -0
@@ -633,6 +633,13 @@ static struct regulator_ops twl6030fixed_ops = { .get_status = twl6030reg_get_status, }; +static struct regulator_ops twl6030_fixed_resource = { + .enable = twl6030reg_enable, + .disable = twl6030reg_disable, + .is_enabled = twl6030reg_is_enabled, + .get_status = twl6030reg_get_status, +}; +/* * SMPS status and control */
@@ -948,6 +955,19 @@ static const struct twlreg_info TWLSMPS_INFO_##label = { \ }, \ } +#define TWL6030_FIXED_RESOURCE (label, offset, turnon_delay) \ +static struct twlreg_info TWLRES_INFO_##label = { \ + .base = offset, \ + .desc = { \ + .name = #label, \ + .id = TWL6030_REG_##label, \ + .ops = &twl6030_fixed_resource, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .enable_time = turnon_delay, \ + }, \ + } +/* * We list regulators here if systems need some level of * software control over them after boot.
@@ -1001,6 +1021,7 @@ TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0);TWL6030_FIXED_LDO (VUSB ,0x70 ,3300 ,0 );TWL6030_FIXED_LDO (V1V8 ,0x16 ,1800 ,0 );TWL6030_FIXED_LDO (V2V1 ,0x1c ,2100 ,0 ); +TWL6030_FIXED_RESOURCE (CLK32KG ,0x8C ,0 );TWL6032_ADJUSTABLE_SMPS (SMPS3 ,0x34 );TWL6032_ADJUSTABLE_SMPS (SMPS4 ,0x10 );TWL6032_ADJUSTABLE_SMPS (VIO ,0x16 );
@@ -1033,6 +1054,7 @@ static u8 twl_get_smps_mult(void)#define TWL6030_OF_MATCH (comp, label) TWL_OF_MATCH(comp, TWL6030, label)#define TWL6032_OF_MATCH (comp, label) TWL_OF_MATCH(comp, TWL6032, label)#define TWLFIXED_OF_MATCH (comp, label) TWL_OF_MATCH(comp, TWLFIXED, label) +#define TWLRES_OF_MATCH (comp, label) TWL_OF_MATCH(comp, TWLRES, label)#define TWLSMPS_OF_MATCH (comp, label) TWL_OF_MATCH(comp, TWLSMPS, label)static const struct of_device_id twl_of_match[] = {
@@ -1080,6 +1102,7 @@ static const struct of_device_id twl_of_match[] = {TWLFIXED_OF_MATCH ("ti,twl6030-vusb" ,VUSB ),TWLFIXED_OF_MATCH ("ti,twl6030-v1v8" ,V1V8 ),TWLFIXED_OF_MATCH ("ti,twl6030-v2v1" ,V2V1 ), +TWLRES_OF_MATCH ("ti,twl6030-clk32kg" ,CLK32KG ),TWLSMPS_OF_MATCH ("ti,twl6032-smps3" ,SMPS3 ),TWLSMPS_OF_MATCH ("ti,twl6032-smps4" ,SMPS4 ), TWLSMPS_OF_MATCH("ti,twl6032-vio", VIO),
Signature · 1 line
1.9.3
Mark Brown
maintainerRFC PATCH 2/2 regulator: twl: Re-add clk32kg to get wifi working
Quoted 7 lines · Stefan Assmann
This partly reverts the following commits to get the wifi working on the Pandaboard OMAP4430 ES2.2.
0e8e5c34cf1a8beaaf0a6a05c053592693bf8cb4regulator: twl: Remove references to 32kHz clock from DT bindingsd1924519fe1dada0cfd9a228bf2ff1ea15840c84regulator: twl: RemoveTWL6030_FIXED_RESOURCE029dd3cefa46ecdd879f9b4e2df3bdf4371cc22cregulator: twl: Remove another unused variable warninge76ab829cc2d8b6350a3f01fffb208df4d7d8c1bregulator: twl: Remove references to the twl4030 regulator
No, you need to implement clocks using the clock API. Please read the
changelogs for the above commits...
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140714/9c610af0/attachment.sig>
RFC PATCH 2/2 regulator: twl: Re-add clk32kg to get wifi working
Quoted 4 lines · Mark Brown
Quoted 2 lines · Stefan Assmann
This partly reverts the following commits to get the wifi working on the Pandaboard OMAP4430 ES2.2.
Quoted 8 lines
Quoted 4 lines
0e8e5c34cf1a8beaaf0a6a05c053592693bf8cb4regulator: twl: Remove references to 32kHz clock from DT bindingsd1924519fe1dada0cfd9a228bf2ff1ea15840c84regulator: twl: RemoveTWL6030_FIXED_RESOURCE029dd3cefa46ecdd879f9b4e2df3bdf4371cc22cregulator: twl: Remove another unused variable warninge76ab829cc2d8b6350a3f01fffb208df4d7d8c1bregulator: twl: Remove references to the twl4030 regulatorNo, you need to implement clocks using the clock API. Please read the changelogs for the above commits...
Yes, that's what I expected. Got any pointers for me how to do this? Never done that before, a little help would be appreciated.
Stefan
Mark Brown
maintainerRFC PATCH 2/2 regulator: twl: Re-add clk32kg to get wifi working
Quoted 7 lines · Stefan Assmann
Quoted 2 lines · Mark Brown
No, you need to implement clocks using the clock API. Please read the changelogs for the above commits...
Yes, that's what I expected. Got any pointers for me how to do this? Never done that before, a little help would be appreciated.
There should be plenty of examples in drivers/clk?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140714/5fda622a/attachment.sig>
RFC PATCH 2/2 regulator: twl: Re-add clk32kg to get wifi working
Quoted 10 lines · Mark Brown
Quoted 7 lines · Stefan Assmann
Quoted 2 lines · Mark Brown
No, you need to implement clocks using the clock API. Please read the changelogs for the above commits...
Yes, that's what I expected. Got any pointers for me how to do this? Never done that before, a little help would be appreciated.
There should be plenty of examples in
drivers/clk?
Looking at this more closely it seems to me that it's a regulator thing after all. In the end it all boils down to a single register write. twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x41, 0x8e);
This is a write to the CLK32KG_CFG_STATE [1] register to power on the device.
I tried moving that to omap4xxx_dt_clk_init() but that won't work because the twl core structures aren't initialized yet.
Any suggestions?
Stefan
[1] http://www.cjemicros.f2s.com/public/datasheets/TWL6030_Register_Map.pdf page 196
Mark Brown
maintainerRFC PATCH 2/2 regulator: twl: Re-add clk32kg to get wifi working
Quoted 5 lines · Stefan Assmann
Looking at this more closely it seems to me that it's a regulator thing after all. In the end it all boils down to a single register write.
twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x41, 0x8e);
This is a write to theCLK32KG_CFG_STATE[1] register to power on the device.
The register description happening to mention power doesn't mean it's not functionally an enable for a clock.
Quoted 4 lines
I tried moving that to
omap4xxx_dt_clk_init()but that won't work because the twl core structures aren't initialized yet.Any suggestions?
Why not just add this to (or create a new) clock driver for the chip?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140716/8e470177/attachment.sig>
RFC PATCH 2/2 regulator: twl: Re-add clk32kg to get wifi working
Quoted 11 lines · Mark Brown
Quoted 5 lines · Stefan Assmann
Looking at this more closely it seems to me that it's a regulator thing after all. In the end it all boils down to a single register write.
twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x41, 0x8e);
This is a write to theCLK32KG_CFG_STATE[1] register to power on the device.The register description happening to mention power doesn't mean it's not functionally an enable for a clock.
Quoted 7 lines
Quoted 4 lines
I tried moving that to
omap4xxx_dt_clk_init()but that won't work because the twl core structures aren't initialized yet.Any suggestions?
Why not just add this to (or create a new) clock driver for the chip?
Problem is that twl_i2c_write_u8() calls twl_get_regmap() to get the regmap. This requires struct twl_priv to be populated which does not happen until twl_probe has run. That hasn't happened at the point when omap4xxx_dt_clk_init() gets called.
Is there a way to defer a clock driver until twl_probe() has run?
Stefan
Mark Brown
maintainerRFC PATCH 2/2 regulator: twl: Re-add clk32kg to get wifi working
Quoted 9 lines · Stefan Assmann
Quoted 1 line · Mark Brown
Why not just add this to (or create a new) clock driver for the chip?
Problem is that
twl_i2c_write_u8()callstwl_get_regmap()to get the regmap. This requires structtwl_privto be populated which does not happen untiltwl_probehas run. That hasn't happened at the point whenomap4xxx_dt_clk_init()gets called.
Is there a way to defer a clock driver untiltwl_probe()has run?
Why would probe deferral not work the same way as it does for
everything, and what does the core SoC clocking have to do with this?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140717/26c50cd8/attachment.sig>
RFC PATCH 2/2 regulator: twl: Re-add clk32kg to get wifi working
In reply to Mark BrownQuoted 11 lines · Mark Brown
Quoted 5 lines · Stefan Assmann
Looking at this more closely it seems to me that it's a regulator thing after all. In the end it all boils down to a single register write.
twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x41, 0x8e);
This is a write to theCLK32KG_CFG_STATE[1] register to power on the device.The register description happening to mention power doesn't mean it's not functionally an enable for a clock.
Quoted 7 lines
Quoted 4 lines
I tried moving that to
omap4xxx_dt_clk_init()but that won't work because the twl core structures aren't initialized yet.Any suggestions?
Why not just add this to (or create a new) clock driver for the chip?
OK, here's a first attempt to add a clock driver for the twl6030. Let me know if this is going the right direction and I'll post a proper patchset.
Thanks!
Stefan
drivers/clk/Kconfig +7 -0
@@ -65,6 +65,13 @@ config COMMON_CLK_S2MPS11 clock. These multi-function devices have two (S2MPS14) or three (S2MPS11, S5M8767) fixed-rate oscillators, clocked at 32KHz each. +config CLK_TWL6030 + tristate "Clock driver for twl6030" + depends on TWL4030_CORE + ---help--- + Enable the TWL6030 clock CLK32KG which is disabled by default. + Needed on the Pandaboard for the wireless LAN. + config CLK_TWL6040 tristate "External McPDM functional clock from twl6040" depends on TWL6040_CORE
drivers/clk/ti/Makefile +1 -0
@@ -10,4 +10,5 @@ obj-$(CONFIG_SOC_OMAP5) += $(clk-common) clk-54xx.o obj-$(CONFIG_SOC_DRA7XX) += $(clk-common) clk-7xx.o \ clk-dra7-atl.o obj-$(CONFIG_SOC_AM43XX) += $(clk-common) clk-43xx.o +obj-$(CONFIG_CLK_TWL6030) += $(clk-common) clk-6030.o endif
drivers/clk/ti/clk-6030.c new file +147 -0
147 lines not on this page · raw message
drivers/mfd/twl-core.c +23 -6
@@ -34,6 +34,7 @@#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/clk.h> +#include <linux/clk-provider.h> #include <linux/err.h> #include <linux/device.h> #include <linux/of.h>
@@ -459,9 +460,15 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)if (!regmap)return -EPERM ; - ret =regmap_bulk_write (regmap, twl_priv->twl_map[mod_no].base + reg, - value, num_bytes); - +if (num_bytes ==1 ) { + ret =regmap_write (regmap, + twl_priv->twl_map[mod_no].base + reg, + *value); + }else { + ret =regmap_bulk_write (regmap, + twl_priv->twl_map[mod_no].base + reg, + value, num_bytes); + }if (ret)pr_err ("%s: Write failed (mod %d, reg 0x%02x count %d)\n" ,DRIVER_NAME , mod_no, reg, num_bytes);
@@ -482,14 +489,22 @@ EXPORT_SYMBOL(twl_i2c_write);int twl_i2c_read (u8 mod_no,u8 *value,u8 reg,unsigned num_bytes) {struct regmap *regmap =twl_get_regmap (mod_no); +unsigned int val;int ret;if (!regmap)return -EPERM ; - ret =regmap_bulk_read (regmap, twl_priv->twl_map[mod_no].base + reg, - value, num_bytes); - +if (num_bytes ==1 ) { + ret =regmap_read (regmap, + twl_priv->twl_map[mod_no].base + reg, + &val); + *value = val; + }else { + ret =regmap_bulk_read (regmap, + twl_priv->twl_map[mod_no].base + reg, + value, num_bytes); + }if (ret)pr_err ("%s: Read failed (mod %d, reg 0x%02x count %d)\n" ,DRIVER_NAME , mod_no, reg, num_bytes);
@@ -1012,6 +1027,8 @@ static void clocks_init(struct device *dev,u32 rate;u8 ctrl =HFCLK_FREQ_26_MHZ ; +of_clk_init (NULL ); + osc =clk_get (dev,"fck" );if (IS_ERR (osc)) { printk(KERN_WARNING "Skipping twl internal clock init and "
drivers/regulator/twl-regulator.c +0 -11
@@ -94,17 +94,6 @@ struct twlreg_info {#define VREG_BC_PROC 3#define VREG_BC_CLK_RST 4 -/* TWL6030 LDO register values for CFG_STATE */ -#define TWL6030_CFG_STATE_OFF 0x00 -#define TWL6030_CFG_STATE_ON 0x01 -#define TWL6030_CFG_STATE_OFF2 0x02 -#define TWL6030_CFG_STATE_SLEEP 0x03 -#define TWL6030_CFG_STATE_GRP_SHIFT 5 -#define TWL6030_CFG_STATE_APP_SHIFT 2 -#define TWL6030_CFG_STATE_APP_MASK (0x03 << TWL6030_CFG_STATE_APP_SHIFT) -#define TWL6030_CFG_STATE_APP (v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\ - TWL6030_CFG_STATE_APP_SHIFT) -/* Flags for SMPS Voltage reading */ #define SMPS_OFFSET_EN BIT(0)#define SMPS_EXTENDED_EN BIT(1)
include/linux/i2c/twl.h +20 -0
@@ -127,6 +127,20 @@ enum twl6030_module_ids {#define REG_INT_MSK_STS_B 0x07#define REG_INT_MSK_STS_C 0x08 +/* TWL6030 register values for CFG_STATE */ +#define TWL6030_GRP_APP (1 << 0) +#define TWL6030_GRP_CON (1 << 1) +#define TWL6030_GRP_MOD (1 << 2) +#define TWL6030_CFG_STATE_OFF 0x00 +#define TWL6030_CFG_STATE_ON 0x01 +#define TWL6030_CFG_STATE_OFF2 0x02 +#define TWL6030_CFG_STATE_SLEEP 0x03 +#define TWL6030_CFG_STATE_GRP_SHIFT 5 +#define TWL6030_CFG_STATE_APP_SHIFT 2 +#define TWL6030_CFG_STATE_APP_MASK (0x03 << TWL6030_CFG_STATE_APP_SHIFT) +#define TWL6030_CFG_STATE_APP (v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\ + TWL6030_CFG_STATE_APP_SHIFT) +/* MASK INT REG GROUP A */ #define TWL6030_PWR_INT_MASK 0x07#define TWL6030_RTC_INT_MASK 0x18
@@ -470,6 +484,12 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)#define TWL4030_PM_MASTER_GLOBAL_TST 0xb6 +/* +* PM Receiver module register offsets (use TWL_MODULE_PM_RECEIVER) +*/ + +#define TWL6030_PM_RECEIVER_CLK32KG_CFG_STATE 0x8e +/*----------------------------------------------------------------------*/ /* Power bus message definitions */
Signature · 1 line
1.9.3
Mark Brown
maintainerRFC PATCH 2/2 regulator: twl: Re-add clk32kg to get wifi working
Quoted 3 lines · Stefan Assmann
OK, here's a first attempt to add a clock driver for the twl6030. Let me know if this is going the right direction and I'll post a proper patchset.
Looks reasonable to me, though I'm not a clock expert. Few comments...
drivers/clk/ti/clk-6030.c line 126
Quoted 4 lines
drivers/clk/ti/clk-6030.c new file +4
-0+static int of_twl6030_clk32kg_remove (struct platform_device *pdev) +{ +return 0 ; +}
Shouldn't need empty functions.
drivers/mfd/twl-core.c int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) · line 471
Quoted 12 lines
drivers/mfd/twl-core.c +9
-3- ret =regmap_bulk_write (regmap, twl_priv->twl_map[mod_no].base + reg, - value, num_bytes); - +if (num_bytes ==1 ) { + ret =regmap_write (regmap, + twl_priv->twl_map[mod_no].base + reg, + *value); + }else { + ret =regmap_bulk_write (regmap, + twl_priv->twl_map[mod_no].base + reg, + value, num_bytes); + }
Just always use regmap_raw_write() - for single byte values there is no difference anyway, bulk_write() only makes a difference if the values are multi-byte.
drivers/mfd/twl-core.c EXPORT_SYMBOL(twl_i2c_write); · line 498
Quoted 4 lines
drivers/mfd/twl-core.c +1
-3- ret =regmap_bulk_read (regmap, twl_priv->twl_map[mod_no].base + reg, - value, num_bytes); - +if (num_bytes ==1 ) {
Similarly here.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140724/628077f5/attachment.sig>
RFC PATCH 2/2 regulator: twl: Re-add clk32kg to get wifi working
In reply to Stefan AssmannQuoting Stefan Assmann (2014-07-24 08:03:32)
Quoted 29 lines
drivers/clk/ti/clk-6030.c new file +29
-0+#define to_twl6030_desc (_hw) container_of(_hw, struct twl6030_desc, hw) + +static int twl6030_clk32kg_enable (struct clk_hw *hw) +{ +struct twl6030_desc *desc =to_twl6030_desc (hw); +int ret; + + ret =twl_i2c_write_u8 (TWL_MODULE_PM_RECEIVER , +TWL6030_GRP_CON <<TWL6030_CFG_STATE_GRP_SHIFT | +TWL6030_CFG_STATE_ON , +TWL6030_PM_RECEIVER_CLK32KG_CFG_STATE ); +if (ret ==0 ) + desc->enabled = true; + +return ret; +} +void twl6030_clk32kg_disable (struct clk_hw *hw) +{ +struct twl6030_desc *desc =to_twl6030_desc (hw); + +twl_i2c_write_u8 (TWL_MODULE_PM_RECEIVER , +TWL6030_GRP_CON <<TWL6030_CFG_STATE_GRP_SHIFT | +TWL6030_CFG_STATE_OFF , +TWL6030_PM_RECEIVER_CLK32KG_CFG_STATE ); + desc->enabled = false; +} + +static int twl6030_clk32kg_is_enabled (struct clk_hw *hw) +{
drivers/clk/ti/clk-6030.c line 64
Quoted 10 lines
drivers/clk/ti/clk-6030.c new file +10
-0+struct twl6030_desc *desc =to_twl6030_desc (hw); + +return desc->enabled; +} + +static const struct clk_ops twl6030_clk32kg_ops = { + .enable = twl6030_clk32kg_enable, + .disable = twl6030_clk32kg_disable, + .is_enabled = twl6030_clk32kg_is_enabled, +};
All three above need to be converted from {en|dis}able to {un}prepare. The reason is that clk_enable/clk_disable must not sleep and of course i2c transactions might do just that.
Please Cc me on the next version :-)
Regards,
Mike