add 3.13 support
Signed-off-by: Imre Kaloz <kaloz@openwrt.org> SVN-Revision: 39508
This commit is contained in:
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…
Reference in New Issue
Block a user