add 3.13 support

Signed-off-by: Imre Kaloz <kaloz@openwrt.org>

SVN-Revision: 39508
v19.07.3_mercusys_ac12_duma
Imre Kaloz 10 years ago
parent ce62a03ede
commit ed2b3e7771

@ -0,0 +1,203 @@
From 884d3962ef4787c8cf0b8a7a673531c623d1dff8 Mon Sep 17 00:00:00 2001
From: Darren Etheridge <detheridge@ti.com>
Date: Fri, 2 Aug 2013 15:35:36 -0500
Subject: [PATCH 334/752] video: da8xx-fb: adding dt support
Enhancing driver to enable probe triggered by a corresponding dt entry.
Add da8xx-fb.txt documentation to devicetree section.
Obtain fb_videomode details for the connected lcd panel using the
display timing details present in DT.
Ensure that platform data is present before checking whether platform
callback is present (the one used to control backlight). So far this
was not an issue as driver was purely non-DT triggered, but now DT
support has been added this check must be performed.
v2: squashing multiple commits from Afzal Mohammed (afzal@ti.com)
v3: remove superfluous cast
v4: expose both ti,am3352-lcdc and ti,da830-lcdc for .compatible
as driver can use enhanced features of all version of the
silicon block.
v5: addressed review comments from Prabhakar Lad
v6: Changed the .compatible naming to match the existing drm bindings
for am33xx devices
v7: clarify which compatible to use in the documentation for DA850
Acked-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>
Signed-off-by: Darren Etheridge <detheridge@ti.com>
---
.../devicetree/bindings/video/da8xx-fb.txt | 42 +++++++++++++
drivers/video/da8xx-fb.c | 66 +++++++++++++++++++-
2 files changed, 105 insertions(+), 3 deletions(-)
create mode 100644 Documentation/devicetree/bindings/video/da8xx-fb.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/da8xx-fb.txt
@@ -0,0 +1,42 @@
+TI LCD Controller on DA830/DA850/AM335x SoC's
+
+Required properties:
+- compatible:
+ DA830, DA850 - "ti,da8xx-tilcdc"
+ AM335x SoC's - "ti,am33xx-tilcdc"
+- reg: Address range of lcdc register set
+- interrupts: lcdc interrupt
+- display-timings: typical videomode of lcd panel, represented as child.
+ Refer Documentation/devicetree/bindings/video/display-timing.txt for
+ display timing binding details. If multiple videomodes are mentioned
+ in display timings node, typical videomode has to be mentioned as the
+ native mode or it has to be first child (driver cares only for native
+ videomode).
+
+Recommended properties:
+- ti,hwmods: Name of the hwmod associated to the LCDC
+
+Example for am335x SoC's:
+
+lcdc@4830e000 {
+ compatible = "ti,am33xx-tilcdc";
+ reg = <0x4830e000 0x1000>;
+ interrupts = <36>;
+ ti,hwmods = "lcdc";
+ status = "okay";
+ display-timings {
+ 800x480p62 {
+ clock-frequency = <30000000>;
+ hactive = <800>;
+ vactive = <480>;
+ hfront-porch = <39>;
+ hback-porch = <39>;
+ hsync-len = <47>;
+ vback-porch = <29>;
+ vfront-porch = <13>;
+ vsync-len = <2>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ };
+ };
+};
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -36,6 +36,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/lcm.h>
+#include <video/of_display_timing.h>
#include <video/da8xx-fb.h>
#include <asm/div64.h>
@@ -1311,12 +1312,54 @@ static struct fb_ops da8xx_fb_ops = {
.fb_blank = cfb_blank,
};
+static struct lcd_ctrl_config *da8xx_fb_create_cfg(struct platform_device *dev)
+{
+ struct lcd_ctrl_config *cfg;
+
+ cfg = devm_kzalloc(&dev->dev, sizeof(struct fb_videomode), GFP_KERNEL);
+ if (!cfg)
+ return NULL;
+
+ /* default values */
+
+ if (lcd_revision == LCD_VERSION_1)
+ cfg->bpp = 16;
+ else
+ cfg->bpp = 32;
+
+ /*
+ * For panels so far used with this LCDC, below statement is sufficient.
+ * For new panels, if required, struct lcd_ctrl_cfg fields to be updated
+ * with additional/modified values. Those values would have to be then
+ * obtained from dt(requiring new dt bindings).
+ */
+
+ cfg->panel_shade = COLOR_ACTIVE;
+
+ return cfg;
+}
+
static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
{
struct da8xx_lcdc_platform_data *fb_pdata = dev_get_platdata(&dev->dev);
struct fb_videomode *lcdc_info;
+ struct device_node *np = dev->dev.of_node;
int i;
+ if (np) {
+ lcdc_info = devm_kzalloc(&dev->dev,
+ sizeof(struct fb_videomode),
+ GFP_KERNEL);
+ if (!lcdc_info)
+ return NULL;
+
+ if (of_get_fb_videomode(np, lcdc_info, OF_USE_NATIVE_MODE)) {
+ dev_err(&dev->dev, "timings not available in DT\n");
+ return NULL;
+ }
+ return lcdc_info;
+ }
+
for (i = 0, lcdc_info = known_lcd_panels;
i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) {
if (strcmp(fb_pdata->type, lcdc_info->name) == 0)
@@ -1345,7 +1388,7 @@ static int fb_probe(struct platform_devi
int ret;
unsigned long ulcm;
- if (fb_pdata == NULL) {
+ if (fb_pdata == NULL && !device->dev.of_node) {
dev_err(&device->dev, "Can not get platform data\n");
return -ENOENT;
}
@@ -1385,7 +1428,10 @@ static int fb_probe(struct platform_devi
break;
}
- lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
+ if (device->dev.of_node)
+ lcd_cfg = da8xx_fb_create_cfg(device);
+ else
+ lcd_cfg = fb_pdata->controller_data;
if (!lcd_cfg) {
ret = -EINVAL;
@@ -1404,7 +1450,7 @@ static int fb_probe(struct platform_devi
par->dev = &device->dev;
par->lcdc_clk = tmp_lcdc_clk;
par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk);
- if (fb_pdata->panel_power_ctrl) {
+ if (fb_pdata && fb_pdata->panel_power_ctrl) {
par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
par->panel_power_ctrl(1);
}
@@ -1652,6 +1698,19 @@ static int fb_resume(struct platform_dev
#define fb_resume NULL
#endif
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id da8xx_fb_of_match[] = {
+ /*
+ * this driver supports version 1 and version 2 of the
+ * Texas Instruments lcd controller (lcdc) hardware block
+ */
+ {.compatible = "ti,da8xx-tilcdc", },
+ {.compatible = "ti,am33xx-tilcdc", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, da8xx_fb_of_match);
+#endif
+
static struct platform_driver da8xx_fb_driver = {
.probe = fb_probe,
.remove = fb_remove,
@@ -1660,6 +1719,7 @@ static struct platform_driver da8xx_fb_d
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(da8xx_fb_of_match),
},
};
module_platform_driver(da8xx_fb_driver);

@ -0,0 +1,91 @@
From 9a1a810516ae9cb3259b898b6879901c5b44fa90 Mon Sep 17 00:00:00 2001
From: Prathap M S <msprathap@ti.com>
Date: Mon, 2 Sep 2013 12:05:23 +0530
Subject: [PATCH 343/752] video: da8xx-fb: Add API to register wait for vsync
callback
This patch adds APIs to register and unregister wait for vsync callback.
This is derived from commit id 2d44302545da24fd22912d964102bc31a7489e97
This commit id was part of 3.2 kernel sources.
Signed-off-by: Prathap M S <msprathap@ti.com>
---
drivers/video/da8xx-fb.c | 33 +++++++++++++++++++++++++++++++++
include/video/da8xx-fb.h | 4 ++++
2 files changed, 37 insertions(+)
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -197,6 +197,9 @@ static struct fb_fix_screeninfo da8xx_fb
.accel = FB_ACCEL_NONE
};
+static vsync_callback_t vsync_cb_handler;
+static void *vsync_cb_arg;
+
static struct fb_videomode known_lcd_panels[] = {
/* Sharp LCD035Q3DG01 */
[0] = {
@@ -825,6 +828,32 @@ static int lcd_init(struct da8xx_fb_par
return 0;
}
+int register_vsync_cb(vsync_callback_t handler, void *arg, int idx)
+{
+ if ((vsync_cb_handler == NULL) && (vsync_cb_arg == NULL)) {
+ vsync_cb_arg = arg;
+ vsync_cb_handler = handler;
+ } else {
+ return -EEXIST;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(register_vsync_cb);
+
+int unregister_vsync_cb(vsync_callback_t handler, void *arg, int idx)
+{
+ if ((vsync_cb_handler == handler) && (vsync_cb_arg == arg)) {
+ vsync_cb_handler = NULL;
+ vsync_cb_arg = NULL;
+ } else {
+ return -ENXIO;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(unregister_vsync_cb);
+
/* IRQ handler for version 2 of LCDC */
static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
{
@@ -862,6 +891,8 @@ static irqreturn_t lcdc_irq_handler_rev0
LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
par->vsync_flag = 1;
wake_up_interruptible(&par->vsync_wait);
+ if (vsync_cb_handler)
+ vsync_cb_handler(vsync_cb_arg);
}
if (stat & LCD_END_OF_FRAME1) {
@@ -937,6 +968,8 @@ static irqreturn_t lcdc_irq_handler_rev0
LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
par->vsync_flag = 1;
wake_up_interruptible(&par->vsync_wait);
+ if (vsync_cb_handler)
+ vsync_cb_handler(vsync_cb_arg);
}
}
--- a/include/video/da8xx-fb.h
+++ b/include/video/da8xx-fb.h
@@ -91,5 +91,9 @@ struct lcd_sync_arg {
/* Proprietary FB_SYNC_ flags */
#define FB_SYNC_CLK_INVERT 0x40000000
+typedef void (*vsync_callback_t)(void *arg);
+int register_vsync_cb(vsync_callback_t handler, void *arg, int idx);
+int unregister_vsync_cb(vsync_callback_t handler, void *arg, int idx);
+
#endif /* ifndef DA8XX_FB_H */

@ -0,0 +1,38 @@
From c99bd415829ef29adf71bb1e1b577650f10e93f5 Mon Sep 17 00:00:00 2001
From: Darren Etheridge <detheridge@ti.com>
Date: Mon, 4 Nov 2013 12:27:40 -0600
Subject: [PATCH 752/752] video/da8xx-fb fix defect with vsync callback
invocation
Fix defect where SGX is running at half of the expected framerate.
The original patch (@ commit ID 9a1a810516ae9cb3259b898b6879901c5b44fa90)
seems to have a mistake where it only calls the callback
for the even or the odd frames depending on the revision of the LCD controller
This patch corrects this and invokes the callback for both odd and even frame
for just the Rev02 version of the LCDC (won't find an SGX GPU on a Rev01).
Signed-off-by: Darren Etheridge <detheridge@ti.com>
---
drivers/video/da8xx-fb.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -903,6 +903,8 @@ static irqreturn_t lcdc_irq_handler_rev0
LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
par->vsync_flag = 1;
wake_up_interruptible(&par->vsync_wait);
+ if (vsync_cb_handler)
+ vsync_cb_handler(vsync_cb_arg);
}
/* Set only when controller is disabled and at the end of
@@ -968,8 +970,6 @@ static irqreturn_t lcdc_irq_handler_rev0
LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
par->vsync_flag = 1;
wake_up_interruptible(&par->vsync_wait);
- if (vsync_cb_handler)
- vsync_cb_handler(vsync_cb_arg);
}
}

@ -0,0 +1,198 @@
Move the wl1251 part of the wl12xx platform data structure into a new
structure specifically for wl1251. Change the platform data built-in
block and board files accordingly.
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
arch/arm/mach-omap2/board-omap3pandora.c | 4 +--
arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +-
drivers/net/wireless/ti/wilink_platform_data.c | 37 +++++++++++++++++++++-----
drivers/net/wireless/ti/wl1251/sdio.c | 12 ++++-----
drivers/net/wireless/ti/wl1251/spi.c | 2 +-
include/linux/wl12xx.h | 22 ++++++++++++++-
6 files changed, 62 insertions(+), 17 deletions(-)
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -536,7 +536,7 @@ static struct spi_board_info omap3pandor
static void __init pandora_wl1251_init(void)
{
- struct wl12xx_platform_data pandora_wl1251_pdata;
+ struct wl1251_platform_data pandora_wl1251_pdata;
int ret;
memset(&pandora_wl1251_pdata, 0, sizeof(pandora_wl1251_pdata));
@@ -550,7 +550,7 @@ static void __init pandora_wl1251_init(v
goto fail_irq;
pandora_wl1251_pdata.use_eeprom = true;
- ret = wl12xx_set_platform_data(&pandora_wl1251_pdata);
+ ret = wl1251_set_platform_data(&pandora_wl1251_pdata);
if (ret < 0)
goto fail_irq;
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -84,7 +84,7 @@ enum {
RX51_SPI_MIPID, /* LCD panel */
};
-static struct wl12xx_platform_data wl1251_pdata;
+static struct wl1251_platform_data wl1251_pdata;
static struct tsc2005_platform_data tsc2005_pdata;
#if defined(CONFIG_SENSORS_LIS3_I2C) || defined(CONFIG_SENSORS_LIS3_I2C_MODULE)
--- a/drivers/net/wireless/ti/wilink_platform_data.c
+++ b/drivers/net/wireless/ti/wilink_platform_data.c
@@ -23,17 +23,17 @@
#include <linux/err.h>
#include <linux/wl12xx.h>
-static struct wl12xx_platform_data *platform_data;
+static struct wl12xx_platform_data *wl12xx_platform_data;
int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data)
{
- if (platform_data)
+ if (wl12xx_platform_data)
return -EBUSY;
if (!data)
return -EINVAL;
- platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
- if (!platform_data)
+ wl12xx_platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
+ if (!wl12xx_platform_data)
return -ENOMEM;
return 0;
@@ -41,9 +41,34 @@ int __init wl12xx_set_platform_data(cons
struct wl12xx_platform_data *wl12xx_get_platform_data(void)
{
- if (!platform_data)
+ if (!wl12xx_platform_data)
return ERR_PTR(-ENODEV);
- return platform_data;
+ return wl12xx_platform_data;
}
EXPORT_SYMBOL(wl12xx_get_platform_data);
+
+static struct wl1251_platform_data *wl1251_platform_data;
+
+int __init wl1251_set_platform_data(const struct wl1251_platform_data *data)
+{
+ if (wl1251_platform_data)
+ return -EBUSY;
+ if (!data)
+ return -EINVAL;
+
+ wl1251_platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
+ if (!wl1251_platform_data)
+ return -ENOMEM;
+
+ return 0;
+}
+
+struct wl1251_platform_data *wl1251_get_platform_data(void)
+{
+ if (!wl1251_platform_data)
+ return ERR_PTR(-ENODEV);
+
+ return wl1251_platform_data;
+}
+EXPORT_SYMBOL(wl1251_get_platform_data);
--- a/drivers/net/wireless/ti/wl1251/sdio.c
+++ b/drivers/net/wireless/ti/wl1251/sdio.c
@@ -227,7 +227,7 @@ static int wl1251_sdio_probe(struct sdio
struct wl1251 *wl;
struct ieee80211_hw *hw;
struct wl1251_sdio *wl_sdio;
- const struct wl12xx_platform_data *wl12xx_board_data;
+ const struct wl1251_platform_data *wl1251_board_data;
hw = wl1251_alloc_hw();
if (IS_ERR(hw))
@@ -254,11 +254,11 @@ static int wl1251_sdio_probe(struct sdio
wl->if_priv = wl_sdio;
wl->if_ops = &wl1251_sdio_ops;
- wl12xx_board_data = wl12xx_get_platform_data();
- if (!IS_ERR(wl12xx_board_data)) {
- wl->set_power = wl12xx_board_data->set_power;
- wl->irq = wl12xx_board_data->irq;
- wl->use_eeprom = wl12xx_board_data->use_eeprom;
+ wl1251_board_data = wl1251_get_platform_data();
+ if (!IS_ERR(wl1251_board_data)) {
+ wl->set_power = wl1251_board_data->set_power;
+ wl->irq = wl1251_board_data->irq;
+ wl->use_eeprom = wl1251_board_data->use_eeprom;
}
if (wl->irq) {
--- a/drivers/net/wireless/ti/wl1251/spi.c
+++ b/drivers/net/wireless/ti/wl1251/spi.c
@@ -238,7 +238,7 @@ static const struct wl1251_if_operations
static int wl1251_spi_probe(struct spi_device *spi)
{
- struct wl12xx_platform_data *pdata;
+ struct wl1251_platform_data *pdata;
struct ieee80211_hw *hw;
struct wl1251 *wl;
int ret;
--- a/include/linux/wl12xx.h
+++ b/include/linux/wl12xx.h
@@ -48,11 +48,15 @@ enum {
WL12XX_TCXOCLOCK_33_6 = 7, /* 33.6 MHz */
};
-struct wl12xx_platform_data {
+struct wl1251_platform_data {
void (*set_power)(bool enable);
/* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */
int irq;
bool use_eeprom;
+};
+
+struct wl12xx_platform_data {
+ int irq;
int board_ref_clock;
int board_tcxo_clock;
unsigned long platform_quirks;
@@ -68,6 +72,10 @@ int wl12xx_set_platform_data(const struc
struct wl12xx_platform_data *wl12xx_get_platform_data(void);
+int wl1251_set_platform_data(const struct wl1251_platform_data *data);
+
+struct wl1251_platform_data *wl1251_get_platform_data(void);
+
#else
static inline
@@ -81,6 +89,18 @@ struct wl12xx_platform_data *wl12xx_get_
{
return ERR_PTR(-ENODATA);
}
+
+static inline
+int wl1251_set_platform_data(const struct wl1251_platform_data *data)
+{
+ return -ENOSYS;
+}
+
+static inline
+struct wl1251_platform_data *wl1251_get_platform_data(void)
+{
+ return ERR_PTR(-ENODATA);
+}
#endif

@ -0,0 +1,126 @@
The platform_quirk element in the platform data was used to change the
way the IRQ is triggered. When set, the EDGE_IRQ quirk would change
the irqflags used and treat edge trigger differently from the rest.
Instead of hiding this irq flag setting behind the quirk, have the
board files set the flags during initialization. This will be more
meaningful than driver-specific quirks when we switch to DT.
Additionally, fix missing gpio_request() calls in the boarding files
(so that setting the flags actually works).
Cc: Tony Lindgren <tony@atomide.com>
Cc: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
Acked-by: Sekhar Nori <nsekhar@ti.com>
---
arch/arm/mach-davinci/board-da850-evm.c | 8 +++++++-
arch/arm/mach-omap2/board-omap3evm.c | 19 ++++++++++++++++++
arch/arm/mach-omap2/board-zoom-peripherals.c | 30 +++++++++++++++++++++++++---
drivers/net/wireless/ti/wlcore/debugfs.c | 2 +-
drivers/net/wireless/ti/wlcore/main.c | 17 ++++++++--------
drivers/net/wireless/ti/wlcore/wlcore.h | 5 ++---
include/linux/wl12xx.h | 4 ----
7 files changed, 64 insertions(+), 21 deletions(-)
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -27,6 +27,7 @@
#include <linux/vmalloc.h>
#include <linux/wl12xx.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include "wlcore.h"
#include "debug.h"
@@ -529,7 +530,7 @@ static int wlcore_irq_locked(struct wl12
* In case edge triggered interrupt must be used, we cannot iterate
* more than once without introducing race conditions with the hardirq.
*/
- if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ)
+ if (wl->irq_flags & IRQF_TRIGGER_RISING)
loopcount = 1;
wl1271_debug(DEBUG_IRQ, "IRQ work");
@@ -5893,7 +5894,6 @@ struct ieee80211_hw *wlcore_alloc_hw(siz
wl->ap_ps_map = 0;
wl->ap_fw_ps_map = 0;
wl->quirks = 0;
- wl->platform_quirks = 0;
wl->system_hlid = WL12XX_SYSTEM_HLID;
wl->active_sta_count = 0;
wl->active_link_count = 0;
@@ -6034,7 +6034,7 @@ static void wlcore_nvs_cb(const struct f
struct platform_device *pdev = wl->pdev;
struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev);
struct wl12xx_platform_data *pdata = pdev_data->pdata;
- unsigned long irqflags;
+
int ret;
irq_handler_t hardirq_fn = NULL;
@@ -6062,18 +6062,17 @@ static void wlcore_nvs_cb(const struct f
wlcore_adjust_conf(wl);
wl->irq = platform_get_irq(pdev, 0);
- wl->platform_quirks = pdata->platform_quirks;
wl->if_ops = pdev_data->if_ops;
- if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) {
- irqflags = IRQF_TRIGGER_RISING;
- hardirq_fn = wlcore_hardirq;
- } else {
- irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
- }
+ wl->irq_flags = irq_get_trigger_type(wl->irq);
+
+ hardirq_fn = wlcore_hardirq;
+
+ /* Since we don't use the primary handler, we must set ONESHOT */
+ wl->irq_flags |= IRQF_ONESHOT;
ret = request_threaded_irq(wl->irq, hardirq_fn, wlcore_irq,
- irqflags, pdev->name, wl);
+ wl->irq_flags, pdev->name, wl);
if (ret < 0) {
wl1271_error("request_irq() failed: %d", ret);
goto out_free_nvs;
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -186,6 +186,8 @@ struct wl1271 {
int irq;
+ int irq_flags;
+
spinlock_t wl_lock;
enum wlcore_state state;
@@ -393,9 +395,6 @@ struct wl1271 {
/* Quirks of specific hardware revisions */
unsigned int quirks;
- /* Platform limitations */
- unsigned int platform_quirks;
-
/* number of currently active RX BA sessions */
int ba_rx_session_count;
--- a/include/linux/wl12xx.h
+++ b/include/linux/wl12xx.h
@@ -59,13 +59,9 @@ struct wl12xx_platform_data {
int irq;
int board_ref_clock;
int board_tcxo_clock;
- unsigned long platform_quirks;
bool pwr_in_suspend;
};
-/* Platform does not support level trigger interrupts */
-#define WL12XX_PLATFORM_QUIRK_EDGE_IRQ BIT(0)
-
#ifdef CONFIG_WILINK_PLATFORM_DATA
int wl12xx_set_platform_data(const struct wl12xx_platform_data *data);

@ -0,0 +1,65 @@
The pwr_in_suspend flag depends on the MMC settings which can be
retrieved from the SDIO subsystem, so it doesn't need to be part of
the platform data structure. Move it to the platform device data that
is passed from SDIO to wlcore.
Signed-off-by: Luciano Coelho <coelho@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
drivers/net/wireless/ti/wlcore/main.c | 3 +--
drivers/net/wireless/ti/wlcore/sdio.c | 2 +-
drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 +
include/linux/wl12xx.h | 1 -
4 files changed, 3 insertions(+), 4 deletions(-)
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -6033,7 +6033,6 @@ static void wlcore_nvs_cb(const struct f
struct wl1271 *wl = context;
struct platform_device *pdev = wl->pdev;
struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev);
- struct wl12xx_platform_data *pdata = pdev_data->pdata;
int ret;
irq_handler_t hardirq_fn = NULL;
@@ -6083,7 +6082,7 @@ static void wlcore_nvs_cb(const struct f
if (!ret) {
wl->irq_wake_enabled = true;
device_init_wakeup(wl->dev, 1);
- if (pdata->pwr_in_suspend)
+ if (pdev_data->pwr_in_suspend)
wl->hw->wiphy->wowlan = &wlcore_wowlan_support;
}
#endif
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -260,7 +260,7 @@ static int wl1271_probe(struct sdio_func
dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags);
if (mmcflags & MMC_PM_KEEP_POWER)
- pdev_data->pdata->pwr_in_suspend = true;
+ pdev_data->pwr_in_suspend = true;
sdio_set_drvdata(func, glue);
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -209,6 +209,7 @@ struct wl1271_if_operations {
struct wlcore_platdev_data {
struct wl12xx_platform_data *pdata;
struct wl1271_if_operations *if_ops;
+ bool pwr_in_suspend;
};
#define MAX_NUM_KEYS 14
--- a/include/linux/wl12xx.h
+++ b/include/linux/wl12xx.h
@@ -59,7 +59,6 @@ struct wl12xx_platform_data {
int irq;
int board_ref_clock;
int board_tcxo_clock;
- bool pwr_in_suspend;
};
#ifdef CONFIG_WILINK_PLATFORM_DATA

@ -0,0 +1,231 @@
Instead of defining an enumeration with the FW specific values for the
different clock rates, use the actual frequency instead. Also add a
boolean to specify whether the clock is XTAL or not.
Change all board files to reflect this.
Additionally, this reverts commit 26f45c (ARM: OMAP2+: Legacy support
for wl12xx when booted with devicetree), since this is not be needed
anymore, now that DT support for WiLink is implemented.
Cc: Tony Lindgren <tony@atomide.com>
Cc: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
arch/arm/mach-davinci/board-da850-evm.c | 3 +-
arch/arm/mach-omap2/board-omap3evm.c | 3 +-
arch/arm/mach-omap2/board-zoom-peripherals.c | 3 +-
arch/arm/mach-omap2/devices.c | 39 -------------------
drivers/net/wireless/ti/wl12xx/main.c | 58 +++++++++++++++++++++++++++-
drivers/net/wireless/ti/wl12xx/wl12xx.h | 28 ++++++++++++++
include/linux/wl12xx.h | 27 ++-----------
7 files changed, 93 insertions(+), 68 deletions(-)
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1711,6 +1711,43 @@ static struct ieee80211_sta_ht_cap wl12x
},
};
+static const struct wl12xx_clock wl12xx_refclock_table[] = {
+ { 19200000, false, WL12XX_REFCLOCK_19 },
+ { 26000000, false, WL12XX_REFCLOCK_26 },
+ { 26000000, true, WL12XX_REFCLOCK_26_XTAL },
+ { 38400000, false, WL12XX_REFCLOCK_38 },
+ { 38400000, true, WL12XX_REFCLOCK_38_XTAL },
+ { 52000000, false, WL12XX_REFCLOCK_52 },
+ { 0, false, 0 }
+};
+
+static const struct wl12xx_clock wl12xx_tcxoclock_table[] = {
+ { 16368000, true, WL12XX_TCXOCLOCK_16_368 },
+ { 16800000, true, WL12XX_TCXOCLOCK_16_8 },
+ { 19200000, true, WL12XX_TCXOCLOCK_19_2 },
+ { 26000000, true, WL12XX_TCXOCLOCK_26 },
+ { 32736000, true, WL12XX_TCXOCLOCK_32_736 },
+ { 33600000, true, WL12XX_TCXOCLOCK_33_6 },
+ { 38400000, true, WL12XX_TCXOCLOCK_38_4 },
+ { 52000000, true, WL12XX_TCXOCLOCK_52 },
+ { 0, false, 0 }
+};
+
+static int wl12xx_get_clock_idx(const struct wl12xx_clock *table,
+ u32 freq, bool xtal)
+{
+ int i = 0;
+
+ while(table[i].freq != 0) {
+ if ((table[i].freq == freq) &&
+ (table[i].xtal == xtal))
+ return table[i].hw_idx;
+ i++;
+ };
+
+ return -EINVAL;
+}
+
static int wl12xx_setup(struct wl1271 *wl)
{
struct wl12xx_priv *priv = wl->priv;
@@ -1732,7 +1769,16 @@ static int wl12xx_setup(struct wl1271 *w
wl12xx_conf_init(wl);
if (!fref_param) {
- priv->ref_clock = pdata->board_ref_clock;
+ priv->ref_clock = wl12xx_get_clock_idx(wl12xx_refclock_table,
+ pdata->ref_clock_freq,
+ pdata->ref_clock_xtal);
+ if (priv->ref_clock < 0) {
+ wl1271_error("Invalid ref_clock frequency (%d Hz, %s)",
+ pdata->ref_clock_freq,
+ pdata->ref_clock_xtal ? "XTAL" : "not XTAL");
+
+ return priv->ref_clock;
+ }
} else {
if (!strcmp(fref_param, "19.2"))
priv->ref_clock = WL12XX_REFCLOCK_19;
@@ -1751,7 +1797,15 @@ static int wl12xx_setup(struct wl1271 *w
}
if (!tcxo_param) {
- priv->tcxo_clock = pdata->board_tcxo_clock;
+ priv->tcxo_clock = wl12xx_get_clock_idx(wl12xx_tcxoclock_table,
+ pdata->tcxo_clock_freq,
+ true);
+ if (priv->tcxo_clock < 0) {
+ wl1271_error("Invalid tcxo_clock frequency (%d Hz)",
+ pdata->tcxo_clock_freq);
+
+ return priv->tcxo_clock;
+ }
} else {
if (!strcmp(tcxo_param, "19.2"))
priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2;
--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
@@ -79,4 +79,32 @@ struct wl12xx_priv {
struct wl127x_rx_mem_pool_addr *rx_mem_addr;
};
+/* Reference clock values */
+enum {
+ WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */
+ WL12XX_REFCLOCK_26 = 1, /* 26 MHz */
+ WL12XX_REFCLOCK_38 = 2, /* 38.4 MHz */
+ WL12XX_REFCLOCK_52 = 3, /* 52 MHz */
+ WL12XX_REFCLOCK_38_XTAL = 4, /* 38.4 MHz, XTAL */
+ WL12XX_REFCLOCK_26_XTAL = 5, /* 26 MHz, XTAL */
+};
+
+/* TCXO clock values */
+enum {
+ WL12XX_TCXOCLOCK_19_2 = 0, /* 19.2MHz */
+ WL12XX_TCXOCLOCK_26 = 1, /* 26 MHz */
+ WL12XX_TCXOCLOCK_38_4 = 2, /* 38.4MHz */
+ WL12XX_TCXOCLOCK_52 = 3, /* 52 MHz */
+ WL12XX_TCXOCLOCK_16_368 = 4, /* 16.368 MHz */
+ WL12XX_TCXOCLOCK_32_736 = 5, /* 32.736 MHz */
+ WL12XX_TCXOCLOCK_16_8 = 6, /* 16.8 MHz */
+ WL12XX_TCXOCLOCK_33_6 = 7, /* 33.6 MHz */
+};
+
+struct wl12xx_clock {
+ u32 freq;
+ bool xtal;
+ u8 hw_idx;
+};
+
#endif /* __WL12XX_PRIV_H__ */
--- a/include/linux/wl12xx.h
+++ b/include/linux/wl12xx.h
@@ -26,28 +26,6 @@
#include <linux/err.h>
-/* Reference clock values */
-enum {
- WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */
- WL12XX_REFCLOCK_26 = 1, /* 26 MHz */
- WL12XX_REFCLOCK_38 = 2, /* 38.4 MHz */
- WL12XX_REFCLOCK_52 = 3, /* 52 MHz */
- WL12XX_REFCLOCK_38_XTAL = 4, /* 38.4 MHz, XTAL */
- WL12XX_REFCLOCK_26_XTAL = 5, /* 26 MHz, XTAL */
-};
-
-/* TCXO clock values */
-enum {
- WL12XX_TCXOCLOCK_19_2 = 0, /* 19.2MHz */
- WL12XX_TCXOCLOCK_26 = 1, /* 26 MHz */
- WL12XX_TCXOCLOCK_38_4 = 2, /* 38.4MHz */
- WL12XX_TCXOCLOCK_52 = 3, /* 52 MHz */
- WL12XX_TCXOCLOCK_16_368 = 4, /* 16.368 MHz */
- WL12XX_TCXOCLOCK_32_736 = 5, /* 32.736 MHz */
- WL12XX_TCXOCLOCK_16_8 = 6, /* 16.8 MHz */
- WL12XX_TCXOCLOCK_33_6 = 7, /* 33.6 MHz */
-};
-
struct wl1251_platform_data {
void (*set_power)(bool enable);
/* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */
@@ -57,8 +35,9 @@ struct wl1251_platform_data {
struct wl12xx_platform_data {
int irq;
- int board_ref_clock;
- int board_tcxo_clock;
+ int ref_clock_freq; /* in Hertz */
+ bool ref_clock_xtal; /* specify whether the clock is XTAL or not */
+ int tcxo_clock_freq; /* in Hertz, tcxo is always XTAL */
};
#ifdef CONFIG_WILINK_PLATFORM_DATA
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -50,8 +50,8 @@ static void __init __used legacy_init_wl
{
int res;
- wl12xx.board_ref_clock = ref_clock;
- wl12xx.board_tcxo_clock = tcxo_clock;
+ wl12xx.ref_clock_freq = ref_clock;
+ wl12xx.tcxo_clock_freq = tcxo_clock;
wl12xx.irq = gpio_to_irq(gpio);
res = wl12xx_set_platform_data(&wl12xx);
@@ -85,12 +85,12 @@ static void __init omap3_igep0020_legacy
static void __init omap3_evm_legacy_init(void)
{
- legacy_init_wl12xx(WL12XX_REFCLOCK_38, 0, 149);
+ legacy_init_wl12xx(38400000, 0, 149);
}
static void __init omap3_zoom_legacy_init(void)
{
- legacy_init_wl12xx(WL12XX_REFCLOCK_26, 0, 162);
+ legacy_init_wl12xx(26000000, 0, 162);
}
#endif /* CONFIG_ARCH_OMAP3 */
@@ -98,15 +98,15 @@ static void __init omap3_zoom_legacy_ini
static void __init omap4_sdp_legacy_init(void)
{
omap_4430sdp_display_init_of();
- legacy_init_wl12xx(WL12XX_REFCLOCK_26,
- WL12XX_TCXOCLOCK_26, 53);
+ legacy_init_wl12xx(26000000,
+ 26000000, 53);
}
static void __init omap4_panda_legacy_init(void)
{
omap4_panda_display_init_of();
legacy_init_ehci_clk("auxclk3_ck");
- legacy_init_wl12xx(WL12XX_REFCLOCK_38, 0, 53);
+ legacy_init_wl12xx(38400000, 0, 53);
}
#endif

@ -0,0 +1,122 @@
If platform data is not available, try to get the required information
from the device tree. Register an OF match table and parse the
appropriate device tree nodes.
Parse interrupt property only, for now.
Signed-off-by: Luciano Coelho <coelho@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
drivers/net/wireless/ti/wlcore/sdio.c | 69 ++++++++++++++++++++++++++++++++---
1 file changed, 63 insertions(+), 6 deletions(-)
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -30,7 +30,7 @@
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
-#include <linux/gpio.h>
+#include <linux/of_irq.h>
#include <linux/wl12xx.h>
#include <linux/pm_runtime.h>
#include <linux/printk.h>
@@ -214,6 +214,43 @@ static struct wl1271_if_operations sdio_
.set_block_size = wl1271_sdio_set_block_size,
};
+static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
+{
+ struct wl12xx_platform_data *pdata;
+ struct device_node *np = dev->of_node;
+
+ if (!np) {
+ np = of_find_matching_node(NULL, dev->driver->of_match_table);
+ if (!np) {
+ dev_notice(dev, "device tree node not available\n");
+ pdata = ERR_PTR(-ENODEV);
+ goto out;
+ }
+ }
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(dev, "can't allocate platform data\n");
+ pdata = ERR_PTR(-ENODEV);
+ goto out;
+ }
+
+ pdata->irq = irq_of_parse_and_map(np, 0);
+ if (pdata->irq < 0) {
+ dev_err(dev, "can't get interrupt gpio from the device tree\n");
+ goto out_free;
+ }
+
+ goto out;
+
+out_free:
+ kfree(pdata);
+ pdata = ERR_PTR(-ENODEV);
+
+out:
+ return pdata;
+}
+
static int wl1271_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
@@ -248,11 +285,22 @@ static int wl1271_probe(struct sdio_func
/* Use block mode for transferring over one block size of data */
func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
+ /* The pdata allocated here is freed when the device is freed,
+ * so we don't need an additional out label to free it in case
+ * of error further on.
+ */
+
+ /* Try to get legacy platform data from the board file */
pdev_data->pdata = wl12xx_get_platform_data();
if (IS_ERR(pdev_data->pdata)) {
- ret = PTR_ERR(pdev_data->pdata);
- dev_err(glue->dev, "missing wlan platform data: %d\n", ret);
- goto out_free_glue;
+ dev_info(&func->dev,
+ "legacy platform data not found, trying device tree\n");
+
+ pdev_data->pdata = wlcore_get_pdata_from_of(&func->dev);
+ if (IS_ERR(pdev_data->pdata)) {
+ dev_err(&func->dev, "can't get platform data\n");
+ goto out_free_glue;
+ }
}
/* if sdio can keep power while host is suspended, enable wow */
@@ -386,16 +434,25 @@ static const struct dev_pm_ops wl1271_sd
};
#endif
+static const struct of_device_id wlcore_sdio_of_match_table[] = {
+ { .compatible = "ti,wilink6" },
+ { .compatible = "ti,wilink7" },
+ { .compatible = "ti,wilink8" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wlcore_sdio_of_match_table);
+
static struct sdio_driver wl1271_sdio_driver = {
.name = "wl1271_sdio",
.id_table = wl1271_devices,
.probe = wl1271_probe,
.remove = wl1271_remove,
-#ifdef CONFIG_PM
.drv = {
+#ifdef CONFIG_PM
.pm = &wl1271_sdio_pm_ops,
- },
#endif
+ .of_match_table = of_match_ptr(wlcore_sdio_of_match_table),
+ },
};
static int __init wl1271_init(void)

@ -0,0 +1,54 @@
Add refclock and tcxoclock as clock providers in WiLink. These clocks
are not accesible outside the WiLink module, but they are registered
in the clock framework anyway. Only the WiLink chip consumes these
clocks.
In theory, the WiLink chip could be connected to external clocks
instead of using these internal clocks, so make the clock consumer
code generic enough. If external clocks are used, then the internal
clock device tree nodes are not necessary, but the external ones must
be specified.
Signed-off-by: Luciano Coelho <coelho@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
drivers/net/wireless/ti/wlcore/sdio.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -34,6 +34,7 @@
#include <linux/wl12xx.h>
#include <linux/pm_runtime.h>
#include <linux/printk.h>
+#include <linux/clk-provider.h>
#include "wlcore.h"
#include "wl12xx_80211.h"
@@ -214,10 +215,15 @@ static struct wl1271_if_operations sdio_
.set_block_size = wl1271_sdio_set_block_size,
};
+static const struct of_device_id wlcore_sdio_of_clk_match_table[] = {
+ { .compatible = "ti,wilink-clock" },
+};
+
static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
{
struct wl12xx_platform_data *pdata;
struct device_node *np = dev->of_node;
+ struct device_node *clock_node;
if (!np) {
np = of_find_matching_node(NULL, dev->driver->of_match_table);
@@ -241,6 +247,9 @@ static struct wl12xx_platform_data *wlco
goto out_free;
}
+ for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
+ of_fixed_clk_setup(clock_node);
+
goto out;
out_free:

@ -0,0 +1,94 @@
Read the clock nodes from the device tree and use them to set the
frequency for the refclock and the tcxo clock.
Also, call sdio_set_drvdata() earlier, so the glue is already set in
the driver data when we call wlcore_get_pdata_from_of() and we don't
need to pass it as a parameter.
Signed-off-by: Luciano Coelho <coelho@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
drivers/net/wireless/ti/wlcore/sdio.c | 36 +++++++++++++++++++++++++++++++++--
1 file changed, 34 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -53,6 +53,7 @@ static bool dump = false;
struct wl12xx_sdio_glue {
struct device *dev;
struct platform_device *core;
+ struct clk *refclock, *tcxoclock;
};
static const struct sdio_device_id wl1271_devices[] = {
@@ -224,6 +225,7 @@ static struct wl12xx_platform_data *wlco
struct wl12xx_platform_data *pdata;
struct device_node *np = dev->of_node;
struct device_node *clock_node;
+ struct wl12xx_sdio_glue *glue = sdio_get_drvdata(dev_to_sdio_func(dev));
if (!np) {
np = of_find_matching_node(NULL, dev->driver->of_match_table);
@@ -250,6 +252,26 @@ static struct wl12xx_platform_data *wlco
for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
of_fixed_clk_setup(clock_node);
+ /* TODO: make sure we have this when needed (ie. for WL6 and WL7) */
+ glue->refclock = of_clk_get_by_name(np, "refclock");
+ if (IS_ERR(glue->refclock)) {
+ dev_err(dev, "couldn't find refclock on the device tree\n");
+ glue->refclock = NULL;
+ } else {
+ clk_prepare_enable(glue->refclock);
+ pdata->ref_clock_freq = clk_get_rate(glue->refclock);
+ }
+
+ /* TODO: make sure we have this when needed (ie. for WL7) */
+ glue->tcxoclock = of_clk_get_by_name(np, "tcxoclock");
+ if (IS_ERR(glue->tcxoclock)) {
+ dev_err(dev, "couldn't find tcxoclock on the device tree\n");
+ glue->tcxoclock = NULL;
+ } else {
+ clk_prepare_enable(glue->tcxoclock);
+ pdata->ref_clock_freq = clk_get_rate(glue->tcxoclock);
+ }
+
goto out;
out_free:
@@ -294,6 +316,8 @@ static int wl1271_probe(struct sdio_func
/* Use block mode for transferring over one block size of data */
func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
+ sdio_set_drvdata(func, glue);
+
/* The pdata allocated here is freed when the device is freed,
* so we don't need an additional out label to free it in case
* of error further on.
@@ -319,8 +343,6 @@ static int wl1271_probe(struct sdio_func
if (mmcflags & MMC_PM_KEEP_POWER)
pdev_data->pwr_in_suspend = true;
- sdio_set_drvdata(func, glue);
-
/* Tell PM core that we don't need the card to be powered now */
pm_runtime_put_noidle(&func->dev);
@@ -387,6 +409,16 @@ static void wl1271_remove(struct sdio_fu
{
struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
+ if (glue->refclock) {
+ clk_disable_unprepare(glue->refclock);
+ clk_put(glue->refclock);
+ }
+
+ if (glue->tcxoclock) {
+ clk_disable_unprepare(glue->tcxoclock);
+ clk_put(glue->tcxoclock);
+ }
+
/* Undo decrement done above in wl1271_probe */
pm_runtime_get_noresume(&func->dev);

@ -0,0 +1,101 @@
The fref and the tcxo clocks settings are optional in some platforms.
WiLink8 doesn't need either, so we don't check the values. WiLink 6
only needs the fref clock, so we check that it is valid or return with
an error. WiLink7 needs both clocks, if either is not available we
return with an error.
Signed-off-by: Luciano Coelho <coelho@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
---
drivers/net/wireless/ti/wl12xx/main.c | 20 +++++++++++++++++---
drivers/net/wireless/ti/wlcore/sdio.c | 4 ----
2 files changed, 17 insertions(+), 7 deletions(-)
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -930,6 +930,11 @@ static int wl128x_boot_clk(struct wl1271
u16 sys_clk_cfg;
int ret;
+ if ((priv->ref_clock < 0) || (priv->tcxo_clock < 0)) {
+ wl1271_error("Missing fref and/or tcxo clock settings\n");
+ return -EINVAL;
+ }
+
/* For XTAL-only modes, FREF will be used after switching from TCXO */
if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
priv->ref_clock == WL12XX_REFCLOCK_38_XTAL) {
@@ -979,6 +984,11 @@ static int wl127x_boot_clk(struct wl1271
u32 clk;
int ret;
+ if (priv->ref_clock < 0) {
+ wl1271_error("Missing fref clock settings\n");
+ return -EINVAL;
+ }
+
if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION;
@@ -1768,7 +1778,7 @@ static int wl12xx_setup(struct wl1271 *w
wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, &wl12xx_ht_cap);
wl12xx_conf_init(wl);
- if (!fref_param) {
+ if (!fref_param && (pdata->ref_clock_freq > 0)) {
priv->ref_clock = wl12xx_get_clock_idx(wl12xx_refclock_table,
pdata->ref_clock_freq,
pdata->ref_clock_xtal);
@@ -1779,6 +1789,8 @@ static int wl12xx_setup(struct wl1271 *w
return priv->ref_clock;
}
+ } else if (!fref_param) {
+ priv->ref_clock = -EINVAL;
} else {
if (!strcmp(fref_param, "19.2"))
priv->ref_clock = WL12XX_REFCLOCK_19;
@@ -1796,7 +1808,7 @@ static int wl12xx_setup(struct wl1271 *w
wl1271_error("Invalid fref parameter %s", fref_param);
}
- if (!tcxo_param) {
+ if (!fref_param && (pdata->tcxo_clock_freq > 0)) {
priv->tcxo_clock = wl12xx_get_clock_idx(wl12xx_tcxoclock_table,
pdata->tcxo_clock_freq,
true);
@@ -1806,7 +1818,9 @@ static int wl12xx_setup(struct wl1271 *w
return priv->tcxo_clock;
}
- } else {
+ } else if (!fref_param) {
+ priv->tcxo_clock = -EINVAL;
+ }else {
if (!strcmp(tcxo_param, "19.2"))
priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2;
else if (!strcmp(tcxo_param, "26"))
--- a/drivers/net/wireless/ti/wlcore/sdio.c
+++ b/drivers/net/wireless/ti/wlcore/sdio.c
@@ -252,20 +252,16 @@ static struct wl12xx_platform_data *wlco
for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
of_fixed_clk_setup(clock_node);
- /* TODO: make sure we have this when needed (ie. for WL6 and WL7) */
glue->refclock = of_clk_get_by_name(np, "refclock");
if (IS_ERR(glue->refclock)) {
- dev_err(dev, "couldn't find refclock on the device tree\n");
glue->refclock = NULL;
} else {
clk_prepare_enable(glue->refclock);
pdata->ref_clock_freq = clk_get_rate(glue->refclock);
}
- /* TODO: make sure we have this when needed (ie. for WL7) */
glue->tcxoclock = of_clk_get_by_name(np, "tcxoclock");
if (IS_ERR(glue->tcxoclock)) {
- dev_err(dev, "couldn't find tcxoclock on the device tree\n");
glue->tcxoclock = NULL;
} else {
clk_prepare_enable(glue->tcxoclock);

@ -0,0 +1,102 @@
From patchwork Tue Jul 30 20:21:08 2013
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [v3] Documentation: dt: bindings: TI WiLink modules
From: Luciano Coelho <coelho@ti.com>
X-Patchwork-Id: 2835914
Message-Id: <1375215668-29171-1-git-send-email-coelho@ti.com>
To: <devicetree@vger.kernel.org>, <linux-doc@vger.kernel.org>
Cc: <mturquette@linaro.org>, <mark.rutland@arm.com>, <balbi@ti.com>,
<grant.likely@linaro.org>, <rob.herring@calxeda.com>,
<linux-kernel@vger.kernel.org>, <linux-omap@vger.kernel.org>,
<linux-wireless@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>, <tony@atomide.com>,
<nm@ti.com>, <laurent.pinchart@ideasonboard.com>
Date: Tue, 30 Jul 2013 23:21:08 +0300
Add device tree bindings documentation for the TI WiLink modules.
Currently only the WLAN part of the WiLink6, WiLink7 and WiLink8
modules is supported.
Signed-off-by: Luciano Coelho <coelho@ti.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
In v3, use IRQ_TYPE_LEVEL_HIGH in the example, as suggested by Laurent.
.../devicetree/bindings/net/wireless/ti-wilink.txt | 68 ++++++++++++++++++++++
1 file changed, 68 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/wireless/ti-wilink.txt
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/wireless/ti-wilink.txt
@@ -0,0 +1,68 @@
+TI WiLink Wireless Modules Device Tree Bindings
+===============================================
+
+The WiLink modules provide wireless connectivity, such as WLAN,
+Bluetooth, FM and NFC.
+
+There are several different modules available, which can be grouped by
+their generation: WiLink6, WiLink7 and WiLink8. WiLink4 is not
+currently supported with device tree.
+
+Currently, only the WLAN portion of the modules is supported with
+device tree.
+
+Required properties:
+--------------------
+
+- compatible: should be "ti,wilink6", "ti,wilink7" or "ti,wilink8"
+- interrupt-parent: the interrupt controller
+- interrupts: out-of-band WLAN interrupt
+ See the interrupt controller's bindings documentation for
+ detailed definition.
+
+Optional properties:
+--------------------
+
+- clocks: list of clocks needed by the chip as follows:
+
+ refclock: the internal WLAN reference clock frequency (required for
+ WiLink6 and WiLink7; not used for WiLink8).
+
+ tcxoclock: the internal WLAN TCXO clock frequency (required for
+ WiLink7 not used for WiLink6 and WiLink8).
+
+ The clocks must be defined and named accordingly. For example:
+
+ clocks = <&refclock>
+ clock-names = "refclock";
+
+ refclock: refclock {
+ compatible = "ti,wilink-clock";
+ #clock-cells = <0>;
+ clock-frequency = <38400000>;
+ };
+
+ Some modules that contain the WiLink chip provide clocks in the
+ module itself. In this case, we define a "ti,wilink-clock" as shown
+ above. But any other clock could in theory be used, so the proper
+ clock definition should be used.
+
+
+Example:
+--------
+
+Example definition that can be used in OMAP4 Panda:
+
+wlan {
+ compatible = "ti,wilink6";
+ interrupt-parent = <&gpio2>;
+ interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; /* gpio line 53 */
+ clocks = <&refclock>;
+ clock-names = "refclock";
+
+ refclock: refclock {
+ compatible = "ti,wilink-clock";
+ #clock-cells = <0>;
+ clock-frequency = <38400000>;
+ };
+};

@ -0,0 +1,70 @@
--- a/arch/arm/boot/dts/am335x-evmsk.dts
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -132,6 +132,39 @@
pinctrl-names = "default";
pinctrl-0 = <&gpio_keys_s0 &clkout2_pin>;
+ lcd_pins_s0: lcd_pins_s0 {
+ pinctrl-single,pins = <
+ 0x20 0x01 /* gpmc_ad8.lcd_data16, OUTPUT | MODE1 */
+ 0x24 0x01 /* gpmc_ad9.lcd_data17, OUTPUT | MODE1 */
+ 0x28 0x01 /* gpmc_ad10.lcd_data18, OUTPUT | MODE1 */
+ 0x2c 0x01 /* gpmc_ad11.lcd_data19, OUTPUT | MODE1 */
+ 0x30 0x01 /* gpmc_ad12.lcd_data20, OUTPUT | MODE1 */
+ 0x34 0x01 /* gpmc_ad13.lcd_data21, OUTPUT | MODE1 */
+ 0x38 0x01 /* gpmc_ad14.lcd_data22, OUTPUT | MODE1 */
+ 0x3c 0x01 /* gpmc_ad15.lcd_data23, OUTPUT | MODE1 */
+ 0xa0 0x00 /* lcd_data0.lcd_data0, OUTPUT | MODE0 */
+ 0xa4 0x00 /* lcd_data1.lcd_data1, OUTPUT | MODE0 */
+ 0xa8 0x00 /* lcd_data2.lcd_data2, OUTPUT | MODE0 */
+ 0xac 0x00 /* lcd_data3.lcd_data3, OUTPUT | MODE0 */
+ 0xb0 0x00 /* lcd_data4.lcd_data4, OUTPUT | MODE0 */
+ 0xb4 0x00 /* lcd_data5.lcd_data5, OUTPUT | MODE0 */
+ 0xb8 0x00 /* lcd_data6.lcd_data6, OUTPUT | MODE0 */
+ 0xbc 0x00 /* lcd_data7.lcd_data7, OUTPUT | MODE0 */
+ 0xc0 0x00 /* lcd_data8.lcd_data8, OUTPUT | MODE0 */
+ 0xc4 0x00 /* lcd_data9.lcd_data9, OUTPUT | MODE0 */
+ 0xc8 0x00 /* lcd_data10.lcd_data10, OUTPUT | MODE0 */
+ 0xcc 0x00 /* lcd_data11.lcd_data11, OUTPUT | MODE0 */
+ 0xd0 0x00 /* lcd_data12.lcd_data12, OUTPUT | MODE0 */
+ 0xd4 0x00 /* lcd_data13.lcd_data13, OUTPUT | MODE0 */
+ 0xd8 0x00 /* lcd_data14.lcd_data14, OUTPUT | MODE0 */
+ 0xdc 0x00 /* lcd_data15.lcd_data15, OUTPUT | MODE0 */
+ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OUTPUT | MODE0 */
+ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OUTPUT | MODE0 */
+ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OUTPUT | MODE0 */
+ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OUTPUT | MODE0 */
+ >;
+ };
+
user_leds_s0: user_leds_s0 {
pinctrl-single,pins = <
0x10 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad4.gpio1_4 */
@@ -486,6 +519,27 @@
rx-num-evt = <1>;
};
+&lcdc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pins_s0>;
+ status = "okay";
+ display-timings {
+ 480x272 {
+ hactive = <480>;
+ vactive = <272>;
+ hback-porch = <43>;
+ hfront-porch = <8>;
+ hsync-len = <4>;
+ vback-porch = <12>;
+ vfront-porch = <4>;
+ vsync-len = <10>;
+ clock-frequency = <9000000>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ };
+ };
+};
+
&tscadc {
status = "okay";
tsc {

@ -0,0 +1,86 @@
--- a/arch/arm/boot/dts/am335x-evmsk.dts
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -14,6 +14,7 @@
/dts-v1/;
#include "am33xx.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/pwm/pwm.h>
/ {
@@ -26,6 +27,20 @@
};
};
+ wlan {
+ compatible = "ti,wilink6";
+ interrupt-parent = <&gpio0>;
+ interrupts = <31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&refclock>;
+ clock-names = "refclock";
+
+ refclock: refclock {
+ compatible = "ti,wilink-clock";
+ #clock-cells = <0>;
+ clock-frequency = <38400000>;
+ };
+ };
+
memory {
device_type = "memory";
reg = <0x80000000 0x10000000>; /* 256 MB */
@@ -45,6 +60,16 @@
regulator-boot-on;
};
+ vmmc_wl: fixedregulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "vmmc-wl";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ gpio = <&gpio1 29 0>;
+ startup-delay-us = <70000>;
+ enable-active-high;
+ };
+
leds {
pinctrl-names = "default";
pinctrl-0 = <&user_leds_s0>;
@@ -297,6 +322,20 @@
0x144 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
>;
};
+
+ wilink_pins: pinmux_wilink_pins {
+ pinctrl-single,pins = <
+ 0x74 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_31 */
+ 0x7c (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_csn0.gpio1_29 */
+ 0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+ 0x84 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+ 0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+ 0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+ 0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+ 0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+ >;
+ };
+
};
&uart0 {
@@ -503,6 +542,16 @@
ti,no-reset-on-init;
};
+&mmc2 {
+ status = "okay";
+ vmmc-supply = <&vmmc_wl>;
+ bus-width = <4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&wilink_pins>;
+ ti,non-removable;
+ keep-power-in-suspend;
+};
+
&mcasp1 {
pinctrl-names = "default";
pinctrl-0 = <&mcasp1_pins>;
Loading…
Cancel
Save