From b70c5b745ef78dd7e9c931d9833a50fb8c3a0e3c Mon Sep 17 00:00:00 2001 From: Sudhir Vyas Date: Thu, 26 Jul 2012 11:12:33 +0530 Subject: media: video: tegra: Focuser range tuning support * Add support for focuser range tuning. * Fix focuser position move programming. * Optimize focuser read/write. * Optimize focuser power consumption. * Fix foucser sound issue while capture. * Improve overall focuser performance. Bug 1013062 Bug 1018136 Bug 978541 Change-Id: I57fc0566a3a43468ce9a07319014cf3c038ed1e1 Signed-off-by: Sudhir Vyas Reviewed-on: http://git-master/r/120307 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Prayas Mohanty Reviewed-by: Sachin Nikam --- drivers/media/video/tegra/ad5816.c | 135 +++++++++++++++++++++++++++---------- 1 file changed, 99 insertions(+), 36 deletions(-) diff --git a/drivers/media/video/tegra/ad5816.c b/drivers/media/video/tegra/ad5816.c index 9e31acc33cc3..6fdb9f184614 100644 --- a/drivers/media/video/tegra/ad5816.c +++ b/drivers/media/video/tegra/ad5816.c @@ -96,12 +96,14 @@ #define AD5816_ID 0x04 #define AD5816_FOCAL_LENGTH (4.570f) #define AD5816_FNUMBER (2.8f) -#define AD5816_ACTUATOR_RANGE 680 -#define AD5816_SETTLETIME 110 +#define AD5816_SLEW_RATE 1 +#define AD5816_ACTUATOR_RANGE 1023 +#define AD5816_SETTLETIME 50 #define AD5816_FOCUS_MACRO 810 #define AD5816_FOCUS_INFINITY 50 /* Exact value needs to be decided */ -#define AD5816_POS_LOW_DEFAULT 220 -#define AD5816_POS_HIGH_DEFAULT 900 +#define AD5816_POS_LOW_DEFAULT 0 +#define AD5816_POS_HIGH_DEFAULT 1023 +#define AD5816_POS_CLAMP 0x03ff /* Need to decide exact value of VCM_THRESHOLD and its use */ /* define AD5816_VCM_THRESHOLD 20 */ @@ -140,6 +142,7 @@ struct ad5816_info { struct ad5816_info *s_info; struct nvc_focus_nvc nvc; struct nvc_focus_cap cap; + struct nv_focuser_config nv_config; struct ad5816_pdata_info config; }; @@ -154,10 +157,12 @@ static struct ad5816_pdata_info ad5816_default_info = { static struct nvc_focus_cap ad5816_default_cap = { .version = NVC_FOCUS_CAP_VER2, + .slew_rate = AD5816_SLEW_RATE, .actuator_range = AD5816_ACTUATOR_RANGE, .settle_time = AD5816_SETTLETIME, .focus_macro = AD5816_FOCUS_MACRO, .focus_infinity = AD5816_FOCUS_INFINITY, + .focus_hyper = AD5816_FOCUS_INFINITY, }; static struct nvc_focus_nvc ad5816_default_nvc = { @@ -637,28 +642,76 @@ static int ad5816_position_rd(struct ad5816_info *info, unsigned *position) int err = 0; err = ad5816_i2c_rd8(info, 0, VCM_CODE_MSB, &t1); - pos = t1 & 0x03; + pos = t1; err = ad5816_i2c_rd8(info, 0, VCM_CODE_LSB, &t1); pos = (pos << 8) | t1; - if(pos) - *position = pos - info->config.pos_low; - else - *position = info->config.pos_low; - return 0; + if (pos < info->config.pos_low) + pos = info->config.pos_low; + else if (pos > info->config.pos_high) + pos = info->config.pos_high; + + *position = pos; + + return err; } -static int ad5816_position_wr(struct ad5816_info *info, unsigned position) +static int ad5816_position_wr(struct ad5816_info *info, s32 position) { - u16 data; + s16 data; - position = position + info->config.pos_low; - if(position > info->config.pos_high) - position = info->config.pos_high; + ad5816_set_arc_mode(info); - data = position & 0x03ff; + if (position > info->config.pos_high) + return -EINVAL; + data = position & AD5816_POS_CLAMP; return ad5816_i2c_wr16(info, VCM_CODE_MSB, data); + +} + +static void ad5816_get_focuser_capabilities(struct ad5816_info *info) +{ + memset(&info->nv_config, 0, sizeof(info->nv_config)); + + info->nv_config.focal_length = info->nvc.focal_length; + info->nv_config.fnumber = info->nvc.fnumber; + info->nv_config.max_aperture = info->nvc.fnumber; + info->nv_config.range_ends_reversed = 0; + info->nv_config.settle_time = info->cap.settle_time; + + info->nv_config.pos_working_low = AF_POS_INVALID_VALUE; + info->nv_config.pos_working_high = AF_POS_INVALID_VALUE; + + info->nv_config.pos_actual_low = info->config.pos_low; + info->nv_config.pos_actual_high = info->config.pos_high; + + info->nv_config.slew_rate = info->cap.slew_rate; + info->nv_config.circle_of_confusion = -1; + info->nv_config.num_focuser_sets = 1; + info->nv_config.focuser_set[0].macro = info->cap.focus_macro; + info->nv_config.focuser_set[0].hyper = info->cap.focus_hyper; + info->nv_config.focuser_set[0].inf = info->cap.focus_infinity; + info->nv_config.focuser_set[0].settle_time = info->cap.settle_time; +} + +static int ad5816_set_focuser_capabilities(struct ad5816_info *info, + struct nvc_param *params) +{ + if (copy_from_user(&info->nv_config, (const void __user *)params->p_value, + sizeof(struct nv_focuser_config))) { + dev_err(&info->i2c_client->dev, "%s Error: copy_from_user bytes %d\n", + __func__, sizeof(struct nv_focuser_config)); + return -EFAULT; + } + + /* set pre-set value, as currently ODM sets incorrect value */ + info->cap.settle_time = AD5816_SETTLETIME; + + dev_dbg(&info->i2c_client->dev, "%s: copy_from_user bytes %d info->cap.settle_time %d\n", + __func__, sizeof(struct nv_focuser_config), info->cap.settle_time); + + return 0; } static int ad5816_param_rd(struct ad5816_info *info, unsigned long arg) @@ -706,13 +759,10 @@ static int ad5816_param_rd(struct ad5816_info *info, unsigned long arg) __func__, info->nvc.fnumber); break; case NVC_PARAM_CAPS: - data_ptr = &info->cap; - /* there are different sizes depending on the version */ /* send back just what's requested or our max size */ - if (params.sizeofvalue < sizeof(info->cap)) - data_size = params.sizeofvalue; - else - data_size = sizeof(info->cap); + ad5816_get_focuser_capabilities(info); + data_ptr = &info->nv_config; + data_size = sizeof(info->nv_config); dev_err(&info->i2c_client->dev, "%s CAPS\n", __func__); break; case NVC_PARAM_STS: @@ -745,16 +795,16 @@ static int ad5816_param_rd(struct ad5816_info *info, unsigned long arg) } static int ad5816_param_wr_s(struct ad5816_info *info, - struct nvc_param *params, u32 u32val) + struct nvc_param *params, s32 s32val) { int err = 0; switch (params->param) { case NVC_PARAM_LOCUS: - dev_dbg(&info->i2c_client->dev, "%s LOCUS: %u\n", __func__, u32val); - err = ad5816_position_wr(info, u32val); + dev_dbg(&info->i2c_client->dev, "%s LOCUS: %d\n", __func__, s32val); + err = ad5816_position_wr(info, s32val); return err; case NVC_PARAM_RESET: - err = ad5816_reset(info, u32val); + err = ad5816_reset(info, s32val); dev_dbg(&info->i2c_client->dev, "%s RESET: %d\n", __func__, err); return err; case NVC_PARAM_SELF_TEST: @@ -773,7 +823,7 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg) { struct nvc_param params; u8 u8val; - u32 u32val; + s32 s32val; int err = 0; if (copy_from_user(¶ms, (const void __user *)arg, sizeof(struct nvc_param))) { @@ -781,11 +831,11 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg) __func__, __LINE__); return -EFAULT; } - if (copy_from_user(&u32val, (const void __user *)params.p_value, sizeof(u32val))) { + if (copy_from_user(&s32val, (const void __user *)params.p_value, sizeof(s32val))) { dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n", __func__, __LINE__); return -EFAULT; } - u8val = (u8)u32val; + u8val = (u8)s32val; /* parameters independent of sync mode */ switch (params.param) { case NVC_PARAM_STEREO: @@ -833,7 +883,7 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg) /* sync power */ info->s_info->pwr_api = info->pwr_api; /* move slave lens to master position */ - err = ad5816_position_wr(info->s_info, info->pos); + err = ad5816_position_wr(info->s_info, (s32)info->pos); if (!err) { info->s_mode = u8val; info->s_info->s_mode = u8val; @@ -854,20 +904,29 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg) if (info->pdata->cfg & NVC_CFG_NOERR) return 0; return err; + + case NVC_PARAM_CAPS: + if (ad5816_set_focuser_capabilities(info, ¶ms)) { + dev_err(&info->i2c_client->dev, "%s: Error: copy_from_user bytes %d\n", + __func__, params.sizeofvalue); + return -EFAULT; + } + return 0; + default: /* parameters dependent on sync mode */ switch (info->s_mode) { case NVC_SYNC_OFF: case NVC_SYNC_MASTER: - return ad5816_param_wr_s(info, ¶ms, u32val); + return ad5816_param_wr_s(info, ¶ms, s32val); case NVC_SYNC_SLAVE: - return ad5816_param_wr_s(info->s_info, ¶ms, u32val); + return ad5816_param_wr_s(info->s_info, ¶ms, s32val); case NVC_SYNC_STEREO: - err = ad5816_param_wr_s(info, ¶ms, u32val); + err = ad5816_param_wr_s(info, ¶ms, s32val); if (!(info->pdata->cfg & NVC_CFG_SYNC_I2C_MUX)) err |= ad5816_param_wr_s(info->s_info, ¶ms, - u32val); + s32val); return err; default: dev_err(&info->i2c_client->dev, "%s %d internal err\n", @@ -886,10 +945,14 @@ static long ad5816_ioctl(struct file *file, int err = 0; switch (cmd) { case NVC_IOCTL_PARAM_WR: + ad5816_pm_dev_wr(info, NVC_PWR_ON); err = ad5816_param_wr(info, arg); + ad5816_pm_dev_wr(info, NVC_PWR_OFF); return err; case NVC_IOCTL_PARAM_RD: + ad5816_pm_dev_wr(info, NVC_PWR_ON); err = ad5816_param_rd(info, arg); + ad5816_pm_dev_wr(info, NVC_PWR_OFF); return err; case NVC_IOCTL_PWR_WR: /* This is a Guaranteed Level of Service (GLOS) call */ @@ -1032,8 +1095,8 @@ static int ad5816_open(struct inode *inode, struct file *file) } file->private_data = info; ad5816_pm_dev_wr(info, NVC_PWR_ON); - /* set ARC Mode to ensure faster focus */ - ad5816_set_arc_mode(info); + ad5816_position_wr(info, info->cap.focus_infinity); + ad5816_pm_dev_wr(info, NVC_PWR_OFF); dev_dbg(&info->i2c_client->dev, "%s\n", __func__); return 0; -- cgit v1.2.3 From bd6c8e078137f35a5afb29d7c36d9fc8da0ac16e Mon Sep 17 00:00:00 2001 From: Charlie Huang Date: Tue, 31 Jul 2012 18:41:38 -0700 Subject: media: tegra: ov9726: add group hold ioctl To make AE transition smoother, the group hold enable/disable actions should be added before and after set gain/frame length/coarse time. bug 1025995 Change-Id: I578b33167e50f59d0d9a88a0e16fac0c5425b6b6 Signed-off-by: Charlie Huang Reviewed-on: http://git-master/r/120406 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Manish Tuteja --- drivers/media/video/tegra/ov9726.c | 57 ++++++++++++++++++++++++++++++++++---- include/media/ov9726.h | 12 +++++++- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/tegra/ov9726.c b/drivers/media/video/tegra/ov9726.c index 378d46fabedf..45d6c85f0925 100644 --- a/drivers/media/video/tegra/ov9726.c +++ b/drivers/media/video/tegra/ov9726.c @@ -38,6 +38,7 @@ struct ov9726_devinfo { struct ov9726_power_rail power_rail; atomic_t in_use; __u32 mode; + struct ov9726_reg grphold_temp[10]; }; static struct ov9726_reg mode_1280x720[] = { @@ -603,6 +604,46 @@ static int ov9726_set_gain(struct i2c_client *i2c_client, u16 gain) return ret; } +static int ov9726_set_group_hold(struct ov9726_devinfo *dev, + struct ov9726_ae *ae) +{ +#define OV9726_REG_PUSH8(p, a, v) \ + do { \ + (p)->addr = (a); \ + (p)->val = (v); \ + (p)++; \ + } while (0) + +#define OV9726_REG_PUSH16(ptr, addr, val) do { \ + OV9726_REG_PUSH8(ptr, (addr), (val) >> 8); \ + OV9726_REG_PUSH8(ptr, (addr) + 1, (val) & 0xff); \ + } while (0) + + struct ov9726_reg *gptr = &dev->grphold_temp[0]; + + if (!ae->gain_enable && + !ae->coarse_time_enable && + !ae->frame_length_enable) + return 0; + + OV9726_REG_PUSH8(gptr, 0x0104, 0x01); + if (ae->gain_enable) + OV9726_REG_PUSH16(gptr, + OV9726_REG_GAIN_HI, ae->gain); + if (ae->coarse_time_enable) + OV9726_REG_PUSH16(gptr, + OV9726_REG_COARSE_TIME_HI, ae->coarse_time); + if (ae->frame_length_enable) { + OV9726_REG_PUSH16(gptr, + OV9726_REG_FRAME_LENGTH_HI, ae->frame_length); + } + OV9726_REG_PUSH8(gptr, 0x0104, 0x00); + OV9726_REG_PUSH8(gptr, OV9726_TABLE_END, 0x00); + + return ov9726_write_table(dev->i2c_client, + dev->grphold_temp, NULL, 0); +} + static int ov9726_get_status(struct i2c_client *i2c_client, u8 *status) { int err; @@ -681,19 +722,26 @@ ov9726_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } - case OV9726_IOCTL_SET_FRAME_LENGTH: err = ov9726_set_frame_length(i2c_client, (u32)arg); break; - case OV9726_IOCTL_SET_COARSE_TIME: err = ov9726_set_coarse_time(i2c_client, (u32)arg); break; - case OV9726_IOCTL_SET_GAIN: err = ov9726_set_gain(i2c_client, (u16)arg); break; - + case OV9726_IOCTL_SET_GROUP_HOLD: + { + struct ov9726_ae ae; + if (copy_from_user(&ae, + (const void __user *)arg, sizeof(struct ov9726_ae))) { + pr_info("%s %d\n", __func__, __LINE__); + return -EFAULT; + } + err = ov9726_set_group_hold(dev, &ae); + break; + } case OV9726_IOCTL_GET_STATUS: { u8 status; @@ -706,7 +754,6 @@ ov9726_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } break; } - default: err = -EINVAL; break; diff --git a/include/media/ov9726.h b/include/media/ov9726.h index b1e759ba583c..fb9995b4a8de 100644 --- a/include/media/ov9726.h +++ b/include/media/ov9726.h @@ -19,7 +19,8 @@ #define OV9726_IOCTL_SET_FRAME_LENGTH _IOW('o', 2, __u32) #define OV9726_IOCTL_SET_COARSE_TIME _IOW('o', 3, __u32) #define OV9726_IOCTL_SET_GAIN _IOW('o', 4, __u16) -#define OV9726_IOCTL_GET_STATUS _IOR('o', 5, __u8) +#define OV9726_IOCTL_GET_STATUS _IOR('o', 5, __u8) +#define OV9726_IOCTL_SET_GROUP_HOLD _IOW('o', 6, struct ov9726_ae) struct ov9726_mode { int mode_id; @@ -30,6 +31,15 @@ struct ov9726_mode { __u16 gain; }; +struct ov9726_ae { + __u32 frame_length; + __u32 coarse_time; + __u16 gain; + __u8 frame_length_enable; + __u8 coarse_time_enable; + __u8 gain_enable; +}; + struct ov9726_reg { __u16 addr; __u16 val; -- cgit v1.2.3 From cef6290dc6b1771c1cfee5163e6db3ba32d137a9 Mon Sep 17 00:00:00 2001 From: naveenk Date: Thu, 26 Jul 2012 14:26:55 +0530 Subject: Revert "Modified the hot-plug governor down_delay to be 500ms instead of 2s" This is required as it is causing performance regression for SD, eMMC and USB Bug 1006055 Bug 1021754 This reverts commit 2f5a59bbeee465fb33d012b8dc714fa0c1637209. Signed-off-by: naveen kumar arepalli (cherry picked from commit 6ba0905d5dbd55d2604f0db2c597826d4354d20a) Change-Id: I09203754db840428dc9df2b9eff9b5d9b88a7ffb Reviewed-on: http://git-master/r/120261 Reviewed-by: Rohan Somvanshi Tested-by: Rohan Somvanshi --- arch/arm/mach-tegra/cpu-tegra3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-tegra/cpu-tegra3.c b/arch/arm/mach-tegra/cpu-tegra3.c index fc96dd6e14b2..ec63622b4705 100644 --- a/arch/arm/mach-tegra/cpu-tegra3.c +++ b/arch/arm/mach-tegra/cpu-tegra3.c @@ -41,7 +41,7 @@ #define INITIAL_STATE TEGRA_HP_DISABLED #define UP2G0_DELAY_MS 70 #define UP2Gn_DELAY_MS 100 -#define DOWN_DELAY_MS 500 +#define DOWN_DELAY_MS 2000 static struct mutex *tegra3_cpu_lock; -- cgit v1.2.3 From d2553b1e4232689ad0b13a2c20da6a4e2ebf8677 Mon Sep 17 00:00:00 2001 From: Rakesh Bodla Date: Thu, 2 Aug 2012 11:40:48 +0530 Subject: arm: tegra: usb_phy: use devm_kfree to free memory devm_kfree() should be used to free memory allocated by devm_kzalloc() Memory allocated with devm_kzalloc is automatically freed on driver detach. Kernel crash will be observed if it is freed with kfree(). Bug 1027472 Change-Id: I48533d520b5c2669ca473c700eec689e2ddcbb90 Signed-off-by: Rakesh Bodla Reviewed-on: http://git-master/r/120273 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Venkat Moganty --- arch/arm/mach-tegra/usb_phy.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c index aed8ec2bf9d8..78f60e1aafb1 100644 --- a/arch/arm/mach-tegra/usb_phy.c +++ b/arch/arm/mach-tegra/usb_phy.c @@ -239,20 +239,23 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev) if (!pdata) { dev_err(&pdev->dev, "inst:[%d] Platform data missing\n", pdev->id); - return ERR_PTR(-EINVAL); + err = -EINVAL; + goto fail_inval; } phy = devm_kzalloc(&pdev->dev, sizeof(struct tegra_usb_phy), GFP_KERNEL); if (!phy) { ERR("inst:[%d] malloc usb phy failed\n", pdev->id); - return ERR_PTR(-ENOMEM); + err = -ENOMEM; + goto fail_nomem; } phy->pdata = devm_kzalloc(&pdev->dev, plat_data_size, GFP_KERNEL); if (!phy->pdata) { ERR("inst:[%d] malloc usb phy pdata failed\n", pdev->id); - kfree(phy); - return ERR_PTR(-ENOMEM); + devm_kfree(&pdev->dev, phy); + err = -ENOMEM; + goto fail_nomem; } memcpy(phy->pdata, pdata, plat_data_size); @@ -281,6 +284,8 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev) ERR("inst:[%d] couldn't get regulator avdd_usb: %ld\n", phy->inst, PTR_ERR(phy->vdd_reg)); phy->vdd_reg = NULL; + err = PTR_ERR(phy->vdd_reg); + goto fail_io; } err = tegra_usb_phy_get_clocks(phy); @@ -377,8 +382,11 @@ fail_clk: regulator_put(phy->vdd_reg); iounmap(phy->regs); fail_io: - kfree(phy); + devm_kfree(&pdev->dev, phy->pdata); + devm_kfree(&pdev->dev, phy); +fail_nomem: +fail_inval: return ERR_PTR(err); } @@ -419,8 +427,8 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy) tegra_usb_phy_release_clocks(phy); - kfree(phy->pdata); - kfree(phy); + devm_kfree(&phy->pdev->dev, phy->pdata); + devm_kfree(&phy->pdev->dev, phy); } irqreturn_t tegra_usb_phy_irq(struct tegra_usb_phy *phy) -- cgit v1.2.3 From 7fb0b48453b7c85b7cbcc7e982edcb9e9a4a0196 Mon Sep 17 00:00:00 2001 From: Rakesh Bodla Date: Thu, 2 Aug 2012 14:24:39 +0530 Subject: USB: gadget: f_accessory: change prototype of create_bluk_endpoints Changing prototype of create_bluk_endpoints since function can called during runtime. Bug 1026235 Change-Id: Ic80eaeb374fb3863cd16be3234653eda80c5eff2 Signed-off-by: Rakesh Bodla Reviewed-on: http://git-master/r/120308 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Venkat Moganty --- drivers/usb/gadget/f_accessory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c index ae65faaf3d77..58c653fe50e4 100644 --- a/drivers/usb/gadget/f_accessory.c +++ b/drivers/usb/gadget/f_accessory.c @@ -296,7 +296,7 @@ static void acc_complete_set_string(struct usb_ep *ep, struct usb_request *req) } } -static int __init create_bulk_endpoints(struct acc_dev *dev, +static int create_bulk_endpoints(struct acc_dev *dev, struct usb_endpoint_descriptor *in_desc, struct usb_endpoint_descriptor *out_desc) { -- cgit v1.2.3 From 84fe6bcbf169c5b653f17c6df83e82521b32f380 Mon Sep 17 00:00:00 2001 From: Rakesh Bodla Date: Thu, 2 Aug 2012 18:03:57 +0530 Subject: arm: configs: tegra3: Enable boost cpu frequency Enabling boost CPU frequency for tegra gadget to improve USB performance. Bug 1020850 Change-Id: I3ef7cbc4e023ffe1443fc2e662550963f34d1daf Signed-off-by: Rakesh Bodla Reviewed-on: http://git-master/r/120353 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Rama Kandhala Reviewed-by: Venkat Moganty --- arch/arm/configs/tegra3_android_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/tegra3_android_defconfig b/arch/arm/configs/tegra3_android_defconfig index 825b6e3b00c1..7a4064c52840 100644 --- a/arch/arm/configs/tegra3_android_defconfig +++ b/arch/arm/configs/tegra3_android_defconfig @@ -34,6 +34,7 @@ CONFIG_TEGRA_EMC_SCALING_ENABLE=y CONFIG_TEGRA_CLOCK_DEBUG_WRITE=y CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND=y CONFIG_USB_HOTPLUG=y +CONFIG_TEGRA_GADGET_BOOST_CPU_FREQ=800 CONFIG_TEGRA_DYNAMIC_PWRDET=y CONFIG_TEGRA_USB_MODEM_POWER=y CONFIG_TEGRA_BB_XMM_POWER=y -- cgit v1.2.3 From 1e268b937047dd401a584ab35443baf795716deb Mon Sep 17 00:00:00 2001 From: Ilan Aelion Date: Thu, 2 Aug 2012 11:01:02 -0600 Subject: misc: tegra-throughput: prevent division by 0 Prevent division by 0 on subsequent flip notifications at an interval shorter than 1 micro-second. Bug 1027664 Change-Id: I6e2f886721216fc2479adc1a24504b707c7ebe45 Signed-off-by: Ilan Aelion Reviewed-on: http://git-master/r/120397 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Sang-Hun Lee Reviewed-by: Jon Mayo --- drivers/misc/tegra-throughput.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/misc/tegra-throughput.c b/drivers/misc/tegra-throughput.c index b2375d2913bf..77eb7c31ed36 100644 --- a/drivers/misc/tegra-throughput.c +++ b/drivers/misc/tegra-throughput.c @@ -57,6 +57,9 @@ static int throughput_flip_notifier(struct notifier_block *nb, else last_frame_time = (unsigned short) timediff; + if (last_frame_time == 0) + return NOTIFY_DONE; + throughput_hint = ((int) target_frame_time * 100)/last_frame_time; -- cgit v1.2.3 From 51f746421b73f8f378bd7908b35fd6c79687e239 Mon Sep 17 00:00:00 2001 From: Matt Wagner Date: Thu, 2 Aug 2012 15:49:50 -0700 Subject: video: tegra: hdcp: Fix Locking Issue Locking in nvhdcp was set up in such a way that we couldn't change the state of the HDMI plug while negotiating the HDCP connection. Another lock was added that is only taken when the state of the plug or hdcp session are changed. This enables correct failure if the plug is removed during negotiation. Bug 1024031 Change-Id: Ia9e49fcd7b996d2ce5338a72ce4e66c1ab40e1bb Reviewed-on: http://git-master/r/120546 Reviewed-by: Automatic_Commit_Validation_User Tested-by: Matt Wagner Reviewed-by: Jon Mayo --- drivers/video/tegra/dc/nvhdcp.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/video/tegra/dc/nvhdcp.c b/drivers/video/tegra/dc/nvhdcp.c index 3566e2bd33b5..b509a6c78499 100644 --- a/drivers/video/tegra/dc/nvhdcp.c +++ b/drivers/video/tegra/dc/nvhdcp.c @@ -78,6 +78,7 @@ struct tegra_nvhdcp { struct tegra_dc_hdmi_data *hdmi; struct workqueue_struct *downstream_wq; struct mutex lock; + struct mutex state_lock; struct miscdevice miscdev; char name[12]; unsigned id; @@ -980,7 +981,9 @@ static void nvhdcp_downstream_worker(struct work_struct *work) nvhdcp_vdbg("CRYPT enabled\n"); + mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_LINK_VERIFY; + mutex_unlock(&nvhdcp->state_lock); nvhdcp_info("link verified!\n"); while (1) { @@ -1007,30 +1010,39 @@ failure: if(nvhdcp->fail_count > 5) { nvhdcp_err("nvhdcp failure - too many failures, giving up!\n"); } else { - nvhdcp_err("nvhdcp failure - renegotiating in 1 second\n"); - if (!nvhdcp_is_plugged(nvhdcp)) + if (!nvhdcp_is_plugged(nvhdcp)) { + nvhdcp_err("nvhdcp failure\n"); goto lost_hdmi; + } + nvhdcp_err("nvhdcp failure - renegotiating in 1 second\n"); queue_delayed_work(nvhdcp->downstream_wq, &nvhdcp->work, msecs_to_jiffies(1000)); } lost_hdmi: + mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_UNAUTHENTICATED; + mutex_unlock(&nvhdcp->state_lock); hdcp_ctrl_run(hdmi, 0); err: mutex_unlock(&nvhdcp->lock); return; disable: + mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_OFF; nvhdcp_set_plugged(nvhdcp, false); + mutex_unlock(&nvhdcp->state_lock); mutex_unlock(&nvhdcp->lock); return; } static int tegra_nvhdcp_on(struct tegra_nvhdcp *nvhdcp) { + mutex_lock(&nvhdcp->state_lock); + nvhdcp_set_plugged(nvhdcp, true); nvhdcp->state = STATE_UNAUTHENTICATED; + mutex_unlock(&nvhdcp->state_lock); if (nvhdcp_is_plugged(nvhdcp)) { nvhdcp->fail_count = 0; queue_delayed_work(nvhdcp->downstream_wq, &nvhdcp->work, @@ -1041,10 +1053,10 @@ static int tegra_nvhdcp_on(struct tegra_nvhdcp *nvhdcp) static int tegra_nvhdcp_off(struct tegra_nvhdcp *nvhdcp) { - mutex_lock(&nvhdcp->lock); + mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_OFF; nvhdcp_set_plugged(nvhdcp, false); - mutex_unlock(&nvhdcp->lock); + mutex_unlock(&nvhdcp->state_lock); wake_up_interruptible(&wq_worker); flush_workqueue(nvhdcp->downstream_wq); return 0; @@ -1055,7 +1067,6 @@ void tegra_nvhdcp_set_plug(struct tegra_nvhdcp *nvhdcp, bool hpd) nvhdcp_debug("hdmi hotplug detected (hpd = %d)\n", hpd); if (hpd) { - nvhdcp_set_plugged(nvhdcp, true); tegra_nvhdcp_on(nvhdcp); } else { tegra_nvhdcp_off(nvhdcp); @@ -1080,9 +1091,9 @@ int tegra_nvhdcp_set_policy(struct tegra_nvhdcp *nvhdcp, int pol) static int tegra_nvhdcp_renegotiate(struct tegra_nvhdcp *nvhdcp) { - mutex_lock(&nvhdcp->lock); + mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_RENEGOTIATE; - mutex_unlock(&nvhdcp->lock); + mutex_unlock(&nvhdcp->state_lock); tegra_nvhdcp_on(nvhdcp); return 0; } @@ -1201,6 +1212,7 @@ struct tegra_nvhdcp *tegra_nvhdcp_create(struct tegra_dc_hdmi_data *hdmi, snprintf(nvhdcp->name, sizeof(nvhdcp->name), "nvhdcp%u", id); nvhdcp->hdmi = hdmi; mutex_init(&nvhdcp->lock); + mutex_init(&nvhdcp->state_lock); strlcpy(nvhdcp->info.type, nvhdcp->name, sizeof(nvhdcp->info.type)); nvhdcp->bus = bus; @@ -1224,7 +1236,9 @@ struct tegra_nvhdcp *tegra_nvhdcp_create(struct tegra_dc_hdmi_data *hdmi, goto free_nvhdcp; } + mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_UNAUTHENTICATED; + mutex_unlock(&nvhdcp->state_lock); nvhdcp->downstream_wq = create_singlethread_workqueue(nvhdcp->name); INIT_DELAYED_WORK(&nvhdcp->work, nvhdcp_downstream_worker); -- cgit v1.2.3 From c900adb3364341265d0f9e5cbd9b3969af3d504b Mon Sep 17 00:00:00 2001 From: Xiao Bo Zhao Date: Fri, 29 Jun 2012 12:46:11 -0700 Subject: ARM: Tegra: Added support to run at two frequency modes CPU clock is now capped at an normal frequency that is below its maximum and allowed to run at a high frequency only once within a period of time. By default the delay is set to 5*DOWN_DELAY, allowing a maximum of 20% high frequency time. Sysfs knobs were also added that allows userspace tuning Bug 1003531 Change-Id: Ic9be46cdae099771950f14e8a6ca79eeab7adbba Signed-off-by: Xiao Bo Zhao (cherry picked from commit 779a488fb850eb452a7b43788b87edb4186b69b9) Reviewed-on: http://git-master/r/121042 Reviewed-by: Ryan Wong Reviewed-by: Automatic_Commit_Validation_User --- drivers/cpufreq/cpufreq_interactive.c | 44 +++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index 798930ffe1f4..20a9b6d22156 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -43,6 +43,7 @@ struct cpufreq_interactive_cpuinfo { u64 freq_change_time; u64 freq_change_time_in_idle; u64 freq_change_time_in_iowait; + u64 last_high_freq_time; struct cpufreq_policy *policy; struct cpufreq_frequency_table *freq_table; unsigned int target_freq; @@ -92,6 +93,24 @@ static unsigned long min_sample_time; #define DEFAULT_TIMER_RATE 20000; static unsigned long timer_rate; +/* + * The minimum delay before frequency is allowed to raise over normal rate. + * Since it must remain at high frequency for a minimum of MIN_SAMPLE_TIME + * once it rises, setting this delay to a multiple of MIN_SAMPLE_TIME + * becomes the best way to enforce a square wave. + * e.g. 5*MIN_SAMPLE_TIME = 20% high freq duty cycle + */ +#define DEFAULT_HIGH_FREQ_MIN_DELAY 5*DEFAULT_MIN_SAMPLE_TIME +static unsigned long high_freq_min_delay; + +/* + * The maximum frequency CPUs are allowed to run normally + * 0 if disabled + */ +#define DEFAULT_MAX_NORMAL_FREQ 0 +static unsigned long max_normal_freq; + + /* Defines to control mid-range frequencies */ #define DEFAULT_MID_RANGE_GO_MAXSPEED_LOAD 95 @@ -274,6 +293,20 @@ static void cpufreq_interactive_timer(unsigned long data) goto rearm; } + /* + * Can only overclock if the delay is satisfy. Otherwise, cap it to + * maximum allowed normal frequency + */ + if (max_normal_freq && (new_freq > max_normal_freq)) { + if (cputime64_sub(pcpu->timer_run_time, pcpu->last_high_freq_time) + < high_freq_min_delay) { + new_freq = max_normal_freq; + } + else { + pcpu->last_high_freq_time = pcpu->timer_run_time; + } + } + if (new_freq < pcpu->target_freq) { pcpu->target_freq = new_freq; spin_lock_irqsave(&down_cpumask_lock, flags); @@ -552,7 +585,9 @@ DECL_CPUFREQ_INTERACTIVE_ATTR(max_boost) DECL_CPUFREQ_INTERACTIVE_ATTR(midrange_max_boost) DECL_CPUFREQ_INTERACTIVE_ATTR(sustain_load) DECL_CPUFREQ_INTERACTIVE_ATTR(min_sample_time) -DECL_CPUFREQ_INTERACTIVE_ATTR(timer_rate); +DECL_CPUFREQ_INTERACTIVE_ATTR(timer_rate) +DECL_CPUFREQ_INTERACTIVE_ATTR(high_freq_min_delay) +DECL_CPUFREQ_INTERACTIVE_ATTR(max_normal_freq) #undef DECL_CPUFREQ_INTERACTIVE_ATTR @@ -567,6 +602,8 @@ static struct attribute *interactive_attributes[] = { &sustain_load_attr.attr, &min_sample_time_attr.attr, &timer_rate_attr.attr, + &high_freq_min_delay_attr.attr, + &max_normal_freq_attr.attr, NULL, }; @@ -604,7 +641,8 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, pcpu->freq_change_time_in_iowait = get_cpu_iowait_time(j, NULL); pcpu->time_in_iowait = pcpu->freq_change_time_in_iowait; - + if (!pcpu->last_high_freq_time) + pcpu->last_high_freq_time = pcpu->freq_change_time; pcpu->timer_idlecancel = 1; pcpu->governor_enabled = 1; smp_wmb(); @@ -694,6 +732,8 @@ static int __init cpufreq_interactive_init(void) midrange_go_maxspeed_load = DEFAULT_MID_RANGE_GO_MAXSPEED_LOAD; min_sample_time = DEFAULT_MIN_SAMPLE_TIME; timer_rate = DEFAULT_TIMER_RATE; + high_freq_min_delay = DEFAULT_HIGH_FREQ_MIN_DELAY; + max_normal_freq = DEFAULT_MAX_NORMAL_FREQ; /* Initalize per-cpu timers */ for_each_possible_cpu(i) { -- cgit v1.2.3 From 334623b8e22fa47beb2e1d877d80678582841108 Mon Sep 17 00:00:00 2001 From: Krishna Yarlagadda Date: Tue, 31 Jul 2012 16:18:50 +0530 Subject: ARM: tegra: usb: Clear pmc wake alarm After a pmc wake, walk pointer and wake alarm should be cleared. Currently wake alarm is cleared only in case of remote wakeup. Clearing wake alarm for all cases of pmc wake. Bug 1024496 Signed-off-by: Krishna Yarlagadda Reviewed-on: http://git-master/r/119619 (cherry picked from commit c3e88db583fec3126ad100775de777a30d9114c6) Change-Id: Ia9e8340d0bea23ccc8aaf3cb522526d9f7076853 Reviewed-on: http://git-master/r/120337 Reviewed-by: Varun Colbert Tested-by: Varun Colbert --- arch/arm/mach-tegra/tegra3_usb_phy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-tegra/tegra3_usb_phy.c b/arch/arm/mach-tegra/tegra3_usb_phy.c index f164b409d29b..be61ffcf4d17 100644 --- a/arch/arm/mach-tegra/tegra3_usb_phy.c +++ b/arch/arm/mach-tegra/tegra3_usb_phy.c @@ -742,6 +742,7 @@ static void utmip_phy_disable_pmc_bus_ctrl(struct tegra_usb_phy *phy) val = readl(pmc_base + PMC_TRIGGERS); val |= UTMIP_CLR_WALK_PTR(inst); + val |= UTMIP_CLR_WAKE_ALARM(inst); writel(val, pmc_base + PMC_TRIGGERS); phy->remote_wakeup = false; -- cgit v1.2.3 From 69b8162aa37e4c7316c2c45860903207d6730e48 Mon Sep 17 00:00:00 2001 From: Gaurav Batra Date: Wed, 1 Aug 2012 12:28:51 -0700 Subject: video: tegra: hdmi: cleanup error handling in init In case tegra_dc_init fails, this change will prevent unbalanced call to dc->out_ops->disable(). Also mark tegra_dc_io_end in case tegra_dc_controller_enable fails, this is required to not stop device from going into suspend mode. Bug 1003874 Change-Id: I5af6b46fc50e1ae8e54f9f4eb8540d751364fed7 Signed-off-by: Gaurav Batra Reviewed-on: http://git-master/r/120108 (cherry picked from commit 7f72709c2f23c05f65ff4ca8bfecde0db1448a65) Reviewed-on: http://git-master/r/120959 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Pradeep Thiruchelvam GVS: Gerrit_Virtual_Submit --- drivers/video/tegra/dc/dc.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index a856691653b1..db97ed3d3c13 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -1299,14 +1299,18 @@ static bool _tegra_dc_controller_enable(struct tegra_dc *dc) tegra_dc_clk_enable(dc); /* do not accept interrupts during initialization */ - tegra_dc_writel(dc, 0, DC_CMD_INT_ENABLE); tegra_dc_writel(dc, 0, DC_CMD_INT_MASK); enable_dc_irq(dc->irq); failed_init = tegra_dc_init(dc); if (failed_init) { - _tegra_dc_controller_disable(dc); + tegra_dc_writel(dc, 0, DC_CMD_INT_MASK); + disable_irq(dc->irq); + tegra_dc_clear_bandwidth(dc); + tegra_dc_clk_disable(dc); + if (dc->out && dc->out->disable) + dc->out->disable(); return false; } @@ -1427,7 +1431,11 @@ static bool _tegra_dc_enable(struct tegra_dc *dc) tegra_dc_io_start(dc); - return _tegra_dc_controller_enable(dc); + if (!_tegra_dc_controller_enable(dc)) { + tegra_dc_io_end(dc); + return false; + } + return true; } void tegra_dc_enable(struct tegra_dc *dc) -- cgit v1.2.3 From f4c6f5181ac212b055e173e66ecd54e240b5f507 Mon Sep 17 00:00:00 2001 From: Rakesh Iyer Date: Thu, 26 Jul 2012 12:18:05 -0700 Subject: ARM: tegra: cardhu: provide suspend aggr for E1506 DSI clock gating requires a valid value for aggressive suspend. Change-Id: I6847fb94e2db899ff251e16f045fa76b8ad2e737 Signed-off-by: Rakesh Iyer Reviewed-on: http://git-master/r/118733 (cherry picked from commit a9d87f3b8f9ec811d6f8e0feb10bfb5151cc659c) Reviewed-on: http://git-master/r/120404 Reviewed-by: Varun Colbert Tested-by: Varun Colbert --- arch/arm/mach-tegra/board-cardhu-panel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-tegra/board-cardhu-panel.c b/arch/arm/mach-tegra/board-cardhu-panel.c index 64a50d41eaf7..41c3477b5754 100644 --- a/arch/arm/mach-tegra/board-cardhu-panel.c +++ b/arch/arm/mach-tegra/board-cardhu-panel.c @@ -1285,7 +1285,8 @@ static void cardhu_panel_preinit(void) cardhu_dsi.n_suspend_cmd = ARRAY_SIZE(dsi_suspend_cmd_1506); cardhu_dsi.dsi_suspend_cmd = dsi_suspend_cmd_1506; - cardhu_dsi.panel_send_dc_frames = true, + cardhu_dsi.panel_send_dc_frames = true; + cardhu_dsi.suspend_aggr = DSI_HOST_SUSPEND_LV0; cardhu_dsi_fb_data.xres = 720; cardhu_dsi_fb_data.yres = 1280; /* Set height and width in mm. */ -- cgit v1.2.3 From 232efaec852448ba31479c98cb4d905289bc8779 Mon Sep 17 00:00:00 2001 From: Rakesh Iyer Date: Thu, 26 Jul 2012 14:30:05 -0700 Subject: ARM: tegra: cardhu: report height/width for cardhu For accurate Dots-per-inch computation we need to report height/width for the cardhu panel. Bug 1003707. Change-Id: I9a3413d06d97bed532ffc501000ca9bc2360e842 Signed-off-by: Rakesh Iyer Reviewed-on: http://git-master/r/118777 (cherry picked from commit bf475b5c3f084af205957fa2be68ef9f3cf57c3b) Reviewed-on: http://git-master/r/120624 Reviewed-by: Varun Colbert Tested-by: Varun Colbert --- arch/arm/mach-tegra/board-cardhu-panel.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-tegra/board-cardhu-panel.c b/arch/arm/mach-tegra/board-cardhu-panel.c index 41c3477b5754..69dab01d533d 100644 --- a/arch/arm/mach-tegra/board-cardhu-panel.c +++ b/arch/arm/mach-tegra/board-cardhu-panel.c @@ -1249,6 +1249,11 @@ static void cardhu_panel_preinit(void) cardhu_disp1_out.n_modes = ARRAY_SIZE(cardhu_panel_modes); cardhu_disp1_out.enable = cardhu_panel_enable; cardhu_disp1_out.disable = cardhu_panel_disable; + if (board_info.board_id == BOARD_E1291) { + /* Set height and width in mm. */ + cardhu_disp1_out.height = 127; + cardhu_disp1_out.width = 216; + } cardhu_disp1_pdata.fb = &cardhu_fb_data; } else { -- cgit v1.2.3 From ac772687150922d76c7a2187ce8377757a69277f Mon Sep 17 00:00:00 2001 From: Rakesh Iyer Date: Thu, 2 Aug 2012 05:19:17 -0700 Subject: ARM: tegra: cardhu: report height/width for cardhu For accurate Dots-per-inch computation we need to report height/width for all cardhu based panels. Bug 1003707. Change-Id: I06c5ee077aa82a9ffd958e1cc7c536b445523da3 Signed-off-by: Rakesh Iyer Reviewed-on: http://git-master/r/120350 (cherry picked from commit 5647ca7f3fe44781a3b9a49f3215d8c629d78f49) Reviewed-on: http://git-master/r/120625 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Pradeep Thiruchelvam --- arch/arm/mach-tegra/board-cardhu-panel.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu-panel.c b/arch/arm/mach-tegra/board-cardhu-panel.c index 69dab01d533d..b34a29b24c46 100644 --- a/arch/arm/mach-tegra/board-cardhu-panel.c +++ b/arch/arm/mach-tegra/board-cardhu-panel.c @@ -1249,11 +1249,9 @@ static void cardhu_panel_preinit(void) cardhu_disp1_out.n_modes = ARRAY_SIZE(cardhu_panel_modes); cardhu_disp1_out.enable = cardhu_panel_enable; cardhu_disp1_out.disable = cardhu_panel_disable; - if (board_info.board_id == BOARD_E1291) { - /* Set height and width in mm. */ - cardhu_disp1_out.height = 127; - cardhu_disp1_out.width = 216; - } + /* Set height and width in mm. */ + cardhu_disp1_out.height = 127; + cardhu_disp1_out.width = 216; cardhu_disp1_pdata.fb = &cardhu_fb_data; } else { @@ -1345,6 +1343,9 @@ int __init cardhu_panel_init(void) #else cardhu_disp1_out.depth = 24; #endif + /* Set height and width in mm. */ + cardhu_disp1_out.height = 127; + cardhu_disp1_out.width = 203; cardhu_fb_data.xres = 1920; cardhu_fb_data.yres = 1200; -- cgit v1.2.3 From 01a3c6ea722de9a91b1d507023bd2a926dd35dfe Mon Sep 17 00:00:00 2001 From: Hyung Taek Ryoo Date: Tue, 31 Jul 2012 15:43:34 -0700 Subject: arm: tegra: optimize L2 enable/disable paths for secureos For the CONFIG_TRUSTED_FOUNDATION code paths, differentiate L2 enable vs. reenable, which are different SMCs (won't trigger an invalidate in the case of a reenable). On an L2 disable SMC, optionally pass a 0 for the L2 ways arg, which skips the full clean/invalidate (and simply just disabled the L2). In order to safely skip flushing the L2 on the disable, we have to be careful what we dirty from the type we flush the L1 and disable the L2. Bug 939415 Signed-off-by: Chris Johnson Change-Id: Ie83703e8a1620dcd4a913e43bb0775ce3f1709b5 Reviewed-on: http://git-master/r/119786 Reviewed-on: http://git-master/r/120956 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Hyung Taek Ryoo Reviewed-by: James Zhao Tested-by: Hyung Taek Ryoo Reviewed-by: Pradeep Thiruchelvam GVS: Gerrit_Virtual_Submit --- arch/arm/mach-tegra/common.c | 118 ++++++++++++++++++------------------------ arch/arm/mach-tegra/headsmp.S | 7 +-- arch/arm/mach-tegra/pm.c | 28 ++++++---- arch/arm/mach-tegra/pm.h | 3 ++ arch/arm/mach-tegra/sleep.S | 79 +++++++++++++++++++++++----- 5 files changed, 144 insertions(+), 91 deletions(-) diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index aa6f0192c5d2..62c253132343 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -2,7 +2,7 @@ * arch/arm/mach-tegra/common.c * * Copyright (C) 2010 Google, Inc. - * Copyright (C) 2010-2012 NVIDIA Corporation + * Copyright (C) 2010-2012, NVIDIA Corporation. All rights reserved. * * Author: * Colin Cross @@ -225,61 +225,13 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = { { NULL, NULL, 0, 0}, }; -#ifdef CONFIG_CACHE_L2X0 #ifdef CONFIG_TRUSTED_FOUNDATIONS -static void tegra_cache_smc(bool enable, u32 arg) -{ - void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; - bool need_affinity_switch; - bool can_switch_affinity; - bool l2x0_enabled; - cpumask_t local_cpu_mask; - cpumask_t saved_cpu_mask; - unsigned long flags; - long ret; - - /* - * ISSUE : Some registers of PL310 controler must be written - * from Secure context (and from CPU0)! - * - * When called form Normal we obtain an abort or do nothing. - * Instructions that must be called in Secure: - * - Write to Control register (L2X0_CTRL==0x100) - * - Write in Auxiliary controler (L2X0_AUX_CTRL==0x104) - * - Invalidate all entries (L2X0_INV_WAY==0x77C), - * mandatory at boot time. - * - Tag and Data RAM Latency Control Registers - * (0x108 & 0x10C) must be written in Secure. - */ - need_affinity_switch = (smp_processor_id() != 0); - can_switch_affinity = !irqs_disabled(); - - WARN_ON(need_affinity_switch && !can_switch_affinity); - if (need_affinity_switch && can_switch_affinity) { - cpu_set(0, local_cpu_mask); - sched_getaffinity(0, &saved_cpu_mask); - ret = sched_setaffinity(0, &local_cpu_mask); - WARN_ON(ret != 0); - } - - local_irq_save(flags); - l2x0_enabled = readl_relaxed(p + L2X0_CTRL) & 1; - if (enable && !l2x0_enabled) - tegra_generic_smc(0xFFFFF100, 0x00000001, arg); - else if (!enable && l2x0_enabled) - tegra_generic_smc(0xFFFFF100, 0x00000002, arg); - local_irq_restore(flags); - - if (need_affinity_switch && can_switch_affinity) { - ret = sched_setaffinity(0, &saved_cpu_mask); - WARN_ON(ret != 0); - } -} +#define CACHE_LINE_SIZE 32 -static void tegra_l2x0_disable(void) +static inline void tegra_l2x0_disable_tz(void) { - unsigned long flags; static u32 l2x0_way_mask; + BUG_ON(smp_processor_id() != 0); if (!l2x0_way_mask) { void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; @@ -290,30 +242,62 @@ static void tegra_l2x0_disable(void) ways = (aux_ctrl & (1 << 16)) ? 16 : 8; l2x0_way_mask = (1 << ways) - 1; } +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + /* flush all ways on disable */ + tegra_generic_smc_uncached(0xFFFFF100, 0x00000002, l2x0_way_mask); +#elif defined(CONFIG_ARCH_TEGRA_3x_SOC) + if (tegra_is_cpu_in_lp2(0)) { + register unsigned long sp asm ("sp"); - local_irq_save(flags); - tegra_cache_smc(false, l2x0_way_mask); - local_irq_restore(flags); + /* flush only the stack, if entering LP2 */ + __cpuc_flush_dcache_area((void *)sp, (CACHE_LINE_SIZE * 2)); + outer_flush_range(__pa(sp), __pa(sp) + (CACHE_LINE_SIZE * 2)); + + /* pass zero arg, so secureos flushes only its workspace */ + tegra_generic_smc_uncached(0xFFFFF100, 0x00000002, 0x0); + } else { + /* flush all ways on disable, if entering LP0/LP1 */ + tegra_generic_smc_uncached(0xFFFFF100, + 0x00000002, l2x0_way_mask); + } +#endif } -#endif /* CONFIG_TRUSTED_FOUNDATIONS */ -void tegra_init_cache(bool init) +static inline void tegra_init_cache_tz(bool init) { void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; u32 aux_ctrl; -#ifdef CONFIG_TRUSTED_FOUNDATIONS - /* issue the SMC to enable the L2 */ - aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL); - tegra_cache_smc(true, aux_ctrl); + BUG_ON(smp_processor_id() != 0); + + if (init) { + /* init L2 from secureos */ + tegra_generic_smc(0xFFFFF100, 0x00000001, 0x0); + + /* common init called for outer call hookup */ + aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL); + l2x0_init(p, aux_ctrl, 0xFFFFFFFF); - /* after init, reread aux_ctrl and register handlers */ - aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL); - l2x0_init(p, aux_ctrl, 0xFFFFFFFF); + /* use our outer_disable() routine */ + outer_cache.disable = tegra_l2x0_disable_tz; + } else { + /* reenable L2 in secureos */ + aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL); + tegra_generic_smc_uncached(0xFFFFF100, 0x00000004, aux_ctrl); + } +} +#endif /* CONFIG_TRUSTED_FOUNDATIONS */ - /* override outer_disable() with our disable */ - outer_cache.disable = tegra_l2x0_disable; +#ifdef CONFIG_CACHE_L2X0 +void tegra_init_cache(bool init) +{ +#ifdef CONFIG_TRUSTED_FOUNDATIONS + /* enable/re-enable of L2 handled by secureos */ + return tegra_init_cache_tz(init); #else + void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; + u32 aux_ctrl; + #if defined(CONFIG_ARCH_TEGRA_2x_SOC) writel_relaxed(0x331, p + L2X0_TAG_LATENCY_CTRL); writel_relaxed(0x441, p + L2X0_DATA_LATENCY_CTRL); @@ -363,7 +347,7 @@ void tegra_init_cache(bool init) l2x0_enable(); #endif } -#endif +#endif /* CONFIG_CACHE_L2X0 */ static void __init tegra_init_power(void) { diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S index 4e28a558cc38..63852b99b3d3 100644 --- a/arch/arm/mach-tegra/headsmp.S +++ b/arch/arm/mach-tegra/headsmp.S @@ -3,7 +3,7 @@ * * CPU initialization routines for Tegra SoCs * - * Copyright (c) 2009-2011, NVIDIA Corporation. + * Copyright (c) 2009-2012, NVIDIA Corporation. All rights reserved. * Copyright (c) 2011 Google, Inc. * Author: Colin Cross * Gary King @@ -90,8 +90,9 @@ ENTRY(tegra_resume) str r1, [r0] #ifdef CONFIG_TRUSTED_FOUNDATIONS - /* wake up (should have specified args?) */ - bl tegra_generic_smc + /* wake up */ + mov r0, #0x00000003 + bl tegra_generic_smc_local #endif b tegra_cpu_resume_phys diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index 9049e37ca05a..d251e57626aa 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -3,7 +3,7 @@ * * CPU complex suspend & resume functions for Tegra SoCs * - * Copyright (c) 2009-2012, NVIDIA Corporation. + * Copyright (c) 2009-2012, NVIDIA Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -546,17 +546,27 @@ bool tegra_set_cpu_in_lp2(int cpu) return last_cpu; } +bool tegra_is_cpu_in_lp2(int cpu) +{ + bool in_lp2; + + spin_lock(&tegra_lp2_lock); + in_lp2 = cpumask_test_cpu(cpu, &tegra_in_lp2); + spin_unlock(&tegra_lp2_lock); + return in_lp2; +} + static void tegra_sleep_core(enum tegra_suspend_mode mode, unsigned long v2p) { #ifdef CONFIG_TRUSTED_FOUNDATIONS if (mode == TEGRA_SUSPEND_LP0) { - tegra_generic_smc(0xFFFFFFFC, 0xFFFFFFE3, - virt_to_phys(tegra_resume)); + tegra_generic_smc_uncached(0xFFFFFFFC, 0xFFFFFFE3, + virt_to_phys(tegra_resume)); } else { - tegra_generic_smc(0xFFFFFFFC, 0xFFFFFFE6, - (TEGRA_RESET_HANDLER_BASE + - tegra_cpu_reset_handler_offset)); + tegra_generic_smc_uncached(0xFFFFFFFC, 0xFFFFFFE6, + (TEGRA_RESET_HANDLER_BASE + + tegra_cpu_reset_handler_offset)); } #endif #ifdef CONFIG_ARCH_TEGRA_2x_SOC @@ -569,9 +579,9 @@ static void tegra_sleep_core(enum tegra_suspend_mode mode, static inline void tegra_sleep_cpu(unsigned long v2p) { #ifdef CONFIG_TRUSTED_FOUNDATIONS - tegra_generic_smc(0xFFFFFFFC, 0xFFFFFFE4, - (TEGRA_RESET_HANDLER_BASE + - tegra_cpu_reset_handler_offset)); + tegra_generic_smc_uncached(0xFFFFFFFC, 0xFFFFFFE4, + (TEGRA_RESET_HANDLER_BASE + + tegra_cpu_reset_handler_offset)); #endif tegra_sleep_cpu_save(v2p); } diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h index 498170648819..b78e9b1abc00 100644 --- a/arch/arm/mach-tegra/pm.h +++ b/arch/arm/mach-tegra/pm.h @@ -75,6 +75,7 @@ unsigned long tegra_cpu_power_off_time(void); unsigned long tegra_cpu_lp2_min_residency(void); void tegra_clear_cpu_in_lp2(int cpu); bool tegra_set_cpu_in_lp2(int cpu); +bool tegra_is_cpu_in_lp2(int cpu); int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags); @@ -222,6 +223,8 @@ extern bool tegra_all_cpus_booted __read_mostly; #ifdef CONFIG_TRUSTED_FOUNDATIONS void tegra_generic_smc(u32 type, u32 subtype, u32 arg); +void tegra_generic_smc_local(u32 type, u32 subtype, u32 arg); +void tegra_generic_smc_uncached(u32 type, u32 subtype, u32 arg); #endif /* The debug channel uart base physical address */ diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S index 973c8677bafe..e86795c5c46a 100644 --- a/arch/arm/mach-tegra/sleep.S +++ b/arch/arm/mach-tegra/sleep.S @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/sleep.S * - * Copyright (c) 2010-2011, NVIDIA Corporation. + * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. * Copyright (c) 2011, Google, Inc. * * Author: Colin Cross @@ -440,28 +440,83 @@ ENDPROC(tegra_cpu_pllp) #endif #ifdef CONFIG_TRUSTED_FOUNDATIONS + /* - * tegra_generic_smc + * Confirm we're issuing this SMC from CPU0 (only one + * currently supported) and issue the instruction. * * r0 = smc type * r1 = smc subtype * r2 = argument passed to smc - * - * issues SMC (secure monitor call) instruction with - * the specified parameters. */ -ENTRY(tegra_generic_smc) - adr r3, __tegra_smc_stack - stmia r3, {r4-r12, lr} +.macro smc_issue_smc tmp + cpu_id \tmp + cmp \tmp, #0 + bne . mov r3, #0 mov r4, #0 dsb smc #0 - adr r3, __tegra_smc_stack - ldmia r3, {r4-r12, pc} +.endm + +/* + * Issue SMC with ctx kept on an uncached stack + */ +ENTRY(tegra_generic_smc_uncached) +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_CACHE_L2X0) + mov32 r3, tegra_cpu_context @ borrow CPU0's non-cached + ldr r3, [r3] @ context grows up + stmia r3, {r4-r12, sp, lr} + + smc_issue_smc r5 + + mov32 r3, tegra_cpu_context @ borrow CPU0's non-cached + ldr r3, [r3] @ context grows up + ldmia r3, {r4-r12, sp, pc} +#else + mov pc, lr +#endif +ENDPROC(tegra_generic_smc_uncached) + +/* + * Issue SMC with ctx kept on a cacheable stack + * (args in R0, R1, R2 and R3 holds save/restore ptr) + */ +ENTRY(tegra_generic_smc_cached) + stmia r3, {r4-r12, sp, lr} + adr r4, __tegra_smc_current_ctx @ save current ptr + str r3, [r4] + + smc_issue_smc r5 + + adr r4, __tegra_smc_current_ctx @ restore from saved ptr + ldr r3, [r4] + ldmia r3, {r4-r12, sp, pc} +ENDPROC(tegra_generic_smc_cached) + .type __tegra_smc_current_ctx, %object +__tegra_smc_current_ctx: + .long 0 + .size __tegra_smc_current_ctx, . - __tegra_smc_current_ctx + +#define TEGRA_SMC_SAVED_WORDS 11 + +/* SMC issued using the current cacheable SP stack */ +ENTRY(tegra_generic_smc) + mov r3, sp @ use current stack + sub r3, #(TEGRA_SMC_SAVED_WORDS << 2) @ context grows up + b tegra_generic_smc_cached ENDPROC(tegra_generic_smc) - .type __tegra_smc_stack, %object + +/* SMC issued using a local cacheable stack */ +ENTRY(tegra_generic_smc_local) + adr r3, __tegra_smc_stack @ use local stack + b tegra_generic_smc_cached +ENDPROC(tegra_generic_smc_local) + .align L1_CACHE_SHIFT + .type __tegra_smc_stack, %object __tegra_smc_stack: - .long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .rept TEGRA_SMC_SAVED_WORDS + .long 0 + .endr .size __tegra_smc_stack, . - __tegra_smc_stack #endif -- cgit v1.2.3 From 287661503d8533e64b79c7a9dab0a31ab7a6419f Mon Sep 17 00:00:00 2001 From: Hyung Taek Ryoo Date: Tue, 31 Jul 2012 15:53:09 -0700 Subject: security: tf_driver: integrate latest TL release Tegra 3 version: TF_TEGRA3_AB01.14.36781 1)Kernel boot addr in TF boot args, branch prediction activated early, fix in system driver mapping. 2)Several improvments in boot and L2CC operations 3)Fix to support Neon Signed-off-by: Hyung Taek Ryoo Change-Id: I6ba85c593331d32e0268e7d6a2d65fdeb8e1214e Reviewed-on: http://git-master/r/119790 Reviewed-on: http://git-master/r/120960 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Hyung Taek Ryoo Reviewed-by: James Zhao Tested-by: Hyung Taek Ryoo Reviewed-by: Pradeep Thiruchelvam GVS: Gerrit_Virtual_Submit --- security/tf_driver/s_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/tf_driver/s_version.h b/security/tf_driver/s_version.h index 5ad7edb86637..81d030a75835 100644 --- a/security/tf_driver/s_version.h +++ b/security/tf_driver/s_version.h @@ -38,7 +38,7 @@ /* * This version number must be updated for each new release */ -#define S_VERSION_MAIN "01.11" +#define S_VERSION_MAIN "01.14" /* * If this is a patch or engineering version use the following -- cgit v1.2.3 From aabfa0e086da91517dbf0c0206143ab8775c781c Mon Sep 17 00:00:00 2001 From: Sayak Ghosh Choudhury Date: Sun, 5 Aug 2012 14:10:17 +0530 Subject: asoc: codecs: max98088: fix no audio after reset 98088 codec register value is altered to fix no audio issue after reset. Previously after reset the register value was getting wiped out. Bug 1017782 Change-Id: I4c6d164067465e15571d1403375eb944a4989f59 Reviewed-on: http://git-master/r/121138 Tested-by: Sayak Choudhury Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Pradeep Thiruchelvam --- sound/soc/codecs/max98088.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index b2b31f912b74..31ca26388642 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -389,7 +389,7 @@ static struct { { 0xFF, 0xFF, 0 }, /* 2C right SPK mixer */ { 0xFF, 0xFF, 0 }, /* 2D SPK control */ { 0xFF, 0xFF, 0 }, /* 2E sidetone */ - { 0xFF, 0xFF, 0 }, /* 2F DAI1 playback level */ + { 0xFF, 0xFF, 1 }, /* 2F DAI1 playback level */ { 0xFF, 0xFF, 0 }, /* 30 DAI1 playback level */ { 0xFF, 0xFF, 0 }, /* 31 DAI2 playback level */ -- cgit v1.2.3 From 621545eea27daea90b1c7e4b2ea5ba10bd6ca618 Mon Sep 17 00:00:00 2001 From: Frank Chen Date: Wed, 1 Aug 2012 16:17:44 -0700 Subject: media: video: tegra: fix sh532u buffer overflows We need to validate the buffer size before we copy buffers from/to user space. Bug 1027334 Change-Id: I0717e9ff1d2e5eb3e8a863555457f4bcfdbb2cb9 Signed-off-by: Frank Chen Reviewed-on: http://git-master/r/120407 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Patrick Shehane Reviewed-by: Anton Kondratenko Reviewed-by: Naren Bhat Reviewed-by: Wei Chen GVS: Gerrit_Virtual_Submit Reviewed-by: Pradeep Thiruchelvam --- drivers/media/video/tegra/sh532u.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/video/tegra/sh532u.c b/drivers/media/video/tegra/sh532u.c index 84692d992154..e41dd1f4afb1 100644 --- a/drivers/media/video/tegra/sh532u.c +++ b/drivers/media/video/tegra/sh532u.c @@ -1406,9 +1406,9 @@ static int sh532u_set_focuser_capabilities(struct sh532u_info *info, struct nvc_param *params) { if (copy_from_user(&info->config, (const void __user *)params->p_value, - params->sizeofvalue)) { + sizeof(struct nv_focuser_config))) { dev_err(&info->i2c_client->dev, "%s Error: copy_from_user bytes %d\n", - __func__, params->sizeofvalue); + __func__, sizeof(struct nv_focuser_config)); return -EFAULT; } @@ -1420,7 +1420,7 @@ static int sh532u_set_focuser_capabilities(struct sh532u_info *info, info->config.slew_rate = info->config.slew_rate; dev_dbg(&info->i2c_client->dev, "%s: copy_from_user bytes %d\n", - __func__, params->sizeofvalue); + __func__, sizeof(struct nv_focuser_config)); return 0; } @@ -1491,7 +1491,7 @@ static int sh532u_param_rd(struct sh532u_info *info, unsigned long arg) sh532u_get_focuser_capabilities(info); data_ptr = &info->config; - data_size = params.sizeofvalue; + data_size = sizeof(info->config); break; case NVC_PARAM_STS: -- cgit v1.2.3 From 14050486641d985f8257c471af3b622157648065 Mon Sep 17 00:00:00 2001 From: Ray Poudrier Date: Thu, 21 Jun 2012 22:03:54 -0700 Subject: ARM: tegra: la: scale latency allowance based on ticks With new memory tables, the tick length will be longer. This will check the tick length of the memory table, and if needed, update the latency allowance. Bug 955082 Change-Id: Idba0071c1452db95e3e430db3bea29947e1def6c Reviewed-on: http://git-master/r/111040 (cherry picked from commit b7627149bd4678e58dfe95db04f5312232715afd) Signed-off-by: Ray Poudrier Reviewed-on: http://git-master/r/120964 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Pradeep Thiruchelvam --- arch/arm/mach-tegra/common-t3.c | 15 +++++++- .../mach-tegra/include/mach/latency_allowance.h | 9 ++++- arch/arm/mach-tegra/latency_allowance.c | 35 ++++++++++++++++- arch/arm/mach-tegra/tegra3_emc.c | 45 +++++++++++++++++++++- arch/arm/mach-tegra/tegra3_emc.h | 43 ++++++++++++++++++++- 5 files changed, 141 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-tegra/common-t3.c b/arch/arm/mach-tegra/common-t3.c index 2da656f97c38..76188723b46f 100644 --- a/arch/arm/mach-tegra/common-t3.c +++ b/arch/arm/mach-tegra/common-t3.c @@ -3,7 +3,7 @@ * * Tegra 3 SoC-specific initialization (memory controller, etc.) * - * Copyright (c) 2010-2012, NVIDIA Corporation. + * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,6 +44,8 @@ ((MC_EMEM_ARB_TIMING_W2R - MC_EMEM_ARB_CFG) / 4 + 1) #define MC_TIMING_REG_NUM2 \ ((MC_EMEM_ARB_MISC1 - MC_EMEM_ARB_DA_TURNS) / 4 + 1) +#define MC_TIMING_REG_NUM3 \ + ((MC_LATENCY_ALLOWANCE_VI_2 - MC_LATENCY_ALLOWANCE_AFI) / 4 + 1) struct mc_client { const char *name; @@ -59,7 +61,8 @@ static void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE); #ifdef CONFIG_PM_SLEEP -static u32 mc_boot_timing[MC_TIMING_REG_NUM1 + MC_TIMING_REG_NUM2 + 4]; +static u32 mc_boot_timing[MC_TIMING_REG_NUM1 + MC_TIMING_REG_NUM2 + + MC_TIMING_REG_NUM3 + 4]; static void tegra_mc_timing_save(void) { @@ -76,6 +79,10 @@ static void tegra_mc_timing_save(void) *ctx++ = readl((u32)mc + MC_EMEM_ARB_OVERRIDE); *ctx++ = readl((u32)mc + MC_RESERVED_RSV); + for (off = MC_LATENCY_ALLOWANCE_AFI; off <= MC_LATENCY_ALLOWANCE_VI_2; + off += 4) + *ctx++ = readl((u32)mc + off); + *ctx++ = readl((u32)mc + MC_INT_MASK); } @@ -94,6 +101,10 @@ void tegra_mc_timing_restore(void) __raw_writel(*ctx++, (u32)mc + MC_EMEM_ARB_OVERRIDE); __raw_writel(*ctx++, (u32)mc + MC_RESERVED_RSV); + for (off = MC_LATENCY_ALLOWANCE_AFI; off <= MC_LATENCY_ALLOWANCE_VI_2; + off += 4) + __raw_writel(*ctx++, (u32)mc + off); + writel(*ctx++, (u32)mc + MC_INT_MASK); off = readl((u32)mc + MC_INT_MASK); diff --git a/arch/arm/mach-tegra/include/mach/latency_allowance.h b/arch/arm/mach-tegra/include/mach/latency_allowance.h index 8644075a88b3..b17569fc5f29 100644 --- a/arch/arm/mach-tegra/include/mach/latency_allowance.h +++ b/arch/arm/mach-tegra/include/mach/latency_allowance.h @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/include/mach/latency_allowance.h * - * Copyright (C) 2011-2012 NVIDIA Corporation. + * Copyright (C) 2011-2012, NVIDIA CORPORATION. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -106,6 +106,12 @@ static inline void tegra_disable_latency_scaling(enum tegra_la_id id) { return; } + +static inline void tegra_latency_allowance_update_tick_length( + unsigned int new_ns_per_tick) +{ + return; +} #else int tegra_set_latency_allowance(enum tegra_la_id id, unsigned int bandwidth_in_mbps); @@ -116,6 +122,7 @@ int tegra_enable_latency_scaling(enum tegra_la_id id, unsigned int threshold_high); void tegra_disable_latency_scaling(enum tegra_la_id id); +void tegra_latency_allowance_update_tick_length(unsigned int new_ns_per_tick); #endif #endif /* _MACH_TEGRA_LATENCY_ALLOWANCE_H_ */ diff --git a/arch/arm/mach-tegra/latency_allowance.c b/arch/arm/mach-tegra/latency_allowance.c index f8e5ce579200..8d16d8d36661 100644 --- a/arch/arm/mach-tegra/latency_allowance.c +++ b/arch/arm/mach-tegra/latency_allowance.c @@ -118,7 +118,7 @@ struct la_client_info { static DEFINE_SPINLOCK(safety_lock); -static const int ns_per_tick = 30; +static int ns_per_tick = 30; /* fifo atom size in bytes for non-fdc clients*/ static const int normal_atom_size = 16; /* fifo atom size in bytes for fdc clients*/ @@ -506,6 +506,39 @@ void tegra_disable_latency_scaling(enum tegra_la_id id) spin_unlock(&safety_lock); } +void tegra_latency_allowance_update_tick_length(unsigned int new_ns_per_tick) +{ + int i = 0; + int la; + unsigned long reg_read; + unsigned long reg_write; + unsigned long scale_factor = 0; + + if (new_ns_per_tick != 30) { + ns_per_tick = new_ns_per_tick; + scale_factor = new_ns_per_tick / 30; + + spin_lock(&safety_lock); + for (i = 0; i < ARRAY_SIZE(la_info) - 1; i++) { + reg_read = readl(la_info[i].reg_addr); + la = ((reg_read & la_info[i].mask) >> la_info[i].shift) + / scale_factor; + + reg_write = (reg_read & ~la_info[i].mask) | + (la << la_info[i].shift); + writel(reg_write, la_info[i].reg_addr); + scaling_info[i].la_set = la; + } + spin_unlock(&safety_lock); + + /* Re-scale G2PR, G2SR, G2DR, G2DW with updated ns_per_tick */ + tegra_set_latency_allowance(TEGRA_LA_G2PR, 20); + tegra_set_latency_allowance(TEGRA_LA_G2SR, 20); + tegra_set_latency_allowance(TEGRA_LA_G2DR, 20); + tegra_set_latency_allowance(TEGRA_LA_G2DW, 20); + } +} + static int la_regs_show(struct seq_file *s, void *unused) { unsigned i; diff --git a/arch/arm/mach-tegra/tegra3_emc.c b/arch/arm/mach-tegra/tegra3_emc.c index 57a673b4df8d..4c06bf91ab1f 100644 --- a/arch/arm/mach-tegra/tegra3_emc.c +++ b/arch/arm/mach-tegra/tegra3_emc.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/tegra3_emc.c * - * Copyright (C) 2012 NVIDIA Corporation + * Copyright (C) 2011-2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +33,7 @@ #include #include +#include #include "clock.h" #include "dvfs.h" @@ -1018,6 +1019,31 @@ static struct notifier_block tegra_emc_resume_nb = { .priority = -1, }; +static int tegra_emc_get_table_ns_per_tick(unsigned int emc_rate, + unsigned int table_tick_len) +{ + unsigned int ns_per_tick = 0; + unsigned int mc_period_10ns = 0; + unsigned int reg; + + reg = mc_readl(MC_EMEM_ARB_MISC0) & MC_EMEM_ARB_MISC0_EMC_SAME_FREQ; + + mc_period_10ns = ((reg ? (NSEC_PER_MSEC * 10) : (20 * NSEC_PER_MSEC)) / + (emc_rate)); + ns_per_tick = ((table_tick_len & MC_EMEM_ARB_CFG_CYCLE_MASK) + * mc_period_10ns) / (10 * + (1 + ((table_tick_len & MC_EMEM_ARB_CFG_EXTRA_TICK_MASK) + >> MC_EMEM_ARB_CFG_EXTRA_TICK_SHIFT))); + + /* round new_ns_per_tick to 30/60 */ + if (ns_per_tick < 45) + ns_per_tick = 30; + else + ns_per_tick = 60; + + return ns_per_tick; +} + void tegra_init_emc(const struct tegra_emc_table *table, int table_size) { int i, mv; @@ -1025,6 +1051,8 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size) bool max_entry = false; unsigned long boot_rate, max_rate; struct clk *cbus = tegra_get_clock_by_name("cbus"); + unsigned int ns_per_tick = 0; + unsigned int cur_ns_per_tick = 0; emc_stats.clkchange_count = 0; spin_lock_init(&emc_stats.spinlock); @@ -1085,6 +1113,19 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size) if (table_rate == max_rate) max_entry = true; + + cur_ns_per_tick = tegra_emc_get_table_ns_per_tick(table_rate, + table[i].burst_regs[MC_EMEM_ARB_CFG_INDEX]); + + if (ns_per_tick == 0) { + ns_per_tick = cur_ns_per_tick; + } else if (ns_per_tick != cur_ns_per_tick) { + pr_err("tegra: invalid EMC DFS table: " + "mismatched DFS tick lengths " + "within table!\n"); + ns_per_tick = 0; + return; + } } /* Validate EMC rate and voltage limits */ @@ -1094,6 +1135,8 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size) return; } + tegra_latency_allowance_update_tick_length(ns_per_tick); + tegra_emc_table = table; adjust_emc_dvfs_table(tegra_emc_table, tegra_emc_table_size); diff --git a/arch/arm/mach-tegra/tegra3_emc.h b/arch/arm/mach-tegra/tegra3_emc.h index 29b4556d749d..43ef636c613f 100644 --- a/arch/arm/mach-tegra/tegra3_emc.h +++ b/arch/arm/mach-tegra/tegra3_emc.h @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/tegra3_emc.h * - * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2011-2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -267,6 +267,10 @@ enum { #define MC_EMEM_ADR_CFG 0x54 #define MC_EMEM_ARB_CFG 0x90 +#define MC_EMEM_ARB_CFG_CYCLE_MASK 0x1ff +#define MC_EMEM_ARB_CFG_EXTRA_TICK_SHIFT 16 +#define MC_EMEM_ARB_CFG_EXTRA_TICK_MASK \ + (0x1f << MC_EMEM_ARB_CFG_EXTRA_TICK_SHIFT) #define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 #define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_SHIFT 0 #define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_MASK \ @@ -295,6 +299,43 @@ enum { #define MC_EMEM_ARB_OVERRIDE 0xe8 #define MC_EMEM_ARB_OVERRIDE_EACK_MASK (0x3 << 0) #define MC_TIMING_CONTROL 0xfc +#define MC_LATENCY_ALLOWANCE_AFI 0x2e0 +#define MC_LATENCY_ALLOWANCE_AVPC 0x2e4 +#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8 +#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec +#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0 +#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4 +#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8 +#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc +#define MC_LATENCY_ALLOWANCE_EPP_0 0x300 +#define MC_LATENCY_ALLOWANCE_EPP_1 0x304 +#define MC_LATENCY_ALLOWANCE_G2_0 0x308 +#define MC_LATENCY_ALLOWANCE_G2_1 0x30c +#define MC_LATENCY_ALLOWANCE_HC_0 0x310 +#define MC_LATENCY_ALLOWANCE_HC_1 0x314 +#define MC_LATENCY_ALLOWANCE_HDA 0x318 +#define MC_LATENCY_ALLOWANCE_ISP 0x31c +#define MC_LATENCY_ALLOWANCE_MPCORE 0x320 +#define MC_LATENCY_ALLOWANCE_MPCORELP 0x324 +#define MC_LATENCY_ALLOWANCE_MPE_0 0x328 +#define MC_LATENCY_ALLOWANCE_MPE_1 0x32c +#define MC_LATENCY_ALLOWANCE_MPE_2 0x330 +#define MC_LATENCY_ALLOWANCE_NV_0 0x334 +#define MC_LATENCY_ALLOWANCE_NV_1 0x338 +#define MC_LATENCY_ALLOWANCE_NV2_0 0x33c +#define MC_LATENCY_ALLOWANCE_NV2_1 0x340 +#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344 +#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348 +#define MC_LATENCY_ALLOWANCE_PTC 0x34c +#define MC_LATENCY_ALLOWANCE_SATA 0x350 +#define MC_LATENCY_ALLOWANCE_VDE_0 0x354 +#define MC_LATENCY_ALLOWANCE_VDE_1 0x358 +#define MC_LATENCY_ALLOWANCE_VDE_2 0x35c +#define MC_LATENCY_ALLOWANCE_VDE_3 0x360 +#define MC_LATENCY_ALLOWANCE_VI_0 0x364 +#define MC_LATENCY_ALLOWANCE_VI_1 0x368 +#define MC_LATENCY_ALLOWANCE_VI_2 0x36c + #define MC_RESERVED_RSV 0x3fc #endif -- cgit v1.2.3 From 40352070f5e0f5661de1260e112ed2d1952553f9 Mon Sep 17 00:00:00 2001 From: Ray Poudrier Date: Mon, 2 Jul 2012 16:41:32 -0700 Subject: ARM: tegra: kai: update memory timings Extend tick length to 60ns Bug 1001229 Change-Id: I8a96dd08b6d11a196c9b82bec403ab2e4676e2f4 Signed-off-by: Ray Poudrier Reviewed-on: http://git-master/r/113081 (cherry picked from commit 487622aa43568d3f6f9a9f5fc98176e5ffdd6246) Reviewed-on: http://git-master/r/120965 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Pradeep Thiruchelvam --- arch/arm/mach-tegra/board-kai-memory.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-tegra/board-kai-memory.c b/arch/arm/mach-tegra/board-kai-memory.c index 1f812ece741b..cf5daf6492eb 100644 --- a/arch/arm/mach-tegra/board-kai-memory.c +++ b/arch/arm/mach-tegra/board-kai-memory.c @@ -117,7 +117,7 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00020001, /* MC_EMEM_ARB_CFG */ + 0x00030003, /* MC_EMEM_ARB_CFG */ 0xc0000008, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -237,7 +237,7 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc000000a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -357,7 +357,7 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000013, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -477,7 +477,7 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000d22, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -597,8 +597,8 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800014d4, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000005, /* MC_EMEM_ARB_CFG */ - 0x8000003d, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000a, /* MC_EMEM_ARB_CFG */ + 0xc000003d, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000008, /* MC_EMEM_ARB_TIMING_RC */ @@ -717,8 +717,8 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800028a5, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000a, /* MC_EMEM_ARB_CFG */ - 0x80000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000014, /* MC_EMEM_ARB_CFG */ + 0xc0000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000003, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000004, /* MC_EMEM_ARB_TIMING_RP */ 0x00000010, /* MC_EMEM_ARB_TIMING_RC */ -- cgit v1.2.3 From 24dc7b418ce916bf0d5dc16867cdd7e2ddf7554f Mon Sep 17 00:00:00 2001 From: Ray Poudrier Date: Mon, 2 Jul 2012 20:17:42 -0700 Subject: ARM: tegra: enterprise: update memory timings Extend to 60ns tick Bug 1001229 Change-Id: Id2b01218a7c5cb1566d0e8c175defb12c79e6497 Signed-off-by: Ray Poudrier Reviewed-on: http://git-master/r/113122 (cherry picked from commit 176fd3fbaede0d38281fe4bad721856e7fef0833) Reviewed-on: http://git-master/r/120966 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Pradeep Thiruchelvam --- arch/arm/mach-tegra/board-enterprise-memory.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-tegra/board-enterprise-memory.c b/arch/arm/mach-tegra/board-enterprise-memory.c index 36a8264c2a21..1fc0d3c3fddd 100644 --- a/arch/arm/mach-tegra/board-enterprise-memory.c +++ b/arch/arm/mach-tegra/board-enterprise-memory.c @@ -116,7 +116,7 @@ static const struct tegra_emc_table enterprise_emc_tables_kmmll0_a02[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000164, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00050001, /* MC_EMEM_ARB_CFG */ + 0x00050002, /* MC_EMEM_ARB_CFG */ 0xc0000008, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -236,7 +236,7 @@ static const struct tegra_emc_table enterprise_emc_tables_kmmll0_a02[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800001c2, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00020001, /* MC_EMEM_ARB_CFG */ + 0x00030003, /* MC_EMEM_ARB_CFG */ 0xc0000008, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -356,7 +356,7 @@ static const struct tegra_emc_table enterprise_emc_tables_kmmll0_a02[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc000000a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -476,7 +476,7 @@ static const struct tegra_emc_table enterprise_emc_tables_kmmll0_a02[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000013, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -596,7 +596,7 @@ static const struct tegra_emc_table enterprise_emc_tables_kmmll0_a02[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -716,7 +716,7 @@ static const struct tegra_emc_table enterprise_emc_tables_kmmll0_a02[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000ce6, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000006, /* MC_EMEM_ARB_CFG */ + 0x0000000c, /* MC_EMEM_ARB_CFG */ 0xc0000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000002, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000003, /* MC_EMEM_ARB_TIMING_RP */ -- cgit v1.2.3 From bc4dcf82adfcda51e355f929fd7d7d4f9bcaa722 Mon Sep 17 00:00:00 2001 From: Ray Poudrier Date: Tue, 3 Jul 2012 11:43:05 -0700 Subject: ARM: tegra: cardhu: update memory timings Extend tick length to 60ns Also add missed Cardhu SKU 1000 table Bug 1001229 Bug 970610 Change-Id: I224158a88d02595d5b911f59b6920b9ed99481ab Signed-off-by: Ray Poudrier Reviewed-on: http://git-master/r/113315 (cherry picked from commit 492193079047d9c5a4fff617a14191438f356e42) Reviewed-on: http://git-master/r/120967 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Pradeep Thiruchelvam --- arch/arm/mach-tegra/board-cardhu-memory.c | 782 ++++++++++++++++++++++++++---- 1 file changed, 694 insertions(+), 88 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu-memory.c b/arch/arm/mach-tegra/board-cardhu-memory.c index 1ed99a9fa1fa..33a66053ee45 100644 --- a/arch/arm/mach-tegra/board-cardhu-memory.c +++ b/arch/arm/mach-tegra/board-cardhu-memory.c @@ -705,7 +705,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000280, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00020001, /* MC_EMEM_ARB_CFG */ + 0x00030003, /* MC_EMEM_ARB_CFG */ 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -825,7 +825,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -945,7 +945,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000018, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -1065,7 +1065,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000d22, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -1185,8 +1185,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000174b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000005, /* MC_EMEM_ARB_CFG */ - 0x80000044, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000b, /* MC_EMEM_ARB_CFG */ + 0xc0000044, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000009, /* MC_EMEM_ARB_TIMING_RC */ @@ -1305,8 +1305,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80001941, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000006, /* MC_EMEM_ARB_CFG */ - 0x8000004a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000c, /* MC_EMEM_ARB_CFG */ + 0xc000004a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x0000000a, /* MC_EMEM_ARB_TIMING_RC */ @@ -1425,8 +1425,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80001bc0, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000006, /* MC_EMEM_ARB_CFG */ - 0x80000051, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000d, /* MC_EMEM_ARB_CFG */ + 0xc0000051, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000002, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000003, /* MC_EMEM_ARB_TIMING_RP */ 0x0000000b, /* MC_EMEM_ARB_TIMING_RC */ @@ -1545,8 +1545,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800020ae, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000008, /* MC_EMEM_ARB_CFG */ - 0x80000060, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000f, /* MC_EMEM_ARB_CFG */ + 0xc0000060, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000002, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000003, /* MC_EMEM_ARB_TIMING_RP */ 0x0000000d, /* MC_EMEM_ARB_TIMING_RC */ @@ -1665,8 +1665,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800028a5, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000a, /* MC_EMEM_ARB_CFG */ - 0x80000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000014, /* MC_EMEM_ARB_CFG */ + 0xc0000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000003, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000004, /* MC_EMEM_ARB_TIMING_RP */ 0x00000010, /* MC_EMEM_ARB_TIMING_RC */ @@ -1785,8 +1785,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000308c, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000c, /* MC_EMEM_ARB_CFG */ - 0x80000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000016, /* MC_EMEM_ARB_CFG */ + 0xc0000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000013, /* MC_EMEM_ARB_TIMING_RC */ @@ -1905,8 +1905,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000308c, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000c, /* MC_EMEM_ARB_CFG */ - 0x80000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000018, /* MC_EMEM_ARB_CFG */ + 0xc0000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000013, /* MC_EMEM_ARB_TIMING_RC */ @@ -2025,8 +2025,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000367d, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000d, /* MC_EMEM_ARB_CFG */ - 0x800000a2, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000001b, /* MC_EMEM_ARB_CFG */ + 0xc00000a2, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000005, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000006, /* MC_EMEM_ARB_TIMING_RP */ 0x00000016, /* MC_EMEM_ARB_TIMING_RC */ @@ -2148,7 +2148,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -2268,7 +2268,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000018, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -2388,7 +2388,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000d22, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -2508,8 +2508,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000174b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000005, /* MC_EMEM_ARB_CFG */ - 0x80000044, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000b, /* MC_EMEM_ARB_CFG */ + 0xc0000044, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000009, /* MC_EMEM_ARB_TIMING_RC */ @@ -2628,8 +2628,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800018c8, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000006, /* MC_EMEM_ARB_CFG */ - 0x80000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000c, /* MC_EMEM_ARB_CFG */ + 0xc0000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000009, /* MC_EMEM_ARB_TIMING_RC */ @@ -2748,8 +2748,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80002d93, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000b, /* MC_EMEM_ARB_CFG */ - 0x80000087, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000014, /* MC_EMEM_ARB_CFG */ + 0xc0000087, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000012, /* MC_EMEM_ARB_TIMING_RC */ @@ -2868,8 +2868,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80002d93, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000b, /* MC_EMEM_ARB_CFG */ - 0x80000087, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000016, /* MC_EMEM_ARB_CFG */ + 0xc0000087, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000012, /* MC_EMEM_ARB_TIMING_RC */ @@ -2988,8 +2988,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000308c, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000c, /* MC_EMEM_ARB_CFG */ - 0x80000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000018, /* MC_EMEM_ARB_CFG */ + 0xc0000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000013, /* MC_EMEM_ARB_TIMING_RC */ @@ -3111,7 +3111,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00020001, /* MC_EMEM_ARB_CFG */ + 0x00030003, /* MC_EMEM_ARB_CFG */ 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -3186,14 +3186,14 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00004288, /* EMC_FBIO_CFG5 */ 0x007800a4, /* EMC_CFG_DIG_DLL */ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ - 0x000fc000, /* EMC_DLL_XFORM_DQS0 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS1 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS2 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS3 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS4 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS5 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS6 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS7 */ + 0x00080000, /* EMC_DLL_XFORM_DQS0 */ + 0x00080000, /* EMC_DLL_XFORM_DQS1 */ + 0x00080000, /* EMC_DLL_XFORM_DQS2 */ + 0x00080000, /* EMC_DLL_XFORM_DQS3 */ + 0x00080000, /* EMC_DLL_XFORM_DQS4 */ + 0x00080000, /* EMC_DLL_XFORM_DQS5 */ + 0x00080000, /* EMC_DLL_XFORM_DQS6 */ + 0x00080000, /* EMC_DLL_XFORM_DQS7 */ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ @@ -3210,10 +3210,10 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ0 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ1 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ2 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ3 */ + 0x00080000, /* EMC_DLL_XFORM_DQ0 */ + 0x00080000, /* EMC_DLL_XFORM_DQ1 */ + 0x00080000, /* EMC_DLL_XFORM_DQ2 */ + 0x00080000, /* EMC_DLL_XFORM_DQ3 */ 0x000002a0, /* EMC_XM2CMDPADCTRL */ 0x0800211c, /* EMC_XM2DQSPADCTRL2 */ 0x00000000, /* EMC_XM2DQPADCTRL2 */ @@ -3231,7 +3231,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -3306,14 +3306,14 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00004288, /* EMC_FBIO_CFG5 */ 0x007800a4, /* EMC_CFG_DIG_DLL */ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ - 0x000fc000, /* EMC_DLL_XFORM_DQS0 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS1 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS2 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS3 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS4 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS5 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS6 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS7 */ + 0x00080000, /* EMC_DLL_XFORM_DQS0 */ + 0x00080000, /* EMC_DLL_XFORM_DQS1 */ + 0x00080000, /* EMC_DLL_XFORM_DQS2 */ + 0x00080000, /* EMC_DLL_XFORM_DQS3 */ + 0x00080000, /* EMC_DLL_XFORM_DQS4 */ + 0x00080000, /* EMC_DLL_XFORM_DQS5 */ + 0x00080000, /* EMC_DLL_XFORM_DQS6 */ + 0x00080000, /* EMC_DLL_XFORM_DQS7 */ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ @@ -3330,10 +3330,10 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ0 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ1 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ2 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ3 */ + 0x00080000, /* EMC_DLL_XFORM_DQ0 */ + 0x00080000, /* EMC_DLL_XFORM_DQ1 */ + 0x00080000, /* EMC_DLL_XFORM_DQ2 */ + 0x00080000, /* EMC_DLL_XFORM_DQ3 */ 0x000002a0, /* EMC_XM2CMDPADCTRL */ 0x0800211c, /* EMC_XM2DQSPADCTRL2 */ 0x00000000, /* EMC_XM2DQPADCTRL2 */ @@ -3351,7 +3351,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000018, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -3471,7 +3471,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000d22, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -3591,8 +3591,8 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000174b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000005, /* MC_EMEM_ARB_CFG */ - 0x80000044, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000b, /* MC_EMEM_ARB_CFG */ + 0xc0000044, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000009, /* MC_EMEM_ARB_TIMING_RC */ @@ -3711,8 +3711,8 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800018c8, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000006, /* MC_EMEM_ARB_CFG */ - 0x80000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000c, /* MC_EMEM_ARB_CFG */ + 0xc0000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000009, /* MC_EMEM_ARB_TIMING_RC */ @@ -3831,8 +3831,8 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80002d93, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000b, /* MC_EMEM_ARB_CFG */ - 0x80000087, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000016, /* MC_EMEM_ARB_CFG */ + 0xc0000087, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000012, /* MC_EMEM_ARB_TIMING_RC */ @@ -3951,8 +3951,8 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000308c, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000c, /* MC_EMEM_ARB_CFG */ - 0x80000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000018, /* MC_EMEM_ARB_CFG */ + 0xc0000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000013, /* MC_EMEM_ARB_TIMING_RC */ @@ -4194,7 +4194,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800001c2, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00020001, /* MC_EMEM_ARB_CFG */ + 0x00030003, /* MC_EMEM_ARB_CFG */ 0xc0000008, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -4314,7 +4314,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc000000a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -4434,7 +4434,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000013, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -4554,7 +4554,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -4914,8 +4914,8 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800010d9, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000008, /* MC_EMEM_ARB_CFG */ - 0x80000060, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000f, /* MC_EMEM_ARB_CFG */ + 0xc0000060, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000003, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000004, /* MC_EMEM_ARB_TIMING_RP */ 0x00000010, /* MC_EMEM_ARB_TIMING_RC */ @@ -5037,7 +5037,7 @@ static const struct tegra_emc_table cardhu_emc_tables_edb8132b2ma[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800001c5, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00020001, /* MC_EMEM_ARB_CFG */ + 0x00030003, /* MC_EMEM_ARB_CFG */ 0xc0000008, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -5157,7 +5157,7 @@ static const struct tegra_emc_table cardhu_emc_tables_edb8132b2ma[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc000000a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -5277,7 +5277,7 @@ static const struct tegra_emc_table cardhu_emc_tables_edb8132b2ma[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000013, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -5397,7 +5397,7 @@ static const struct tegra_emc_table cardhu_emc_tables_edb8132b2ma[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -5517,8 +5517,8 @@ static const struct tegra_emc_table cardhu_emc_tables_edb8132b2ma[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800010d9, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000008, /* MC_EMEM_ARB_CFG */ - 0x80000060, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000f, /* MC_EMEM_ARB_CFG */ + 0xc0000060, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000003, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000004, /* MC_EMEM_ARB_TIMING_RP */ 0x00000010, /* MC_EMEM_ARB_TIMING_RC */ @@ -5640,7 +5640,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_pm311[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc000000a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -5760,7 +5760,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_pm311[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000013, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -5880,7 +5880,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_pm311[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000d22, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -6000,8 +6000,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_pm311[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800014d4, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000005, /* MC_EMEM_ARB_CFG */ - 0x8000003d, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000a, /* MC_EMEM_ARB_CFG */ + 0xc000003d, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000008, /* MC_EMEM_ARB_TIMING_RC */ @@ -6120,8 +6120,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_pm311[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800028a5, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000a, /* MC_EMEM_ARB_CFG */ - 0x80000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000014, /* MC_EMEM_ARB_CFG */ + 0xc0000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000003, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000004, /* MC_EMEM_ARB_TIMING_RP */ 0x00000010, /* MC_EMEM_ARB_TIMING_RC */ @@ -6151,6 +6151,609 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_pm311[] = { }, }; +static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2g2r[] = { + { + 0x32, /* Rev 3.2 */ + 25500, /* SDRAM frequency */ + { + 0x00000001, /* EMC_RC */ + 0x00000004, /* EMC_RFC */ + 0x00000000, /* EMC_RAS */ + 0x00000000, /* EMC_RP */ + 0x00000002, /* EMC_R2W */ + 0x0000000a, /* EMC_W2R */ + 0x00000003, /* EMC_R2P */ + 0x0000000b, /* EMC_W2P */ + 0x00000000, /* EMC_RD_RCD */ + 0x00000000, /* EMC_WR_RCD */ + 0x00000003, /* EMC_RRD */ + 0x00000001, /* EMC_REXT */ + 0x00000000, /* EMC_WEXT */ + 0x00000005, /* EMC_WDV */ + 0x00000005, /* EMC_QUSE */ + 0x00000004, /* EMC_QRST */ + 0x00000007, /* EMC_QSAFE */ + 0x0000000c, /* EMC_RDV */ + 0x000000c0, /* EMC_REFRESH */ + 0x00000000, /* EMC_BURST_REFRESH_NUM */ + 0x00000030, /* EMC_PRE_REFRESH_REQ_CNT */ + 0x00000002, /* EMC_PDEX2WR */ + 0x00000002, /* EMC_PDEX2RD */ + 0x00000001, /* EMC_PCHG2PDEN */ + 0x00000000, /* EMC_ACT2PDEN */ + 0x00000007, /* EMC_AR2PDEN */ + 0x0000000f, /* EMC_RW2PDEN */ + 0x00000005, /* EMC_TXSR */ + 0x00000005, /* EMC_TXSRDLL */ + 0x00000004, /* EMC_TCKE */ + 0x00000001, /* EMC_TFAW */ + 0x00000000, /* EMC_TRPAB */ + 0x00000004, /* EMC_TCLKSTABLE */ + 0x00000005, /* EMC_TCLKSTOP */ + 0x000000c7, /* EMC_TREFBW */ + 0x00000000, /* EMC_QUSE_EXTRA */ + 0x00000004, /* EMC_FBIO_CFG6 */ + 0x00000000, /* EMC_ODT_WRITE */ + 0x00000000, /* EMC_ODT_READ */ + 0x00006288, /* EMC_FBIO_CFG5 */ + 0x007800a4, /* EMC_CFG_DIG_DLL */ + 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ + 0x000fc000, /* EMC_DLL_XFORM_DQS0 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS1 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS2 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS3 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS4 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS5 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS6 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS7 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE3 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE4 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE5 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE6 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE7 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ0 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ1 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ2 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ3 */ + 0x000002a0, /* EMC_XM2CMDPADCTRL */ + 0x0800211c, /* EMC_XM2DQSPADCTRL2 */ + 0x00000000, /* EMC_XM2DQPADCTRL2 */ + 0x77fff884, /* EMC_XM2CLKPADCTRL */ + 0x01f1f108, /* EMC_XM2COMPPADCTRL */ + 0x05057404, /* EMC_XM2VTTGENPADCTRL */ + 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */ + 0x08000168, /* EMC_XM2QUSEPADCTRL */ + 0x08000000, /* EMC_XM2DQSPADCTRL3 */ + 0x00000802, /* EMC_CTT_TERM_CTRL */ + 0x00000000, /* EMC_ZCAL_INTERVAL */ + 0x00000040, /* EMC_ZCAL_WAIT_CNT */ + 0x000c000c, /* EMC_MRS_WAIT_CNT */ + 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */ + 0x00000000, /* EMC_CTT */ + 0x00000000, /* EMC_CTT_DURATION */ + 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */ + 0x00030003, /* MC_EMEM_ARB_CFG */ + 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RC */ + 0x00000000, /* MC_EMEM_ARB_TIMING_RAS */ + 0x00000001, /* MC_EMEM_ARB_TIMING_FAW */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */ + 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */ + 0x00000001, /* MC_EMEM_ARB_TIMING_W2W */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */ + 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */ + 0x06020102, /* MC_EMEM_ARB_DA_TURNS */ + 0x000a0402, /* MC_EMEM_ARB_DA_COVERS */ + 0x74830303, /* MC_EMEM_ARB_MISC0 */ + 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */ + 0xd8000000, /* EMC_FBIO_SPARE */ + 0xff00ff00, /* EMC_CFG_RSV */ + }, + 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */ + 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */ + 0x00000000, /* EMC_CFG.PERIODIC_QRST */ + 0x00001221, /* Mode Register 0 */ + 0x00100003, /* Mode Register 1 */ + 0x00200008, /* Mode Register 2 */ + 0x00000001, /* EMC_CFG.DYN_SELF_REF */ + }, + { + 0x32, /* Rev 3.2 */ + 51000, /* SDRAM frequency */ + { + 0x00000002, /* EMC_RC */ + 0x00000008, /* EMC_RFC */ + 0x00000001, /* EMC_RAS */ + 0x00000000, /* EMC_RP */ + 0x00000002, /* EMC_R2W */ + 0x0000000a, /* EMC_W2R */ + 0x00000003, /* EMC_R2P */ + 0x0000000b, /* EMC_W2P */ + 0x00000000, /* EMC_RD_RCD */ + 0x00000000, /* EMC_WR_RCD */ + 0x00000003, /* EMC_RRD */ + 0x00000001, /* EMC_REXT */ + 0x00000000, /* EMC_WEXT */ + 0x00000005, /* EMC_WDV */ + 0x00000005, /* EMC_QUSE */ + 0x00000004, /* EMC_QRST */ + 0x00000007, /* EMC_QSAFE */ + 0x0000000c, /* EMC_RDV */ + 0x00000181, /* EMC_REFRESH */ + 0x00000000, /* EMC_BURST_REFRESH_NUM */ + 0x00000060, /* EMC_PRE_REFRESH_REQ_CNT */ + 0x00000002, /* EMC_PDEX2WR */ + 0x00000002, /* EMC_PDEX2RD */ + 0x00000001, /* EMC_PCHG2PDEN */ + 0x00000000, /* EMC_ACT2PDEN */ + 0x00000007, /* EMC_AR2PDEN */ + 0x0000000f, /* EMC_RW2PDEN */ + 0x00000009, /* EMC_TXSR */ + 0x00000009, /* EMC_TXSRDLL */ + 0x00000004, /* EMC_TCKE */ + 0x00000002, /* EMC_TFAW */ + 0x00000000, /* EMC_TRPAB */ + 0x00000004, /* EMC_TCLKSTABLE */ + 0x00000005, /* EMC_TCLKSTOP */ + 0x0000018e, /* EMC_TREFBW */ + 0x00000000, /* EMC_QUSE_EXTRA */ + 0x00000004, /* EMC_FBIO_CFG6 */ + 0x00000000, /* EMC_ODT_WRITE */ + 0x00000000, /* EMC_ODT_READ */ + 0x00006288, /* EMC_FBIO_CFG5 */ + 0x007800a4, /* EMC_CFG_DIG_DLL */ + 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ + 0x000fc000, /* EMC_DLL_XFORM_DQS0 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS1 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS2 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS3 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS4 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS5 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS6 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS7 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE3 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE4 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE5 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE6 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE7 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ0 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ1 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ2 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ3 */ + 0x000002a0, /* EMC_XM2CMDPADCTRL */ + 0x0800211c, /* EMC_XM2DQSPADCTRL2 */ + 0x00000000, /* EMC_XM2DQPADCTRL2 */ + 0x77fff884, /* EMC_XM2CLKPADCTRL */ + 0x01f1f108, /* EMC_XM2COMPPADCTRL */ + 0x05057404, /* EMC_XM2VTTGENPADCTRL */ + 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */ + 0x08000168, /* EMC_XM2QUSEPADCTRL */ + 0x08000000, /* EMC_XM2DQSPADCTRL3 */ + 0x00000802, /* EMC_CTT_TERM_CTRL */ + 0x00000000, /* EMC_ZCAL_INTERVAL */ + 0x00000040, /* EMC_ZCAL_WAIT_CNT */ + 0x000c000c, /* EMC_MRS_WAIT_CNT */ + 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */ + 0x00000000, /* EMC_CTT */ + 0x00000000, /* EMC_CTT_DURATION */ + 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ + 0x00010003, /* MC_EMEM_ARB_CFG */ + 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RC */ + 0x00000000, /* MC_EMEM_ARB_TIMING_RAS */ + 0x00000001, /* MC_EMEM_ARB_TIMING_FAW */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */ + 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */ + 0x00000001, /* MC_EMEM_ARB_TIMING_W2W */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */ + 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */ + 0x06020102, /* MC_EMEM_ARB_DA_TURNS */ + 0x000a0402, /* MC_EMEM_ARB_DA_COVERS */ + 0x73430303, /* MC_EMEM_ARB_MISC0 */ + 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */ + 0xd8000000, /* EMC_FBIO_SPARE */ + 0xff00ff00, /* EMC_CFG_RSV */ + }, + 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */ + 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */ + 0x00000000, /* EMC_CFG.PERIODIC_QRST */ + 0x00001221, /* Mode Register 0 */ + 0x00100003, /* Mode Register 1 */ + 0x00200008, /* Mode Register 2 */ + 0x00000001, /* EMC_CFG.DYN_SELF_REF */ + }, + { + 0x32, /* Rev 3.2 */ + 102000, /* SDRAM frequency */ + { + 0x00000004, /* EMC_RC */ + 0x00000010, /* EMC_RFC */ + 0x00000003, /* EMC_RAS */ + 0x00000001, /* EMC_RP */ + 0x00000002, /* EMC_R2W */ + 0x0000000a, /* EMC_W2R */ + 0x00000003, /* EMC_R2P */ + 0x0000000b, /* EMC_W2P */ + 0x00000001, /* EMC_RD_RCD */ + 0x00000001, /* EMC_WR_RCD */ + 0x00000003, /* EMC_RRD */ + 0x00000001, /* EMC_REXT */ + 0x00000000, /* EMC_WEXT */ + 0x00000005, /* EMC_WDV */ + 0x00000005, /* EMC_QUSE */ + 0x00000004, /* EMC_QRST */ + 0x00000007, /* EMC_QSAFE */ + 0x0000000c, /* EMC_RDV */ + 0x00000303, /* EMC_REFRESH */ + 0x00000000, /* EMC_BURST_REFRESH_NUM */ + 0x000000c0, /* EMC_PRE_REFRESH_REQ_CNT */ + 0x00000002, /* EMC_PDEX2WR */ + 0x00000002, /* EMC_PDEX2RD */ + 0x00000001, /* EMC_PCHG2PDEN */ + 0x00000000, /* EMC_ACT2PDEN */ + 0x00000007, /* EMC_AR2PDEN */ + 0x0000000f, /* EMC_RW2PDEN */ + 0x00000012, /* EMC_TXSR */ + 0x00000012, /* EMC_TXSRDLL */ + 0x00000004, /* EMC_TCKE */ + 0x00000004, /* EMC_TFAW */ + 0x00000000, /* EMC_TRPAB */ + 0x00000004, /* EMC_TCLKSTABLE */ + 0x00000005, /* EMC_TCLKSTOP */ + 0x0000031c, /* EMC_TREFBW */ + 0x00000000, /* EMC_QUSE_EXTRA */ + 0x00000004, /* EMC_FBIO_CFG6 */ + 0x00000000, /* EMC_ODT_WRITE */ + 0x00000000, /* EMC_ODT_READ */ + 0x00006288, /* EMC_FBIO_CFG5 */ + 0x007800a4, /* EMC_CFG_DIG_DLL */ + 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ + 0x000fc000, /* EMC_DLL_XFORM_DQS0 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS1 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS2 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS3 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS4 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS5 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS6 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS7 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE3 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE4 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE5 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE6 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE7 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ0 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ1 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ2 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ3 */ + 0x000002a0, /* EMC_XM2CMDPADCTRL */ + 0x0800211c, /* EMC_XM2DQSPADCTRL2 */ + 0x00000000, /* EMC_XM2DQPADCTRL2 */ + 0x77fff884, /* EMC_XM2CLKPADCTRL */ + 0x01f1f108, /* EMC_XM2COMPPADCTRL */ + 0x05057404, /* EMC_XM2VTTGENPADCTRL */ + 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */ + 0x08000168, /* EMC_XM2QUSEPADCTRL */ + 0x08000000, /* EMC_XM2DQSPADCTRL3 */ + 0x00000802, /* EMC_CTT_TERM_CTRL */ + 0x00000000, /* EMC_ZCAL_INTERVAL */ + 0x00000040, /* EMC_ZCAL_WAIT_CNT */ + 0x000c000c, /* EMC_MRS_WAIT_CNT */ + 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */ + 0x00000000, /* EMC_CTT */ + 0x00000000, /* EMC_CTT_DURATION */ + 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ + 0x00000003, /* MC_EMEM_ARB_CFG */ + 0xc0000018, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ + 0x00000003, /* MC_EMEM_ARB_TIMING_RC */ + 0x00000000, /* MC_EMEM_ARB_TIMING_RAS */ + 0x00000001, /* MC_EMEM_ARB_TIMING_FAW */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */ + 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */ + 0x00000001, /* MC_EMEM_ARB_TIMING_W2W */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */ + 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */ + 0x06020102, /* MC_EMEM_ARB_DA_TURNS */ + 0x000a0403, /* MC_EMEM_ARB_DA_COVERS */ + 0x72830504, /* MC_EMEM_ARB_MISC0 */ + 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */ + 0xd8000000, /* EMC_FBIO_SPARE */ + 0xff00ff00, /* EMC_CFG_RSV */ + }, + 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */ + 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */ + 0x00000000, /* EMC_CFG.PERIODIC_QRST */ + 0x00001221, /* Mode Register 0 */ + 0x00100003, /* Mode Register 1 */ + 0x00200008, /* Mode Register 2 */ + 0x00000001, /* EMC_CFG.DYN_SELF_REF */ + }, + { + 0x32, /* Rev 3.2 */ + 333500, /* SDRAM frequency */ + { + 0x0000000f, /* EMC_RC */ + 0x00000034, /* EMC_RFC */ + 0x0000000a, /* EMC_RAS */ + 0x00000003, /* EMC_RP */ + 0x00000003, /* EMC_R2W */ + 0x00000008, /* EMC_W2R */ + 0x00000002, /* EMC_R2P */ + 0x00000009, /* EMC_W2P */ + 0x00000003, /* EMC_RD_RCD */ + 0x00000003, /* EMC_WR_RCD */ + 0x00000002, /* EMC_RRD */ + 0x00000001, /* EMC_REXT */ + 0x00000000, /* EMC_WEXT */ + 0x00000004, /* EMC_WDV */ + 0x00000006, /* EMC_QUSE */ + 0x00000004, /* EMC_QRST */ + 0x0000000a, /* EMC_QSAFE */ + 0x0000000c, /* EMC_RDV */ + 0x000009e9, /* EMC_REFRESH */ + 0x00000000, /* EMC_BURST_REFRESH_NUM */ + 0x0000027a, /* EMC_PRE_REFRESH_REQ_CNT */ + 0x00000001, /* EMC_PDEX2WR */ + 0x00000008, /* EMC_PDEX2RD */ + 0x00000001, /* EMC_PCHG2PDEN */ + 0x00000000, /* EMC_ACT2PDEN */ + 0x00000007, /* EMC_AR2PDEN */ + 0x0000000e, /* EMC_RW2PDEN */ + 0x00000039, /* EMC_TXSR */ + 0x00000200, /* EMC_TXSRDLL */ + 0x00000004, /* EMC_TCKE */ + 0x0000000a, /* EMC_TFAW */ + 0x00000000, /* EMC_TRPAB */ + 0x00000004, /* EMC_TCLKSTABLE */ + 0x00000005, /* EMC_TCLKSTOP */ + 0x00000a2a, /* EMC_TREFBW */ + 0x00000000, /* EMC_QUSE_EXTRA */ + 0x00000006, /* EMC_FBIO_CFG6 */ + 0x00000000, /* EMC_ODT_WRITE */ + 0x00000000, /* EMC_ODT_READ */ + 0x00007088, /* EMC_FBIO_CFG5 */ + 0x00260084, /* EMC_CFG_DIG_DLL */ + 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ + 0x00028000, /* EMC_DLL_XFORM_DQS0 */ + 0x00028000, /* EMC_DLL_XFORM_DQS1 */ + 0x00028000, /* EMC_DLL_XFORM_DQS2 */ + 0x00028000, /* EMC_DLL_XFORM_DQS3 */ + 0x00028000, /* EMC_DLL_XFORM_DQS4 */ + 0x00028000, /* EMC_DLL_XFORM_DQS5 */ + 0x00028000, /* EMC_DLL_XFORM_DQS6 */ + 0x00028000, /* EMC_DLL_XFORM_DQS7 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE3 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE4 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE5 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE6 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE7 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ + 0x0004c000, /* EMC_DLL_XFORM_DQ0 */ + 0x0004c000, /* EMC_DLL_XFORM_DQ1 */ + 0x0004c000, /* EMC_DLL_XFORM_DQ2 */ + 0x0004c000, /* EMC_DLL_XFORM_DQ3 */ + 0x000002a0, /* EMC_XM2CMDPADCTRL */ + 0x0800013d, /* EMC_XM2DQSPADCTRL2 */ + 0x00000000, /* EMC_XM2DQPADCTRL2 */ + 0x77fff884, /* EMC_XM2CLKPADCTRL */ + 0x01f1f508, /* EMC_XM2COMPPADCTRL */ + 0x05057404, /* EMC_XM2VTTGENPADCTRL */ + 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */ + 0x080001e8, /* EMC_XM2QUSEPADCTRL */ + 0x08000021, /* EMC_XM2DQSPADCTRL3 */ + 0x00000802, /* EMC_CTT_TERM_CTRL */ + 0x00020000, /* EMC_ZCAL_INTERVAL */ + 0x00000100, /* EMC_ZCAL_WAIT_CNT */ + 0x014b000c, /* EMC_MRS_WAIT_CNT */ + 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */ + 0x00000000, /* EMC_CTT */ + 0x00000000, /* EMC_CTT_DURATION */ + 0x800014d4, /* EMC_DYN_SELF_REF_CONTROL */ + 0x0000000a, /* MC_EMEM_ARB_CFG */ + 0xc000003d, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ + 0x00000008, /* MC_EMEM_ARB_TIMING_RC */ + 0x00000004, /* MC_EMEM_ARB_TIMING_RAS */ + 0x00000004, /* MC_EMEM_ARB_TIMING_FAW */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */ + 0x00000007, /* MC_EMEM_ARB_TIMING_WAP2PRE */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */ + 0x00000002, /* MC_EMEM_ARB_TIMING_W2W */ + 0x00000003, /* MC_EMEM_ARB_TIMING_R2W */ + 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */ + 0x06030202, /* MC_EMEM_ARB_DA_TURNS */ + 0x000b0608, /* MC_EMEM_ARB_DA_COVERS */ + 0x70850f09, /* MC_EMEM_ARB_MISC0 */ + 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */ + 0xe8000000, /* EMC_FBIO_SPARE */ + 0xff00ff88, /* EMC_CFG_RSV */ + }, + 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */ + 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */ + 0x00000000, /* EMC_CFG.PERIODIC_QRST */ + 0x00000321, /* Mode Register 0 */ + 0x00100002, /* Mode Register 1 */ + 0x00200000, /* Mode Register 2 */ + 0x00000000, /* EMC_CFG.DYN_SELF_REF */ + }, + { + 0x32, /* Rev 3.2 */ + 667000, /* SDRAM frequency */ + { + 0x0000001f, /* EMC_RC */ + 0x00000069, /* EMC_RFC */ + 0x00000016, /* EMC_RAS */ + 0x00000008, /* EMC_RP */ + 0x00000005, /* EMC_R2W */ + 0x0000000c, /* EMC_W2R */ + 0x00000003, /* EMC_R2P */ + 0x00000011, /* EMC_W2P */ + 0x00000008, /* EMC_RD_RCD */ + 0x00000008, /* EMC_WR_RCD */ + 0x00000002, /* EMC_RRD */ + 0x00000001, /* EMC_REXT */ + 0x00000000, /* EMC_WEXT */ + 0x00000007, /* EMC_WDV */ + 0x0000000b, /* EMC_QUSE */ + 0x00000009, /* EMC_QRST */ + 0x0000000c, /* EMC_QSAFE */ + 0x00000011, /* EMC_RDV */ + 0x00001412, /* EMC_REFRESH */ + 0x00000000, /* EMC_BURST_REFRESH_NUM */ + 0x00000504, /* EMC_PRE_REFRESH_REQ_CNT */ + 0x00000002, /* EMC_PDEX2WR */ + 0x0000000e, /* EMC_PDEX2RD */ + 0x00000001, /* EMC_PCHG2PDEN */ + 0x00000000, /* EMC_ACT2PDEN */ + 0x0000000c, /* EMC_AR2PDEN */ + 0x00000016, /* EMC_RW2PDEN */ + 0x00000072, /* EMC_TXSR */ + 0x00000200, /* EMC_TXSRDLL */ + 0x00000005, /* EMC_TCKE */ + 0x00000015, /* EMC_TFAW */ + 0x00000000, /* EMC_TRPAB */ + 0x00000006, /* EMC_TCLKSTABLE */ + 0x00000007, /* EMC_TCLKSTOP */ + 0x00001453, /* EMC_TREFBW */ + 0x0000000c, /* EMC_QUSE_EXTRA */ + 0x00000004, /* EMC_FBIO_CFG6 */ + 0x00000000, /* EMC_ODT_WRITE */ + 0x00000000, /* EMC_ODT_READ */ + 0x00005088, /* EMC_FBIO_CFG5 */ + 0xf00b0191, /* EMC_CFG_DIG_DLL */ + 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ + 0x00000008, /* EMC_DLL_XFORM_DQS0 */ + 0x00000008, /* EMC_DLL_XFORM_DQS1 */ + 0x00000008, /* EMC_DLL_XFORM_DQS2 */ + 0x00000008, /* EMC_DLL_XFORM_DQS3 */ + 0x00000008, /* EMC_DLL_XFORM_DQS4 */ + 0x00000008, /* EMC_DLL_XFORM_DQS5 */ + 0x00000008, /* EMC_DLL_XFORM_DQS6 */ + 0x00000008, /* EMC_DLL_XFORM_DQS7 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE3 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE4 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE5 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE6 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE7 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ + 0x00000008, /* EMC_DLL_XFORM_DQ0 */ + 0x00000008, /* EMC_DLL_XFORM_DQ1 */ + 0x00000008, /* EMC_DLL_XFORM_DQ2 */ + 0x00000008, /* EMC_DLL_XFORM_DQ3 */ + 0x000002a0, /* EMC_XM2CMDPADCTRL */ + 0x0600013d, /* EMC_XM2DQSPADCTRL2 */ + 0x00000000, /* EMC_XM2DQPADCTRL2 */ + 0x77fff884, /* EMC_XM2CLKPADCTRL */ + 0x01f1f508, /* EMC_XM2COMPPADCTRL */ + 0x07077404, /* EMC_XM2VTTGENPADCTRL */ + 0x54000000, /* EMC_XM2VTTGENPADCTRL2 */ + 0x080001e8, /* EMC_XM2QUSEPADCTRL */ + 0x07000021, /* EMC_XM2DQSPADCTRL3 */ + 0x00000802, /* EMC_CTT_TERM_CTRL */ + 0x00020000, /* EMC_ZCAL_INTERVAL */ + 0x00000100, /* EMC_ZCAL_WAIT_CNT */ + 0x0116000c, /* EMC_MRS_WAIT_CNT */ + 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */ + 0x00000000, /* EMC_CTT */ + 0x00000000, /* EMC_CTT_DURATION */ + 0x800028a5, /* EMC_DYN_SELF_REF_CONTROL */ + 0x00000014, /* MC_EMEM_ARB_CFG */ + 0xc0000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000003, /* MC_EMEM_ARB_TIMING_RCD */ + 0x00000004, /* MC_EMEM_ARB_TIMING_RP */ + 0x00000010, /* MC_EMEM_ARB_TIMING_RC */ + 0x0000000a, /* MC_EMEM_ARB_TIMING_RAS */ + 0x0000000a, /* MC_EMEM_ARB_TIMING_FAW */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */ + 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */ + 0x0000000b, /* MC_EMEM_ARB_TIMING_WAP2PRE */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */ + 0x00000002, /* MC_EMEM_ARB_TIMING_W2W */ + 0x00000004, /* MC_EMEM_ARB_TIMING_R2W */ + 0x00000008, /* MC_EMEM_ARB_TIMING_W2R */ + 0x08040202, /* MC_EMEM_ARB_DA_TURNS */ + 0x00140c10, /* MC_EMEM_ARB_DA_COVERS */ + 0x70ea1f11, /* MC_EMEM_ARB_MISC0 */ + 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */ + 0xf8000000, /* EMC_FBIO_SPARE */ + 0xff00ff01, /* EMC_CFG_RSV */ + }, + 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */ + 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */ + 0x00000001, /* EMC_CFG.PERIODIC_QRST */ + 0x00000b71, /* Mode Register 0 */ + 0x00100002, /* Mode Register 1 */ + 0x00200018, /* Mode Register 2 */ + 0x00000000, /* EMC_CFG.DYN_SELF_REF */ + }, +}; + static const u32 pm269_bit_swap_map[32] = { /* DDR bit # SoC bit # */ [0] = 0x1 << 1, @@ -6231,6 +6834,9 @@ int cardhu_emc_init(void) SKU_MEMORY_CARDHU_2GB_1R_HYNIX) tegra_init_emc(cardhu_emc_tables_h5tc2g_a2_2GB1R, ARRAY_SIZE(cardhu_emc_tables_h5tc2g_a2_2GB1R)); + else if (MEMORY_TYPE(board.sku) == SKU_MEMORY_CARDHU_2GB_2R) + tegra_init_emc(cardhu_emc_tables_h5tc2g_a2_2g2r, + ARRAY_SIZE(cardhu_emc_tables_h5tc2g_a2_2g2r)); break; } -- cgit v1.2.3 From 2fee002b48324b80ea63c645bfd82ae782c6f968 Mon Sep 17 00:00:00 2001 From: Ilan Aelion Date: Sun, 5 Aug 2012 06:56:40 -0600 Subject: misc: tegra-throughput: prevent race on init prevent a race condition on initialization which could result in multiple notifier registrations. Bug 1027664 Change-Id: I2e7dcad159f631a7e244d43019169fdaf195bc34 Signed-off-by: Ilan Aelion Reviewed-on: http://git-master/r/121140 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bharat Nihalani Reviewed-by: Peter Boonstoppel Reviewed-by: Jon Mayo GVS: Gerrit_Virtual_Submit --- drivers/misc/tegra-throughput.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/misc/tegra-throughput.c b/drivers/misc/tegra-throughput.c index 77eb7c31ed36..c90a6a00a1a0 100644 --- a/drivers/misc/tegra-throughput.c +++ b/drivers/misc/tegra-throughput.c @@ -98,19 +98,24 @@ static int notifier_initialized; static int throughput_open(struct inode *inode, struct file *file) { + int need_init = 0; + + spin_lock(&lock); + if (!notifier_initialized) { - tegra_dc_register_flip_notifier(&throughput_flip_nb); notifier_initialized = 1; + need_init = 1; } - spin_lock(&lock); - throughput_active_app_count++; if (throughput_active_app_count > 1) multiple_app_disable = 1; spin_unlock(&lock); + if (need_init) + tegra_dc_register_flip_notifier(&throughput_flip_nb); + pr_debug("throughput_open node %p file %p\n", inode, file); return 0; @@ -118,17 +123,22 @@ static int throughput_open(struct inode *inode, struct file *file) static int throughput_release(struct inode *inode, struct file *file) { + int need_deinit = 0; + spin_lock(&lock); - throughput_active_app_count--; - spin_unlock(&lock); + throughput_active_app_count--; if (throughput_active_app_count == 0) { reset_target_frame_time(); multiple_app_disable = 0; - tegra_dc_unregister_flip_notifier(&throughput_flip_nb); notifier_initialized = 0; + need_deinit = 1; } + spin_unlock(&lock); + + if (need_deinit) + tegra_dc_unregister_flip_notifier(&throughput_flip_nb); pr_debug("throughput_release node %p file %p\n", inode, file); -- cgit v1.2.3 From 871ddb4695625921857d29375fc2ac9522431c48 Mon Sep 17 00:00:00 2001 From: Xiaohui Tao Date: Wed, 1 Aug 2012 17:28:31 -0700 Subject: kernel/arch: Cardhu: Decrease sensitivity of touch Decrease the sensitivity threshold of touch. It might still cause false touches. May decrease the performance. BUG 1025873 Change-Id: I9c287a07b470878b05e2e5684a296fbfb5f22aad Signed-off-by: Xiaohui Tao Reviewed-on: http://git-master/r/120454 Reviewed-by: Robert Collins Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: David Jung GVS: Gerrit_Virtual_Submit Reviewed-by: Pradeep Thiruchelvam --- arch/arm/mach-tegra/board-cardhu.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu.c b/arch/arm/mach-tegra/board-cardhu.c index 16ad11943533..577d8593dfd0 100644 --- a/arch/arm/mach-tegra/board-cardhu.c +++ b/arch/arm/mach-tegra/board-cardhu.c @@ -878,12 +878,12 @@ static const u8 e1506_config[] = { 0x00 }; -#define MXT_CONFIG_CRC 0xD62DE8 +#define MXT_CONFIG_CRC 0x362575 static const u8 config[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x0A, 0x00, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, - 0x1B, 0x2A, 0x00, 0x20, 0x3C, 0x04, 0x05, 0x00, + 0x1B, 0x2A, 0x00, 0x20, 0x70, 0x04, 0x05, 0x00, 0x02, 0x01, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0xFF, 0x02, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x02, 0x00, 0x00, 0x00, @@ -902,12 +902,12 @@ static const u8 config[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -#define MXT_CONFIG_CRC_SKU2000 0xA24D9A +#define MXT_CONFIG_CRC_SKU2000 0xD6CDCD static const u8 config_sku2000[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x32, 0x0A, 0x00, 0x14, 0x14, 0x19, + 0xFF, 0xFF, 0x32, 0x0A, 0x00, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, - 0x1B, 0x2A, 0x00, 0x20, 0x3A, 0x04, 0x05, 0x00, //23=thr 2 di + 0x1B, 0x2A, 0x00, 0x20, 0x70, 0x04, 0x05, 0x00, //23=thr 2 di 0x04, 0x04, 0x41, 0x0A, 0x0A, 0x0A, 0x0A, 0xFF, 0x02, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, //0A=limit -- cgit v1.2.3 From bd3100fb8f3f59678d6b67d5eb8a9e0fba48bfee Mon Sep 17 00:00:00 2001 From: Jihoon Bang Date: Tue, 19 Jun 2012 16:12:00 -0700 Subject: WAR: gr3d: limit 3d clock when camera is on As WAR, limit 3d clock frequency and emc clock frequency when camera is on and chip is AP37. 3d clock is set to 361MHz and 437MHz is requested for emc clock with this change. This change allows 3d to request 1.1V in Core instead of 1.3V in AP37. Bug 1001262 Bug 1019309 Signed-off-by: Jihoon Bang Change-Id: I1dbab3469a31ef603f7665fc5a6cb5c1999f89b6 Reviewed-on: http://git-master/r/120480 Reviewed-by: Varun Colbert Tested-by: Varun Colbert --- arch/arm/mach-tegra/board-cardhu.c | 19 ++++++++++++++++ drivers/media/video/tegra/tegra_camera.c | 24 +++++++++++++++++++- drivers/video/tegra/host/gr3d/scale3d.c | 38 ++++++++++++++++++++++++++------ include/media/tegra_camera.h | 10 +++++++++ 4 files changed, 83 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu.c b/arch/arm/mach-tegra/board-cardhu.c index 577d8593dfd0..3f0f19612d0d 100644 --- a/arch/arm/mach-tegra/board-cardhu.c +++ b/arch/arm/mach-tegra/board-cardhu.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -628,11 +629,28 @@ static void __init cardhu_uart_init(void) ARRAY_SIZE(cardhu_uart_devices)); } +static struct tegra_camera_platform_data tegra_camera_pdata = { + .limit_3d_emc_clk = false, +}; + static struct platform_device tegra_camera = { .name = "tegra_camera", + .dev = { + .platform_data = &tegra_camera_pdata, + }, .id = -1, }; +static void tegra_camera_init(void) +{ + /* For AP37 platform, limit 3d and emc freq when camera is ON */ + if (TEGRA_REVISION_A03 == tegra_get_revision() && + 0xA0 == tegra_sku_id()) + tegra_camera_pdata.limit_3d_emc_clk = true; + else + tegra_camera_pdata.limit_3d_emc_clk = false; +} + static struct platform_device *cardhu_spi_devices[] __initdata = { &tegra_spi_device4, }; @@ -1440,6 +1458,7 @@ static void __init tegra_cardhu_init(void) cardhu_edp_init(); #endif cardhu_uart_init(); + tegra_camera_init(); platform_add_devices(cardhu_devices, ARRAY_SIZE(cardhu_devices)); tegra_ram_console_debug_init(); tegra_io_dpd_init(); diff --git a/drivers/media/video/tegra/tegra_camera.c b/drivers/media/video/tegra/tegra_camera.c index 03eecf464c48..2b0cd005096c 100644 --- a/drivers/media/video/tegra/tegra_camera.c +++ b/drivers/media/video/tegra/tegra_camera.c @@ -2,7 +2,7 @@ * drivers/media/video/tegra/tegra_camera.c * * Copyright (C) 2010 Google, Inc. - * Copyright (C) 2012 Nvidia Corp + * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -58,6 +58,25 @@ struct tegra_camera_block { bool is_enabled; }; +/* + * Declare and define two static variables to provide hint to + * gr3d module + */ +static int tegra_camera_on; +static struct tegra_camera_platform_data *pdata; + +int is_tegra_camera_on(void) +{ + if (pdata) { + if (pdata->limit_3d_emc_clk) + return tegra_camera_on; + else + return 0; + } else { + return 0; + } +} + static int tegra_camera_enable_clk(struct tegra_camera_dev *dev) { clk_enable(dev->vi_clk); @@ -227,6 +246,7 @@ static int tegra_camera_power_on(struct tegra_camera_dev *dev) __func__); #endif dev->power_on = 1; + tegra_camera_on = dev->power_on; return ret; } @@ -255,6 +275,7 @@ static int tegra_camera_power_off(struct tegra_camera_dev *dev) } } dev->power_on = 0; + tegra_camera_on = dev->power_on; return ret; } @@ -425,6 +446,7 @@ static int tegra_camera_probe(struct platform_device *pdev) mutex_unlock(&dev->tegra_camera_lock); dev->dev = &pdev->dev; + pdata = pdev->dev.platform_data; /* Get regulator pointer */ #ifdef CONFIG_ARCH_TEGRA_2x_SOC diff --git a/drivers/video/tegra/host/gr3d/scale3d.c b/drivers/video/tegra/host/gr3d/scale3d.c index 9a6a8e73b513..fc30c2259ad4 100644 --- a/drivers/video/tegra/host/gr3d/scale3d.c +++ b/drivers/video/tegra/host/gr3d/scale3d.c @@ -3,7 +3,7 @@ * * Tegra Graphics Host 3D clock scaling * - * Copyright (c) 2010-2012, NVIDIA Corporation. + * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -41,12 +41,22 @@ #include #include "scale3d.h" #include "dev.h" +#include static int scale3d_is_enabled(void); static void scale3d_enable(int enable); #define POW2(x) ((x) * (x)) +/* + * 3D clock scaling should be treated differently when camera is on in AP37. + * 3D in AP37 requires 1.3V and combining it with MPE reaches to EDP limit. + * 3D clock really needs to be set to lower frequency which requires 1.0V. + * The same thing applies to 3D EMC clock. + */ +#define CAMERA_3D_CLK 300000000 +#define CAMERA_3D_EMC_CLK 437000000 + /* * debugfs parameters to control 3d clock scaling test * @@ -169,12 +179,26 @@ void nvhost_scale3d_suspend(struct nvhost_device *dev) static void reset_3d_clocks(void) { if (clk_get_rate(scale3d.clk_3d) != scale3d.max_rate_3d) { - clk_set_rate(scale3d.clk_3d, scale3d.max_rate_3d); - if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA3) - clk_set_rate(scale3d.clk_3d2, scale3d.max_rate_3d); - if (scale3d.p_scale_emc) - clk_set_rate(scale3d.clk_3d_emc, - clk_round_rate(scale3d.clk_3d_emc, UINT_MAX)); + if (is_tegra_camera_on()) + clk_set_rate(scale3d.clk_3d, CAMERA_3D_CLK); + else + clk_set_rate(scale3d.clk_3d, scale3d.max_rate_3d); + if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA3) { + if (is_tegra_camera_on()) + clk_set_rate(scale3d.clk_3d2, CAMERA_3D_CLK); + else + clk_set_rate(scale3d.clk_3d2, + scale3d.max_rate_3d); + } + if (scale3d.p_scale_emc) { + if (is_tegra_camera_on()) + clk_set_rate(scale3d.clk_3d_emc, + CAMERA_3D_EMC_CLK); + else + clk_set_rate(scale3d.clk_3d_emc, + clk_round_rate(scale3d.clk_3d_emc, + UINT_MAX)); + } } } diff --git a/include/media/tegra_camera.h b/include/media/tegra_camera.h index 9dea1485781d..3c41864cc71f 100644 --- a/include/media/tegra_camera.h +++ b/include/media/tegra_camera.h @@ -2,6 +2,7 @@ * include/linux/tegra_camera.h * * Copyright (C) 2010 Google, Inc. + * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -48,6 +49,15 @@ enum StereoCameraMode { StereoCameraMode_Force32 = 0x7FFFFFFF }; +struct tegra_camera_platform_data { + bool limit_3d_emc_clk; +}; + +#if defined(CONFIG_TEGRA_CAMERA) +int is_tegra_camera_on(void); +#else +int is_tegra_camera_on(void) { return 0; } +#endif #define TEGRA_CAMERA_IOCTL_ENABLE _IOWR('i', 1, uint) #define TEGRA_CAMERA_IOCTL_DISABLE _IOWR('i', 2, uint) -- cgit v1.2.3 From 7d4e0461a88b8cf638963e69829274824fecc38b Mon Sep 17 00:00:00 2001 From: Marvin Zhang Date: Thu, 2 Aug 2012 17:03:21 -0700 Subject: video: tegra: dc: move set default videomode out of _tegra_dc_enable. Set default videomode happens during probe and resume. _tegra_dc_enable is also called during hotplug, setting default videomode there causes hdcp test failure. Bug 991805 Change-Id: I8a5355d764cbcd386f5749430b42f2226ea44ebe Signed-off-by: Marvin Zhang Reviewed-on: http://git-master/r/121052 Reviewed-by: Gaurav Sarode Tested-by: Gaurav Sarode Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bharat Nihalani GVS: Gerrit_Virtual_Submit Reviewed-by: Jon Mayo --- drivers/video/tegra/dc/dc.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index db97ed3d3c13..da7f2910bb25 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -1397,11 +1397,6 @@ static bool _tegra_dc_controller_reset_enable(struct tegra_dc *dc) #endif static int _tegra_dc_set_default_videomode(struct tegra_dc *dc) -{ - return tegra_dc_set_fb_mode(dc, &tegra_dc_hdmi_fallback_mode, 0); -} - -static bool _tegra_dc_enable(struct tegra_dc *dc) { if (dc->mode.pclk == 0) { switch (dc->out->type) { @@ -1409,8 +1404,8 @@ static bool _tegra_dc_enable(struct tegra_dc *dc) /* DC enable called but no videomode is loaded. Check if HDMI is connected, then set fallback mdoe */ if (tegra_dc_hpd(dc)) { - if (_tegra_dc_set_default_videomode(dc)) - return false; + return tegra_dc_set_fb_mode(dc, + &tegra_dc_hdmi_fallback_mode, 0); } else return false; @@ -1426,6 +1421,14 @@ static bool _tegra_dc_enable(struct tegra_dc *dc) } } + return false; +} + +static bool _tegra_dc_enable(struct tegra_dc *dc) +{ + if (dc->mode.pclk == 0) + return false; + if (!dc->out) return false; @@ -1810,8 +1813,10 @@ static int tegra_dc_probe(struct nvhost_device *ndev, } mutex_lock(&dc->lock); - if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED) + if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED) { dc->enabled = _tegra_dc_enable(dc); + _tegra_dc_set_default_videomode(dc); + } mutex_unlock(&dc->lock); /* interrupt handler must be registered before tegra_fb_register() */ @@ -1959,8 +1964,10 @@ static int tegra_dc_resume(struct nvhost_device *ndev) mutex_lock(&dc->lock); dc->suspended = false; - if (dc->enabled) + if (dc->enabled) { _tegra_dc_enable(dc); + _tegra_dc_set_default_videomode(dc); + } if (dc->out && dc->out->hotplug_init) dc->out->hotplug_init(); -- cgit v1.2.3 From c3f12874f0eab8b8821f9e1314f9706d068bb5fc Mon Sep 17 00:00:00 2001 From: Tom Cherry Date: Tue, 8 May 2012 15:41:16 -0700 Subject: arm: tegra: enterprise: change BB to DAP5 from DAP3 for A04 Due to a hardware issue, Audio Baseband lines are changed for A04 board from DAP3 to DAP5. All other boards retain the same older line Bug 980383 Bug 1014702 Change-Id: If9ecfaa7328a9a7148f95d604926975172c0886a Signed-off-by: Tom Cherry Reviewed-on: http://git-master/r/105168 (cherry picked from commit 65688c4123a896291b5d08e511a609aaedd1b319) Reviewed-on: http://git-master/r/121107 Reviewed-by: Manish Tuteja Tested-by: Manish Tuteja Reviewed-by: Automatic_Commit_Validation_User --- arch/arm/mach-tegra/board-enterprise-pinmux.c | 6 +++--- arch/arm/mach-tegra/board-enterprise.c | 31 +++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-tegra/board-enterprise-pinmux.c b/arch/arm/mach-tegra/board-enterprise-pinmux.c index c946d2ee5f40..4fcd7360833c 100644 --- a/arch/arm/mach-tegra/board-enterprise-pinmux.c +++ b/arch/arm/mach-tegra/board-enterprise-pinmux.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-enterprise-pinmux.c * - * Copyright (C) 2011 NVIDIA Corporation + * Copyright (C) 2011-2012, NVIDIA CORPORATION. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -276,8 +276,8 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_common[] = { DEFAULT_PINMUX(GMI_A18, UARTD, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(GMI_A19, UARTD, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(CAM_MCLK, VI_ALT2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PCC1, RSVD1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PBB0, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PCC1, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB0, I2S4, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(GPIO_PBB3, VGP3, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(GPIO_PBB7, I2S4, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(GPIO_PCC2, I2S4, NORMAL, NORMAL, INPUT), diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c index f9791a7b0e48..6f872264a43e 100644 --- a/arch/arm/mach-tegra/board-enterprise.c +++ b/arch/arm/mach-tegra/board-enterprise.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-enterprise.c * - * Copyright (c) 2011-2012, NVIDIA Corporation. + * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -182,7 +182,6 @@ static __initdata struct tegra_clk_init_table enterprise_clk_init_table[] = { { "blink", "clk_32k", 32768, true}, { "i2s0", "pll_a_out0", 0, false}, { "i2s1", "pll_a_out0", 0, false}, - { "i2s2", "pll_a_out0", 0, false}, { "i2s3", "pll_a_out0", 0, false}, { "spdif_out", "pll_a_out0", 0, false}, { "d_audio", "clk_m", 12000000, false}, @@ -198,6 +197,18 @@ static __initdata struct tegra_clk_init_table enterprise_clk_init_table[] = { { NULL, NULL, 0, 0}, }; +static __initdata struct tegra_clk_init_table enterprise_clk_i2s2_table[] = { + /* name parent rate enabled */ + { "i2s2", "pll_a_out0", 0, false}, + { NULL, NULL, 0, 0}, +}; + +static __initdata struct tegra_clk_init_table enterprise_clk_i2s4_table[] = { + /* name parent rate enabled */ + { "i2s4", "pll_a_out0", 0, false}, + { NULL, NULL, 0, 0}, +}; + static struct tegra_i2c_platform_data enterprise_i2c1_platform_data = { .adapter_nr = 0, .bus_count = 1, @@ -507,7 +518,6 @@ static struct tegra_asoc_platform_data enterprise_audio_pdata = { .sample_size = 16, }, .i2s_param[BASEBAND] = { - .audio_port_id = 2, .is_i2s_master = 1, .i2s_mode = TEGRA_DAIFMT_DSP_A, .sample_size = 16, @@ -850,7 +860,6 @@ static struct platform_device *enterprise_audio_devices[] __initdata = { &tegra_dam_device2, &tegra_i2s_device0, &tegra_i2s_device1, - &tegra_i2s_device2, &tegra_i2s_device3, &tegra_spdif_device, &spdif_dit_device, @@ -869,6 +878,13 @@ static void enterprise_audio_init(void) if (board_info.board_id == BOARD_E1197) enterprise_audio_pdata.i2s_param[HIFI_CODEC].audio_port_id = 1; + else if (board_info.fab == BOARD_FAB_A04) { + enterprise_audio_pdata.i2s_param[BASEBAND].audio_port_id = 4; + platform_device_register(&tegra_i2s_device4); + } else { + enterprise_audio_pdata.i2s_param[BASEBAND].audio_port_id = 2; + platform_device_register(&tegra_i2s_device2); + } platform_add_devices(enterprise_audio_devices, ARRAY_SIZE(enterprise_audio_devices)); @@ -979,6 +995,13 @@ static void enterprise_nfc_init(void) static void __init tegra_enterprise_init(void) { + struct board_info board_info; + tegra_get_board_info(&board_info); + if (board_info.fab == BOARD_FAB_A04) + tegra_clk_init_from_table(enterprise_clk_i2s4_table); + else + tegra_clk_init_from_table(enterprise_clk_i2s2_table); + tegra_thermal_init(&thermal_data, throttle_list, ARRAY_SIZE(throttle_list)); -- cgit v1.2.3 From d13f5c641280e4799dc1dcf7490b343100c5973a Mon Sep 17 00:00:00 2001 From: Xiaohui Tao Date: Mon, 6 Aug 2012 17:44:36 -0700 Subject: kernel/drivers: Atmel: Increase input_dev buf size Multi-touch causes a lot of events being generated. Increase the buffer size so that it does not queue up very rapidly. May still cause the screen to become slow. BUG 1025871 Change-Id: If4488e38c88f0a533d7deb5654f67ca896f9f344 Signed-off-by: Xiaohui Tao Reviewed-on: http://git-master/r/121497 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: David Jung GVS: Gerrit_Virtual_Submit Reviewed-by: Robert Collins Reviewed-by: Dan Willemsen --- drivers/input/touchscreen/atmel_mxt_ts.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index ad21ef9c0105..cfa7a1493724 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -3,7 +3,7 @@ * * Copyright (C) 2010 Samsung Electronics Co.Ltd * Copyright (C) 2011 Atmel Corporation - * Copyright (C) 2011 NVIDIA Corporation + * Copyright (C) 2011-2012 NVIDIA Corporation * Author: Joonyoung Shim * * This program is free software; you can redistribute it and/or modify it @@ -1642,6 +1642,7 @@ static int __devinit mxt_probe(struct i2c_client *client, input_dev->dev.parent = &client->dev; input_dev->open = mxt_input_open; input_dev->close = mxt_input_close; + input_dev->hint_events_per_packet = 256U; data->client = client; data->input_dev = input_dev; -- cgit v1.2.3 From 6c0e907b437765fb9f7093599911b71a836d49a6 Mon Sep 17 00:00:00 2001 From: Ilan Aelion Date: Tue, 7 Aug 2012 09:27:45 -0600 Subject: misc: tegra-throughput: warn on short frames issue a warning on flip events less than 1 microsecond apart. Bug 1027664 Bug 1028850 Change-Id: I5dff33baf7dc568687468beab598f3d113985c8d Signed-off-by: Ilan Aelion Reviewed-on: http://git-master/r/121810 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Sang-Hun Lee Reviewed-by: Donghan Ryu Reviewed-by: Varun Wadekar Tested-by: Donghan Ryu --- drivers/misc/tegra-throughput.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/misc/tegra-throughput.c b/drivers/misc/tegra-throughput.c index c90a6a00a1a0..bff53235a74c 100644 --- a/drivers/misc/tegra-throughput.c +++ b/drivers/misc/tegra-throughput.c @@ -57,8 +57,11 @@ static int throughput_flip_notifier(struct notifier_block *nb, else last_frame_time = (unsigned short) timediff; - if (last_frame_time == 0) + if (last_frame_time == 0) { + pr_warn("%s: notifications %lld nsec apart\n", + __func__, now.tv64 - last_flip.tv64); return NOTIFY_DONE; + } throughput_hint = ((int) target_frame_time * 100)/last_frame_time; -- cgit v1.2.3 From 20af69b17e8acdee573eab7e24a7d9d4fed326c0 Mon Sep 17 00:00:00 2001 From: Prem Sasidharan Date: Fri, 27 Jul 2012 15:22:15 -0700 Subject: arm: tegra: cardhu: Disable ACCELIRQ Setting MPU_ACCEL_IRQ_GPIO to 0. This helps prevent creation of device node /dev/accelirq and enable timerirq to provide polling ticks for the MPU sensors. The MPU sensors are not currently operating in interrupt mode, the sensors needs to be polled at regular interval. MPU sensor HAL enables the polling timer in the absense of /dev/accelirq device node. Bug 947670 Signed-off-by: Prem Sasidharan Change-Id: I8a2c60da00e7d288ec785aa204bdb3207d717028 (cherry picked from commit 27e76e47b5998941259b7ba3ffb77a486760e2c1) Reviewed-on: http://git-master/r/120255 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Wen Yi Reviewed-by: Robert Collins Reviewed-by: Erik Lilliebjerg Reviewed-by: Bharat Nihalani --- arch/arm/mach-tegra/board-cardhu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-tegra/board-cardhu.h b/arch/arm/mach-tegra/board-cardhu.h index 7c6a132421f0..3dd3d23d9414 100644 --- a/arch/arm/mach-tegra/board-cardhu.h +++ b/arch/arm/mach-tegra/board-cardhu.h @@ -231,7 +231,7 @@ extern struct tegra_uart_platform_data cardhu_irda_pdata; #define MPU_GYRO_BUS_NUM 2 #define MPU_GYRO_ORIENTATION { 0, -1, 0, -1, 0, 0, 0, 0, -1 } #define MPU_ACCEL_NAME "kxtf9" -#define MPU_ACCEL_IRQ_GPIO TEGRA_GPIO_PL1 +#define MPU_ACCEL_IRQ_GPIO 0 /* DISABLE ACCELIRQ: TEGRA_GPIO_PL1 */ #define MPU_ACCEL_ADDR 0x0F #define MPU_ACCEL_BUS_NUM 2 #define MPU_ACCEL_ORIENTATION { 0, -1, 0, -1, 0, 0, 0, 0, -1 } -- cgit v1.2.3 From cef956d07ec717f4714f5101805bbe2f0f149e71 Mon Sep 17 00:00:00 2001 From: Nuno Subtil Date: Mon, 6 Aug 2012 22:11:01 -0700 Subject: video: tegra: host: invalidate FDC before context save Invalidate the FDC before submitting the context save pushbuffer to ensure cache coherency across both GPU cores. Bug 1020291 Change-Id: I595d16f42b03edd6f0938741905f1f94211c3962 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/121945 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Daniel Parker GVS: Gerrit_Virtual_Submit --- drivers/video/tegra/host/gr3d/gr3d.h | 3 +++ drivers/video/tegra/host/gr3d/gr3d_t30.c | 12 +++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/video/tegra/host/gr3d/gr3d.h b/drivers/video/tegra/host/gr3d/gr3d.h index 3855b237b702..61f708cea95c 100644 --- a/drivers/video/tegra/host/gr3d/gr3d.h +++ b/drivers/video/tegra/host/gr3d/gr3d.h @@ -29,6 +29,9 @@ #define AR3D_PSEQ_QUAD_ID 0x545 #define AR3D_DW_MEMORY_OUTPUT_ADDRESS 0x904 #define AR3D_DW_MEMORY_OUTPUT_DATA 0x905 +#define AR3D_FDC_CONTROL_0 0xa00 +#define AR3D_FDC_CONTROL_0_RESET_VAL 0xe00 +#define AR3D_FDC_CONTROL_0_INVALIDATE 1 #define AR3D_GSHIM_WRITE_MASK 0xb00 #define AR3D_GSHIM_READ_SELECT 0xb01 #define AR3D_GLOBAL_MEMORY_OUTPUT_READS 0xe40 diff --git a/drivers/video/tegra/host/gr3d/gr3d_t30.c b/drivers/video/tegra/host/gr3d/gr3d_t30.c index c35fea2f3ac2..5e26a6ff90ae 100644 --- a/drivers/video/tegra/host/gr3d/gr3d_t30.c +++ b/drivers/video/tegra/host/gr3d/gr3d_t30.c @@ -125,6 +125,16 @@ static void save_push_v1(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma) nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0), NVHOST_OPCODE_NOOP); + /* invalidate the FDC to prevent cache-coherency issues across GPUs + note that we assume FDC_CONTROL_0 is left in the reset state by all + contexts. the invalidate bit will clear itself, so the register + should be unchanged after this */ + nvhost_cdma_push(cdma, + nvhost_opcode_imm(AR3D_FDC_CONTROL_0, + AR3D_FDC_CONTROL_0_RESET_VAL + | AR3D_FDC_CONTROL_0_INVALIDATE), + NVHOST_OPCODE_NOOP); + /* set register set 0 and 1 register read memory output addresses, and send their reads to memory */ @@ -132,7 +142,7 @@ static void save_push_v1(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma) nvhost_opcode_imm(AR3D_GSHIM_WRITE_MASK, 2), nvhost_opcode_imm(AR3D_GLOBAL_MEMORY_OUTPUT_READS, 1)); nvhost_cdma_push(cdma, - nvhost_opcode_nonincr(0x904, 1), + nvhost_opcode_nonincr(AR3D_DW_MEMORY_OUTPUT_ADDRESS, 1), ctx->restore_phys + restore_set1_offset * 4); nvhost_cdma_push(cdma, -- cgit v1.2.3 From f691268c138b9ed31b3867b049e64c121ecb188e Mon Sep 17 00:00:00 2001 From: Wen Yi Date: Wed, 8 Aug 2012 11:36:04 -0700 Subject: arm: cardhu: correct EMEM_ARB_CFG in emc dfs table The memory frequencies 266.5mhz and 437mhz have incorrect EMEM_ARB_CFG set in emc table of Samsung part. That resulted in emc scaling completely disabled and emc runs at 533mhz all time. The settings have been corrected to 0x00000008 and 0x0000000D. Bug 1030392 Change-Id: I2ca9b1d8b93fbf292b33e8f39ee77a00cd11b2a6 Signed-off-by: Wen Yi Reviewed-on: http://git-master/r/122163 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Raymond Poudrier Reviewed-by: Aleksandr Frid Reviewed-by: Yu-Huan Hsu GVS: Gerrit_Virtual_Submit --- arch/arm/mach-tegra/board-cardhu-memory.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu-memory.c b/arch/arm/mach-tegra/board-cardhu-memory.c index 33a66053ee45..72ff02aba05e 100644 --- a/arch/arm/mach-tegra/board-cardhu-memory.c +++ b/arch/arm/mach-tegra/board-cardhu-memory.c @@ -4674,7 +4674,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800008ee, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000004, /* MC_EMEM_ARB_CFG */ + 0x00000008, /* MC_EMEM_ARB_CFG */ 0x80000030, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ @@ -4794,7 +4794,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000dff, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000006, /* MC_EMEM_ARB_CFG */ + 0x0000000d, /* MC_EMEM_ARB_CFG */ 0xc000004f, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000002, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000003, /* MC_EMEM_ARB_TIMING_RP */ -- cgit v1.2.3 From a3a1d1797e310d61204256af8be995f9396c22e7 Mon Sep 17 00:00:00 2001 From: Rohan Somvanshi Date: Thu, 9 Aug 2012 06:08:29 +0000 Subject: arm: cardhu: change parameters for emc 266.5mhz The EmcTclkStable is set to 0x00000004 and McEmemArbOutStandingReq is set to 0xc0000030 Bug 1030392 Change-Id: I4ade7a7bbceb990f57397d5777bf7215dbfd65f1 Signed-off-by: Wen Yi Reviewed-on: http://git-master/r/122302 Reviewed-by: Rohan Somvanshi Tested-by: Rohan Somvanshi Reviewed-by: Automatic_Commit_Validation_User --- arch/arm/mach-tegra/board-cardhu-memory.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu-memory.c b/arch/arm/mach-tegra/board-cardhu-memory.c index 72ff02aba05e..4ec8839c44f6 100644 --- a/arch/arm/mach-tegra/board-cardhu-memory.c +++ b/arch/arm/mach-tegra/board-cardhu-memory.c @@ -4619,7 +4619,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000004, /* EMC_TCKE */ 0x0000000e, /* EMC_TFAW */ 0x00000006, /* EMC_TRPAB */ - 0x00000001, /* EMC_TCLKSTABLE */ + 0x00000004, /* EMC_TCLKSTABLE */ 0x00000002, /* EMC_TCLKSTOP */ 0x00000455, /* EMC_TREFBW */ 0x00000000, /* EMC_QUSE_EXTRA */ @@ -4675,7 +4675,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT_DURATION */ 0x800008ee, /* EMC_DYN_SELF_REF_CONTROL */ 0x00000008, /* MC_EMEM_ARB_CFG */ - 0x80000030, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0xc0000030, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000008, /* MC_EMEM_ARB_TIMING_RC */ -- cgit v1.2.3 From 431e6544c8581bc4122091462dfa57fa41452b3c Mon Sep 17 00:00:00 2001 From: Ilan Aelion Date: Wed, 8 Aug 2012 12:25:52 -0600 Subject: misc: throughput: move client calls to work queue Perform throughput notifications to clients on work queue rather than synchronously to dc flip notifications. Bug 1028850 Change-Id: Ib9446a4ab87a476230a90a1f23c260bcf98e01dc Signed-off-by: Ilan Aelion Reviewed-on: http://git-master/r/122160 Reviewed-by: Varun Colbert Tested-by: Varun Colbert --- drivers/misc/tegra-throughput.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/misc/tegra-throughput.c b/drivers/misc/tegra-throughput.c index bff53235a74c..26573d8afc1a 100644 --- a/drivers/misc/tegra-throughput.c +++ b/drivers/misc/tegra-throughput.c @@ -34,9 +34,17 @@ static unsigned short target_frame_time; static unsigned short last_frame_time; static ktime_t last_flip; static unsigned int multiple_app_disable; - static spinlock_t lock; +static struct work_struct work; +static int throughput_hint; + +static void set_throughput_hint(struct work_struct *work) +{ + /* notify throughput hint clients here */ + nvhost_scale3d_set_throughput_hint(throughput_hint); +} + static int throughput_flip_notifier(struct notifier_block *nb, unsigned long val, void *data) @@ -47,7 +55,6 @@ static int throughput_flip_notifier(struct notifier_block *nb, else { long timediff; ktime_t now; - int throughput_hint; now = ktime_get(); if (last_flip.tv64 != 0) { @@ -66,8 +73,8 @@ static int throughput_flip_notifier(struct notifier_block *nb, throughput_hint = ((int) target_frame_time * 100)/last_frame_time; - /* notify throughput hint clients here */ - nvhost_scale3d_set_throughput_hint(throughput_hint); + if (!work_pending(&work)) + schedule_work(&work); } last_flip = now; } @@ -225,6 +232,7 @@ int __init throughput_init_miscdev(void) pr_debug("%s: initializing\n", __func__); spin_lock_init(&lock); + INIT_WORK(&work, set_throughput_hint); ret = misc_register(&throughput_miscdev); if (ret) { @@ -242,6 +250,8 @@ void __exit throughput_exit_miscdev(void) { pr_debug("%s: exiting\n", __func__); + cancel_work_sync(&work); + misc_deregister(&throughput_miscdev); } -- cgit v1.2.3 From 65d02640b4b0b38263687c7f3e664c873237dc43 Mon Sep 17 00:00:00 2001 From: Krishna Reddy Date: Sun, 29 Jul 2012 15:32:14 -0700 Subject: mm: Avoid freeing init and initrd memory when CPA is enabled. Align memblock reserve for text area to PMD size. Reserve the memory hole between DRAM start and Page table start. Add Sanity check to avoid section split in text area. Bug 1028787 Change-Id: I7fe94f6063b120df9993bc0a51b2ff57609aef3e Signed-off-by: Krishna Reddy Reviewed-on: http://git-master/r/121883 Reviewed-by: Automatic_Commit_Validation_User --- arch/arm/mm/init.c | 6 +++++- arch/arm/mm/mmu.c | 2 +- arch/arm/mm/pageattr.c | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 6f81c8e05c3a..cb4e96e1019d 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -339,7 +339,7 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) #ifdef CONFIG_XIP_KERNEL memblock_reserve(__pa(_sdata), _end - _sdata); #else - memblock_reserve(__pa(_stext), _end - _stext); + memblock_reserve(__pa(_stext), ALIGN(_end - _stext, PMD_SIZE)); #endif #ifdef CONFIG_BLK_DEV_INITRD if (phys_initrd_size && @@ -734,6 +734,7 @@ void __init mem_init(void) void free_initmem(void) { +#ifndef CONFIG_CPA #ifdef CONFIG_HAVE_TCM extern char __tcm_start, __tcm_end; @@ -748,6 +749,7 @@ void free_initmem(void) totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)), __phys_to_pfn(__pa(__init_end)), "init"); +#endif } #ifdef CONFIG_BLK_DEV_INITRD @@ -756,12 +758,14 @@ static int keep_initrd; void free_initrd_mem(unsigned long start, unsigned long end) { +#ifndef CONFIG_CPA if (!keep_initrd) { poison_init_mem((void *)start, PAGE_ALIGN(end) - start); totalram_pages += free_area(__phys_to_pfn(__pa(start)), __phys_to_pfn(__pa(end)), "initrd"); } +#endif } static int __init keepinitrd_setup(char *__unused) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index bb80555edac9..992bbc52938c 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -942,7 +942,7 @@ void __init arm_mm_memblock_reserve(void) */ memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t)); -#ifdef CONFIG_SA1111 +#if defined(CONFIG_SA1111) || defined(CONFIG_CPA) /* * Because of the SA1111 DMA bug, we want to preserve our * precious DMA-able memory... diff --git a/arch/arm/mm/pageattr.c b/arch/arm/mm/pageattr.c index b7ff7f19b541..b4c7be82ea45 100644 --- a/arch/arm/mm/pageattr.c +++ b/arch/arm/mm/pageattr.c @@ -476,6 +476,8 @@ static int split_large_page(pte_t *kpte, unsigned long address) pgprot_t ref_prot = 0, ext_prot = 0; int ret = 0; + BUG_ON((address & PMD_MASK) < __pa(_end)); + pbase = pte_alloc_one_kernel(&init_mm, address); if (!pbase) return -ENOMEM; -- cgit v1.2.3 From 6bc3bd033bad907e37ba0ebc71bb31ea97d1e327 Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Fri, 3 Aug 2012 14:29:11 +0300 Subject: video: tegra: host: Fix section mismatches nvhost context related functions were in init section, even though they are called from non-init functions. Bug 1022681 Change-Id: Ie85e9dd3f19873aec4153e34c7bffa19f40d37fa Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/120884 Reviewed-by: Simone Willett Tested-by: Simone Willett (cherry picked from commit 665a0fee9dc497413bc702fbe86430c9248db8c8) Reviewed-on: http://git-master/r/123456 Reviewed-by: Automatic_Commit_Validation_User --- drivers/video/tegra/host/gr3d/gr3d_t20.c | 12 ++++++------ drivers/video/tegra/host/gr3d/gr3d_t30.c | 14 +++++++------- drivers/video/tegra/host/mpe/mpe.c | 16 ++++++++-------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/video/tegra/host/gr3d/gr3d_t20.c b/drivers/video/tegra/host/gr3d/gr3d_t20.c index b6e3896fe50c..505674c1b867 100644 --- a/drivers/video/tegra/host/gr3d/gr3d_t20.c +++ b/drivers/video/tegra/host/gr3d/gr3d_t20.c @@ -144,7 +144,7 @@ static void save_push_v0(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma) p->save_phys); } -static void __init save_begin_v0(struct host1x_hwctx_handler *h, u32 *ptr) +static void save_begin_v0(struct host1x_hwctx_handler *h, u32 *ptr) { /* 3d: when done, increment syncpt to base+1 */ ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0); @@ -162,7 +162,7 @@ static void __init save_begin_v0(struct host1x_hwctx_handler *h, u32 *ptr) h->syncpt); /* incr 2 */ } -static void __init save_direct_v0(u32 *ptr, u32 start_reg, u32 count) +static void save_direct_v0(u32 *ptr, u32 start_reg, u32 count) { ptr[0] = nvhost_opcode_nonincr(host1x_uclass_indoff_r(), 1); ptr[1] = nvhost_class_host_indoff_reg_read(NV_HOST_MODULE_GR3D, @@ -170,7 +170,7 @@ static void __init save_direct_v0(u32 *ptr, u32 start_reg, u32 count) ptr[2] = nvhost_opcode_nonincr(host1x_uclass_inddata_r(), count); } -static void __init save_indirect_v0(u32 *ptr, u32 offset_reg, u32 offset, +static void save_indirect_v0(u32 *ptr, u32 offset_reg, u32 offset, u32 data_reg, u32 count) { ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, @@ -183,7 +183,7 @@ static void __init save_indirect_v0(u32 *ptr, u32 offset_reg, u32 offset, ptr[4] = nvhost_opcode_nonincr(host1x_uclass_inddata_r(), count); } -static void __init save_end_v0(struct host1x_hwctx_handler *h, u32 *ptr) +static void save_end_v0(struct host1x_hwctx_handler *h, u32 *ptr) { /* Wait for context read service to finish (cpu incr 3) */ ptr[0] = nvhost_opcode_nonincr(host1x_uclass_wait_syncpt_base_r(), 1); @@ -226,7 +226,7 @@ static u32 *save_regs_v0(u32 *ptr, unsigned int *pending, /*** save ***/ -static void __init setup_save_regs(struct save_info *info, +static void setup_save_regs(struct save_info *info, const struct hwctx_reginfo *regs, unsigned int nr_regs) { @@ -284,7 +284,7 @@ static void __init setup_save_regs(struct save_info *info, info->restore_count = restore_count; } -static void __init setup_save(struct host1x_hwctx_handler *h, u32 *ptr) +static void setup_save(struct host1x_hwctx_handler *h, u32 *ptr) { struct save_info info = { ptr, diff --git a/drivers/video/tegra/host/gr3d/gr3d_t30.c b/drivers/video/tegra/host/gr3d/gr3d_t30.c index 5e26a6ff90ae..42b42558c2d2 100644 --- a/drivers/video/tegra/host/gr3d/gr3d_t30.c +++ b/drivers/video/tegra/host/gr3d/gr3d_t30.c @@ -160,7 +160,7 @@ static void save_push_v1(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma) p->save_phys); } -static void __init save_begin_v1(struct host1x_hwctx_handler *p, u32 *ptr) +static void save_begin_v1(struct host1x_hwctx_handler *p, u32 *ptr) { ptr[0] = nvhost_opcode_nonincr(AR3D_DW_MEMORY_OUTPUT_DATA, RESTORE_BEGIN_SIZE); @@ -168,7 +168,7 @@ static void __init save_begin_v1(struct host1x_hwctx_handler *p, u32 *ptr) ptr += RESTORE_BEGIN_SIZE; } -static void __init save_direct_v1(u32 *ptr, u32 start_reg, u32 count) +static void save_direct_v1(u32 *ptr, u32 start_reg, u32 count) { ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, AR3D_DW_MEMORY_OUTPUT_DATA, 1); @@ -182,7 +182,7 @@ static void __init save_direct_v1(u32 *ptr, u32 start_reg, u32 count) ptr[3] = nvhost_opcode_nonincr(host1x_uclass_inddata_r(), count); } -static void __init save_indirect_v1(u32 *ptr, u32 offset_reg, u32 offset, +static void save_indirect_v1(u32 *ptr, u32 offset_reg, u32 offset, u32 data_reg, u32 count) { ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, 0, 0); @@ -199,7 +199,7 @@ static void __init save_indirect_v1(u32 *ptr, u32 offset_reg, u32 offset, ptr[5] = nvhost_opcode_nonincr(host1x_uclass_inddata_r(), count); } -static void __init save_end_v1(struct host1x_hwctx_handler *p, u32 *ptr) +static void save_end_v1(struct host1x_hwctx_handler *p, u32 *ptr) { /* write end of restore buffer */ ptr[0] = nvhost_opcode_setclass(NV_GRAPHICS_3D_CLASS_ID, @@ -234,7 +234,7 @@ static void __init save_end_v1(struct host1x_hwctx_handler *p, u32 *ptr) -static void __init setup_save_regs(struct save_info *info, +static void setup_save_regs(struct save_info *info, const struct hwctx_reginfo *regs, unsigned int nr_regs) { @@ -292,7 +292,7 @@ static void __init setup_save_regs(struct save_info *info, info->restore_count = restore_count; } -static void __init switch_gpu(struct save_info *info, +static void switch_gpu(struct save_info *info, unsigned int save_src_set, u32 save_dest_sets, u32 restore_dest_sets) @@ -313,7 +313,7 @@ static void __init switch_gpu(struct save_info *info, info->restore_count += 1; } -static void __init setup_save(struct host1x_hwctx_handler *p, u32 *ptr) +static void setup_save(struct host1x_hwctx_handler *p, u32 *ptr) { struct save_info info = { ptr, diff --git a/drivers/video/tegra/host/mpe/mpe.c b/drivers/video/tegra/host/mpe/mpe.c index c738700469c6..3b716a05e565 100644 --- a/drivers/video/tegra/host/mpe/mpe.c +++ b/drivers/video/tegra/host/mpe/mpe.c @@ -212,7 +212,7 @@ struct save_info { unsigned int restore_count; }; -static void __init save_begin(struct host1x_hwctx_handler *h, u32 *ptr) +static void save_begin(struct host1x_hwctx_handler *h, u32 *ptr) { /* MPE: when done, increment syncpt to base+1 */ ptr[0] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID, 0, 0); @@ -229,7 +229,7 @@ static void __init save_begin(struct host1x_hwctx_handler *h, u32 *ptr) } #define SAVE_BEGIN_SIZE 5 -static void __init save_direct(u32 *ptr, u32 start_reg, u32 count) +static void save_direct(u32 *ptr, u32 start_reg, u32 count) { ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, host1x_uclass_indoff_r(), 1); @@ -239,7 +239,7 @@ static void __init save_direct(u32 *ptr, u32 start_reg, u32 count) } #define SAVE_DIRECT_SIZE 3 -static void __init save_set_ram_cmd(u32 *ptr, u32 cmd_reg, u32 count) +static void save_set_ram_cmd(u32 *ptr, u32 cmd_reg, u32 count) { ptr[0] = nvhost_opcode_setclass(NV_VIDEO_ENCODE_MPEG_CLASS_ID, cmd_reg, 1); @@ -247,7 +247,7 @@ static void __init save_set_ram_cmd(u32 *ptr, u32 cmd_reg, u32 count) } #define SAVE_SET_RAM_CMD_SIZE 2 -static void __init save_read_ram_data_nasty(u32 *ptr, u32 data_reg) +static void save_read_ram_data_nasty(u32 *ptr, u32 data_reg) { ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, host1x_uclass_indoff_r(), 1); @@ -261,7 +261,7 @@ static void __init save_read_ram_data_nasty(u32 *ptr, u32 data_reg) } #define SAVE_READ_RAM_DATA_NASTY_SIZE 5 -static void __init save_end(struct host1x_hwctx_handler *h, u32 *ptr) +static void save_end(struct host1x_hwctx_handler *h, u32 *ptr) { /* Wait for context read service to finish (cpu incr 3) */ ptr[0] = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, @@ -275,7 +275,7 @@ static void __init save_end(struct host1x_hwctx_handler *h, u32 *ptr) } #define SAVE_END_SIZE 5 -static void __init setup_save_regs(struct save_info *info, +static void setup_save_regs(struct save_info *info, const struct hwctx_reginfo *regs, unsigned int nr_regs) { @@ -304,7 +304,7 @@ static void __init setup_save_regs(struct save_info *info, info->restore_count = restore_count; } -static void __init setup_save_ram_nasty(struct save_info *info, unsigned words, +static void setup_save_ram_nasty(struct save_info *info, unsigned words, unsigned cmd_reg, unsigned data_reg) { u32 *ptr = info->ptr; @@ -330,7 +330,7 @@ static void __init setup_save_ram_nasty(struct save_info *info, unsigned words, info->restore_count = restore_count; } -static void __init setup_save(struct host1x_hwctx_handler *h, u32 *ptr) +static void setup_save(struct host1x_hwctx_handler *h, u32 *ptr) { struct save_info info = { ptr, -- cgit v1.2.3 From 2a11baf116d691a74b247f694a1353a9316d11d3 Mon Sep 17 00:00:00 2001 From: Abhishek Shukla Date: Fri, 27 Jul 2012 13:04:18 +0530 Subject: ARM: tegra: usb_phy: Fix fake remote wakeup 1. Move hsic line value detectors power on config to the beginning of the sequence before enabling interrupt on hsic line wake event. This avoids any fake event caused by any glitches introduced by this switching. 2. Clear any prior interrupts for the line wake event before enabling interrupt for the line wake event. This also clears any fake events generated because of any glitches. 3. Fix wake event type to NONE in the disable routine during resume interrupt. Bug 1019619 Bug 1018416 Signed-off-by: Abhishek Shukla Change-Id: I934fa2514897c4c23bc62ff8365f6fffe7915bd0 Reviewed-on: http://git-master/r/116699 Reviewed-by: Simone Willett Tested-by: Simone Willett (cherry picked from commit 50008402a6f093e48dee05fc88bc54750b97ae25) Reviewed-on: http://git-master/r/123457 Reviewed-by: Automatic_Commit_Validation_User --- arch/arm/mach-tegra/tegra3_usb_phy.c | 61 +++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-tegra/tegra3_usb_phy.c b/arch/arm/mach-tegra/tegra3_usb_phy.c index be61ffcf4d17..d1612d71e5de 100644 --- a/arch/arm/mach-tegra/tegra3_usb_phy.c +++ b/arch/arm/mach-tegra/tegra3_usb_phy.c @@ -1870,6 +1870,30 @@ static void uhsic_setup_pmc_wake_detect(struct tegra_usb_phy *phy) val |= UHSIC_PWR; writel(val, pmc_base + PMC_UTMIP_MASTER_CONFIG); + /* Make sure nothing is happening on the line with respect to PMC */ + val = readl(pmc_base + PMC_UTMIP_UHSIC_FAKE); + val &= ~UHSIC_STROBE_VAL; + val &= ~UHSIC_DATA_VAL; + writel(val, pmc_base + PMC_UTMIP_UHSIC_FAKE); + + /* Clear walk enable */ + val = readl(pmc_base + PMC_SLEEPWALK_CFG); + val &= ~UHSIC_LINEVAL_WALK_EN; + writel(val, pmc_base + PMC_SLEEPWALK_CFG); + + /* Make sure wake value for line is none */ + val = readl(pmc_base + PMC_SLEEP_CFG); + val &= ~UHSIC_WAKE_VAL(WAKE_VAL_ANY); + val |= UHSIC_WAKE_VAL(WAKE_VAL_NONE); + writel(val, pmc_base + PMC_SLEEP_CFG); + + /* turn on pad detectors */ + val = readl(pmc_base + PMC_USB_AO); + val &= ~(STROBE_VAL_PD_P0 | DATA_VAL_PD_P0); + writel(val, pmc_base + PMC_USB_AO); + + /* Add small delay before usb detectors provide stable line values */ + udelay(1); /* Enable which type of event can trigger a walk, * in this case usb_line_wake */ @@ -1886,19 +1910,16 @@ static void uhsic_setup_pmc_wake_detect(struct tegra_usb_phy *phy) val |= UHSIC_DATA_RPD_A; val &= ~UHSIC_STROBE_RPD_A; val |= UHSIC_STROBE_RPU_A; - writel(val, pmc_base + PMC_SLEEPWALK_UHSIC); val &= ~UHSIC_DATA_RPD_B; val |= UHSIC_DATA_RPU_B; val &= ~UHSIC_STROBE_RPU_B; val |= UHSIC_STROBE_RPD_B; - writel(val, pmc_base + PMC_SLEEPWALK_UHSIC); val &= ~UHSIC_DATA_RPD_C; val |= UHSIC_DATA_RPU_C; val &= ~UHSIC_STROBE_RPU_C; val |= UHSIC_STROBE_RPD_C; - writel(val, pmc_base + PMC_SLEEPWALK_UHSIC); val &= ~UHSIC_DATA_RPD_D; val |= UHSIC_DATA_RPU_D; @@ -1906,19 +1927,21 @@ static void uhsic_setup_pmc_wake_detect(struct tegra_usb_phy *phy) val |= UHSIC_STROBE_RPD_D; writel(val, pmc_base + PMC_SLEEPWALK_UHSIC); - /* turn on pad detectors */ - val = readl(pmc_base + PMC_USB_AO); - val &= ~(STROBE_VAL_PD_P0 | DATA_VAL_PD_P0); - writel(val, pmc_base + PMC_USB_AO); - /* Add small delay before usb detectors provide stable line values */ - udelay(1); - phy->remote_wakeup = false; - /* Turn over pad configuration to PMC for line wake events*/ + /* Setting Wake event*/ val = readl(pmc_base + PMC_SLEEP_CFG); - val &= ~UHSIC_WAKE_VAL(~0); + val &= ~UHSIC_WAKE_VAL(WAKE_VAL_ANY); val |= UHSIC_WAKE_VAL(WAKE_VAL_SD10); + writel(val, pmc_base + PMC_SLEEP_CFG); + + /* Clear the walk pointers and wake alarm */ + val = readl(pmc_base + PMC_TRIGGERS); + val |= UHSIC_CLR_WAKE_ALARM_P0 | UHSIC_CLR_WALK_PTR_P0; + writel(val, pmc_base + PMC_TRIGGERS); + + /* Turn over pad configuration to PMC for line wake events*/ + val = readl(pmc_base + PMC_SLEEP_CFG); val |= UHSIC_MASTER_ENABLE; writel(val, pmc_base + PMC_SLEEP_CFG); @@ -1937,14 +1960,10 @@ static void uhsic_phy_disable_pmc_bus_ctrl(struct tegra_usb_phy *phy) DBG("%s (%d)\n", __func__, __LINE__); val = readl(pmc_base + PMC_SLEEP_CFG); - val &= ~UHSIC_WAKE_VAL(0x0); + val &= ~UHSIC_WAKE_VAL(WAKE_VAL_ANY); val |= UHSIC_WAKE_VAL(WAKE_VAL_NONE); writel(val, pmc_base + PMC_SLEEP_CFG); - val = readl(pmc_base + PMC_TRIGGERS); - val |= UHSIC_CLR_WAKE_ALARM_P0 | UHSIC_CLR_WALK_PTR_P0; - writel(val, pmc_base + PMC_TRIGGERS); - val = readl(base + UHSIC_PMC_WAKEUP0); val &= ~EVENT_INT_ENB; writel(val, base + UHSIC_PMC_WAKEUP0); @@ -1959,6 +1978,10 @@ static void uhsic_phy_disable_pmc_bus_ctrl(struct tegra_usb_phy *phy) val |= (STROBE_VAL_PD_P0 | DATA_VAL_PD_P0); writel(val, pmc_base + PMC_USB_AO); + val = readl(pmc_base + PMC_TRIGGERS); + val |= (UHSIC_CLR_WALK_PTR_P0 | UHSIC_CLR_WAKE_ALARM_P0); + writel(val, pmc_base + PMC_TRIGGERS); + phy->remote_wakeup = false; } @@ -1973,12 +1996,12 @@ static bool uhsic_phy_remotewake_detected(struct tegra_usb_phy *phy) val = readl(pmc_base + UTMIP_UHSIC_STATUS); if (UHSIC_WAKE_ALARM & val) { val = readl(pmc_base + PMC_SLEEP_CFG); - val &= ~UHSIC_WAKE_VAL(0x0); + val &= ~UHSIC_WAKE_VAL(WAKE_VAL_ANY); val |= UHSIC_WAKE_VAL(WAKE_VAL_NONE); writel(val, pmc_base + PMC_SLEEP_CFG); val = readl(pmc_base + PMC_TRIGGERS); - val |= UHSIC_CLR_WAKE_ALARM_P0 | UHSIC_CLR_WALK_PTR_P0; + val |= UHSIC_CLR_WAKE_ALARM_P0; writel(val, pmc_base + PMC_TRIGGERS); val = readl(base + UHSIC_PMC_WAKEUP0); -- cgit v1.2.3 From cb63051e6151352a38fb8b04c542c8099a7ecea3 Mon Sep 17 00:00:00 2001 From: Venu Byravarasu Date: Fri, 16 Mar 2012 11:10:19 +0530 Subject: mfd: tps65090: align driver with mainline Align the driver with mainline. This is vbased on commit 3c33be06f9aa0949ad24e67dfcae1f2a3006f4e1 --------------- mfd: Add support for TPS65090 TPS65090 is a Texas Instrument PMIC. It contains 3 Step-Down converters, 2 always on LDO's and 7 current limited load switches. Signed-off-by: Venu Byravarasu Signed-off-by: Samuel Ortiz -------------- Change-Id: I26545520f2cc72100a927cb60b38693153a4afce Signed-off-by: Laxman Dewangan Reviewed-on: http://git-master/r/119320 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Venu Byravarasu (cherry picked from commit a108454c2b8e037a82e49e14ceb3d9c0228af963) Signed-off-by: Peter Zu Change-Id: I1f7d303ae8a306aa61cf627f40474b1e098cef23 Reviewed-on: http://git-master/r/123458 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/mfd/Kconfig | 24 +-- drivers/mfd/Makefile | 2 +- drivers/mfd/tps65090.c | 351 +++++++++++++++---------------------------- include/linux/mfd/tps65090.h | 7 - 4 files changed, 133 insertions(+), 251 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index f37d3ec02123..7040ae62f75a 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -783,6 +783,18 @@ config MFD_PM8XXX_IRQ config TPS65911_COMPARATOR tristate +config MFD_TPS65090 + bool "TPS65090 Power Management chips" + depends on I2C=y && GENERIC_HARDIRQS + select MFD_CORE + select REGMAP_I2C + help + If you say yes here you get support for the TPS65090 series of + Power Management chips. + This driver provides common support for accessing the device, + additional drivers must be enabled in order to use the + functionality of the device. + config MFD_AAT2870_CORE bool "Support for the AnalogicTech AAT2870" select MFD_CORE @@ -804,18 +816,6 @@ config MFD_TPS6591X additional drivers must be enabled in order to use the functionality of the device. -config MFD_TPS65090 - bool "TPS65090 Power Management chips" - depends on I2C && GENERIC_HARDIRQS - select MFD_CORE - select REGMAP_I2C - help - If you say yes here you get support for the TPS65090 series of - Power Management chips. - This driver provides common support for accessing the device, - additional drivers must be enabled in order to use the - functionality of the device. - config MFD_RC5T583 bool "Ricoh RC5T583 Power Management system device" depends on I2C=y && GENERIC_HARDIRQS diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 6634515b64e4..efd9f7fee186 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -101,9 +101,9 @@ obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o +obj-$(CONFIG_MFD_TPS65090) += tps65090.o obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o obj-$(CONFIG_MFD_TPS6591X) += tps6591x.o -obj-$(CONFIG_MFD_TPS65090) += tps65090.o obj-$(CONFIG_MFD_TPS80031) += tps80031.o obj-$(CONFIG_GPADC_TPS80031) += tps8003x-gpadc.o obj-$(CONFIG_MFD_MAX8907C) += max8907c.o diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index 080f97aa264b..a66d4df51293 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c @@ -1,24 +1,19 @@ /* - * driver/mfd/tps65090.c - * * Core driver for TI TPS65090 PMIC family * - * Copyright (C) 2012 NVIDIA Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + + * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #include @@ -28,10 +23,13 @@ #include #include #include - #include #include #include +#include + +#define NUM_INT_REG 2 +#define TOTAL_NUM_REG 0x18 /* interrupt status registers */ #define TPS65090_INT_STS 0x0 @@ -41,41 +39,43 @@ #define TPS65090_INT_MSK 0x2 #define TPS65090_INT_MSK2 0x3 - -enum irq_type { - EVENT, -}; - struct tps65090_irq_data { u8 mask_reg; u8 mask_pos; - enum irq_type type; }; -#define TPS65090_IRQ(_reg, _mask_pos, _type) \ +#define TPS65090_IRQ(_reg, _mask_pos) \ { \ .mask_reg = (_reg), \ .mask_pos = (_mask_pos), \ - .type = (_type), \ } static const struct tps65090_irq_data tps65090_irqs[] = { - [0] = TPS65090_IRQ(0, 0, EVENT), - [1] = TPS65090_IRQ(0, 1, EVENT), - [2] = TPS65090_IRQ(0, 2, EVENT), - [3] = TPS65090_IRQ(0, 3, EVENT), - [4] = TPS65090_IRQ(0, 4, EVENT), - [5] = TPS65090_IRQ(0, 5, EVENT), - [6] = TPS65090_IRQ(0, 6, EVENT), - [7] = TPS65090_IRQ(0, 7, EVENT), - [8] = TPS65090_IRQ(1, 0, EVENT), - [9] = TPS65090_IRQ(1, 1, EVENT), - [10] = TPS65090_IRQ(1, 2, EVENT), - [11] = TPS65090_IRQ(1, 3, EVENT), - [12] = TPS65090_IRQ(1, 4, EVENT), - [13] = TPS65090_IRQ(1, 5, EVENT), - [14] = TPS65090_IRQ(1, 6, EVENT), - [15] = TPS65090_IRQ(1, 7, EVENT), + [0] = TPS65090_IRQ(0, 0), + [1] = TPS65090_IRQ(0, 1), + [2] = TPS65090_IRQ(0, 2), + [3] = TPS65090_IRQ(0, 3), + [4] = TPS65090_IRQ(0, 4), + [5] = TPS65090_IRQ(0, 5), + [6] = TPS65090_IRQ(0, 6), + [7] = TPS65090_IRQ(0, 7), + [8] = TPS65090_IRQ(1, 0), + [9] = TPS65090_IRQ(1, 1), + [10] = TPS65090_IRQ(1, 2), + [11] = TPS65090_IRQ(1, 3), + [12] = TPS65090_IRQ(1, 4), + [13] = TPS65090_IRQ(1, 5), + [14] = TPS65090_IRQ(1, 6), + [15] = TPS65090_IRQ(1, 7), +}; + +static struct mfd_cell tps65090s[] = { + { + .name = "tps65910-pmic", + }, + { + .name = "tps65910-regulator", + }, }; struct tps65090 { @@ -86,51 +86,42 @@ struct tps65090 { struct irq_chip irq_chip; struct mutex irq_lock; int irq_base; - u32 irq_en; - u8 mask_cache[2]; - u8 mask_reg[2]; + unsigned int id; }; + int tps65090_write(struct device *dev, int reg, uint8_t val) { struct tps65090 *tps = dev_get_drvdata(dev); return regmap_write(tps->rmap, reg, val); } +EXPORT_SYMBOL_GPL(tps65090_write); + int tps65090_read(struct device *dev, int reg, uint8_t *val) { - int rval, ret = 0; struct tps65090 *tps = dev_get_drvdata(dev); - ret = regmap_read(tps->rmap, reg, &rval); - *val = rval; - return 0; + unsigned int temp_val; + int ret; + ret = regmap_read(tps->rmap, reg, &temp_val); + if (!ret) + *val = temp_val; + return ret; } EXPORT_SYMBOL_GPL(tps65090_read); int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num) { struct tps65090 *tps = dev_get_drvdata(dev); - return regmap_update_bits_lazy(tps->rmap, reg, BIT(bit_num), ~0u); - + return regmap_update_bits(tps->rmap, reg, BIT(bit_num), ~0u); } EXPORT_SYMBOL_GPL(tps65090_set_bits); int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num) { struct tps65090 *tps = dev_get_drvdata(dev); - return regmap_update_bits_lazy(tps->rmap, reg, BIT(bit_num), 0u); + return regmap_update_bits(tps->rmap, reg, BIT(bit_num), 0u); } EXPORT_SYMBOL_GPL(tps65090_clr_bits); -static int __remove_subdev(struct device *dev, void *unused) -{ - platform_device_unregister(to_platform_device(dev)); - return 0; -} - -static int tps65090_remove_subdevs(struct tps65090 *tps65090) -{ - return device_for_each_child(tps65090->dev, NULL, __remove_subdev); -} - static void tps65090_irq_lock(struct irq_data *data) { struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data); @@ -141,135 +132,97 @@ static void tps65090_irq_lock(struct irq_data *data) static void tps65090_irq_mask(struct irq_data *irq_data) { struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data); - unsigned int __irq = irq_data->irq - tps65090->irq_base; + unsigned int __irq = irq_data->hwirq; const struct tps65090_irq_data *data = &tps65090_irqs[__irq]; - if (data->type == EVENT) - tps65090->mask_reg[data->mask_reg] |= (1 << data->mask_pos); - else - tps65090->mask_reg[data->mask_reg] |= (3 << data->mask_pos); - - tps65090->irq_en &= ~(1 << __irq); + tps65090_set_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg), + data->mask_pos); } static void tps65090_irq_unmask(struct irq_data *irq_data) { struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data); - unsigned int __irq = irq_data->irq - tps65090->irq_base; const struct tps65090_irq_data *data = &tps65090_irqs[__irq]; - if (data->type == EVENT) { - tps65090->mask_reg[data->mask_reg] &= ~(1 << data->mask_pos); - tps65090->irq_en |= (1 << __irq); - } + tps65090_clr_bits(tps65090->dev, (TPS65090_INT_MSK + data->mask_reg), + data->mask_pos); } static void tps65090_irq_sync_unlock(struct irq_data *data) { struct tps65090 *tps65090 = irq_data_get_irq_chip_data(data); - int i; - - for (i = 0; i < ARRAY_SIZE(tps65090->mask_reg); i++) { - if (tps65090->mask_reg[i] != tps65090->mask_cache[i]) { - if (!WARN_ON(tps65090_write(tps65090->dev, - TPS65090_INT_MSK + 2*i, - tps65090->mask_reg[i]))) - tps65090->mask_cache[i] = tps65090->mask_reg[i]; - } - } mutex_unlock(&tps65090->irq_lock); } -static int tps65090_irq_set_type(struct irq_data *irq_data, unsigned int type) -{ - struct tps65090 *tps65090 = irq_data_get_irq_chip_data(irq_data); - - unsigned int __irq = irq_data->irq - tps65090->irq_base; - const struct tps65090_irq_data *data = &tps65090_irqs[__irq]; - - if (data->type != EVENT) /* add support for GPIO, if needed */ - return -EINVAL; - - return 0; -} - static irqreturn_t tps65090_irq(int irq, void *data) { struct tps65090 *tps65090 = data; int ret = 0; - u8 tmp[3]; - u8 int_ack; - u32 acks, mask = 0; + u8 status, mask; + unsigned long int acks = 0; int i; - for (i = 0; i < 3; i++) { - ret = tps65090_read(tps65090->dev, TPS65090_INT_STS + 2*i, - &tmp[i]); + for (i = 0; i < NUM_INT_REG; i++) { + ret = tps65090_read(tps65090->dev, TPS65090_INT_MSK + i, &mask); if (ret < 0) { dev_err(tps65090->dev, - "failed to read interrupt status\n"); + "failed to read mask reg [addr:%d]\n", + TPS65090_INT_MSK + i); return IRQ_NONE; } - if (tmp[i]) { - /* Ack only those interrupts which are enabled */ - int_ack = tmp[i] & (~(tps65090->mask_cache[i])); + ret = tps65090_read(tps65090->dev, TPS65090_INT_STS + i, + &status); + if (ret < 0) { + dev_err(tps65090->dev, + "failed to read status reg [addr:%d]\n", + TPS65090_INT_STS + i); + return IRQ_NONE; + } + if (status) { + /* Ack only those interrupts which are not masked */ + status &= (~mask); ret = tps65090_write(tps65090->dev, - TPS65090_INT_STS + 2*i, int_ack); + TPS65090_INT_STS + i, status); if (ret < 0) { dev_err(tps65090->dev, "failed to write interrupt status\n"); return IRQ_NONE; } + acks |= (status << (i * 8)); } } - acks = (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]; - - for (i = 0; i < ARRAY_SIZE(tps65090_irqs); i++) { - if (tps65090_irqs[i].type == EVENT) - mask = (1 << (tps65090_irqs[i].mask_pos - + tps65090_irqs[i].mask_reg*8)); - else - return -EINVAL; - if ((acks & mask) && (tps65090->irq_en & (1 << i))) - handle_nested_irq(tps65090->irq_base + i); - } - return IRQ_HANDLED; + for_each_set_bit(i, &acks, ARRAY_SIZE(tps65090_irqs)) + handle_nested_irq(tps65090->irq_base + i); + return acks ? IRQ_HANDLED : IRQ_NONE; } static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq, - int irq_base) + int irq_base) { int i, ret; if (!irq_base) { - dev_warn(tps65090->dev, "No interrupt support on IRQ base\n"); + dev_err(tps65090->dev, "IRQ base not set\n"); return -EINVAL; } mutex_init(&tps65090->irq_lock); - tps65090->mask_reg[0] = 0xFF; - tps65090->mask_reg[1] = 0xFF; - for (i = 0; i < 2; i++) { - tps65090->mask_cache[i] = tps65090->mask_reg[i]; - tps65090_write(tps65090->dev, TPS65090_INT_MSK + i, - tps65090->mask_cache[i]); - } + for (i = 0; i < NUM_INT_REG; i++) + tps65090_write(tps65090->dev, TPS65090_INT_MSK + i, 0xFF); - for (i = 0; i < 2; i++) + for (i = 0; i < NUM_INT_REG; i++) tps65090_write(tps65090->dev, TPS65090_INT_STS + i, 0xff); tps65090->irq_base = irq_base; - tps65090->irq_chip.name = "tps65090"; tps65090->irq_chip.irq_mask = tps65090_irq_mask; tps65090->irq_chip.irq_unmask = tps65090_irq_unmask; tps65090->irq_chip.irq_bus_lock = tps65090_irq_lock; tps65090->irq_chip.irq_bus_sync_unlock = tps65090_irq_sync_unlock; - tps65090->irq_chip.irq_set_type = tps65090_irq_set_type; for (i = 0; i < ARRAY_SIZE(tps65090_irqs); i++) { int __irq = i + tps65090->irq_base; @@ -292,90 +245,21 @@ static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq, return ret; } -static int __devinit tps65090_add_subdevs(struct tps65090 *tps65090, - struct tps65090_platform_data *pdata) -{ - struct tps65090_subdev_info *subdev; - struct platform_device *pdev; - int i, ret = 0; - - for (i = 0; i < pdata->num_subdevs; i++) { - subdev = &pdata->subdevs[i]; - - pdev = platform_device_alloc(subdev->name, subdev->id); - - pdev->dev.parent = tps65090->dev; - pdev->dev.platform_data = subdev->platform_data; - - ret = platform_device_add(pdev); - if (ret) - goto failed; - } - return 0; - -failed: - tps65090_remove_subdevs(tps65090); - return ret; -} -#ifdef CONFIG_DEBUG_FS -#include -#include -static void print_regs(const char *header, struct seq_file *s, - struct i2c_client *client, int start_offset, - int end_offset) -{ - int reg_val; - int i; - int ret; - struct tps65090 *tps = s->private; - seq_printf(s, "%s\n", header); - for (i = start_offset; i <= end_offset; ++i) { - ret = regmap_read(tps->rmap, i, ®_val); - if (ret >= 0) - seq_printf(s, "Reg 0x%02x Value 0x%02x\n", i, reg_val); - } - seq_printf(s, "------------------\n"); -} - -static int dbg_tps_show(struct seq_file *s, void *unused) +static bool is_volatile_reg(struct device *dev, unsigned int reg) { - struct tps65090 *tps = s->private; - struct i2c_client *client = tps->client; - - seq_printf(s, "TPS65090 Registers\n"); - seq_printf(s, "------------------\n"); - - print_regs("All Regs", s, client, 0x0, 24); - return 0; -} - -static int dbg_tps_open(struct inode *inode, struct file *file) -{ - return single_open(file, dbg_tps_show, inode->i_private); -} - -static const struct file_operations debug_fops = { - .open = dbg_tps_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static void __init tps65090_debuginit(struct tps65090 *tps) -{ - (void)debugfs_create_file("tps65090", S_IRUGO, NULL, - tps, &debug_fops); -} -#else -static void __init tps65090_debuginit(struct tps65090 *tpsi) -{ - return; + if ((reg == TPS65090_INT_STS) || (reg == TPS65090_INT_STS)) + return true; + else + return false; } -#endif static const struct regmap_config tps65090_regmap_config = { .reg_bits = 8, .val_bits = 8, + .max_register = TOTAL_NUM_REG, + .num_reg_defaults_raw = TOTAL_NUM_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = is_volatile_reg, }; static int __devinit tps65090_i2c_probe(struct i2c_client *client, @@ -387,10 +271,11 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client, if (!pdata) { dev_err(&client->dev, "tps65090 requires platform data\n"); - return -ENOTSUPP; + return -EINVAL; } - tps65090 = kzalloc(sizeof(struct tps65090), GFP_KERNEL); + tps65090 = devm_kzalloc(&client->dev, sizeof(struct tps65090), + GFP_KERNEL); if (tps65090 == NULL) return -ENOMEM; @@ -401,36 +286,39 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client, mutex_init(&tps65090->lock); if (client->irq) { - ret = tps65090_irq_init(tps65090, client->irq, - pdata->irq_base); + ret = tps65090_irq_init(tps65090, client->irq, pdata->irq_base); if (ret) { - dev_err(&client->dev, "IRQ init failed: %d\n", ret); - goto err_irq_init; + dev_err(&client->dev, "IRQ init failed with err: %d\n", + ret); + goto err_exit; } } - ret = tps65090_add_subdevs(tps65090, pdata); - if (ret) { - dev_err(&client->dev, "add devices failed: %d\n", ret); - goto err_add_devs; - } - tps65090->rmap = regmap_init_i2c(tps65090->client, &tps65090_regmap_config); if (IS_ERR(tps65090->rmap)) { - dev_err(&client->dev, "regmap_init failed: %ld\n", + dev_err(&client->dev, "regmap_init failed with err: %ld\n", PTR_ERR(tps65090->rmap)); - goto err_add_devs; + goto err_irq_exit; }; - tps65090_debuginit(tps65090); + + ret = mfd_add_devices(tps65090->dev, -1, tps65090s, + ARRAY_SIZE(tps65090s), NULL, 0); + if (ret) { + dev_err(&client->dev, "add mfd devices failed with err: %d\n", + ret); + goto err_regmap_exit; + } return 0; -err_add_devs: +err_regmap_exit: + regmap_exit(tps65090->rmap); + +err_irq_exit: if (client->irq) free_irq(client->irq, tps65090); -err_irq_init: - kfree(tps65090); +err_exit: return ret; } @@ -438,13 +326,14 @@ static int __devexit tps65090_i2c_remove(struct i2c_client *client) { struct tps65090 *tps65090 = i2c_get_clientdata(client); + mfd_remove_devices(tps65090->dev); + regmap_exit(tps65090->rmap); if (client->irq) free_irq(client->irq, tps65090); - regmap_exit(tps65090->rmap); - kfree(tps65090); return 0; } + #ifdef CONFIG_PM static int tps65090_i2c_suspend(struct i2c_client *client, pm_message_t state) { @@ -461,7 +350,6 @@ static int tps65090_i2c_resume(struct i2c_client *client) } #endif - static const struct i2c_device_id tps65090_id_table[] = { { "tps65090", 0 }, { }, @@ -495,4 +383,5 @@ static void __exit tps65090_exit(void) module_exit(tps65090_exit); MODULE_DESCRIPTION("TPS65090 core driver"); -MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Venu Byravarasu "); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/tps65090.h b/include/linux/mfd/tps65090.h index 511ced59ef1a..38e31c55adbb 100644 --- a/include/linux/mfd/tps65090.h +++ b/include/linux/mfd/tps65090.h @@ -1,5 +1,4 @@ /* - * include/linux/mfd/tps65090.h * Core driver interface for TI TPS65090 PMIC family * * Copyright (C) 2012 NVIDIA Corporation @@ -23,8 +22,6 @@ #ifndef __LINUX_MFD_TPS65090_H #define __LINUX_MFD_TPS65090_H -#include - struct tps65090_subdev_info { int id; const char *name; @@ -42,12 +39,8 @@ struct tps65090_platform_data { * of the TPS65090 sub-device drivers */ extern int tps65090_write(struct device *dev, int reg, uint8_t val); -extern int tps65090_writes(struct device *dev, int reg, int len, uint8_t *val); extern int tps65090_read(struct device *dev, int reg, uint8_t *val); -extern int tps65090_reads(struct device *dev, int reg, int len, uint8_t *val); extern int tps65090_set_bits(struct device *dev, int reg, uint8_t bit_num); extern int tps65090_clr_bits(struct device *dev, int reg, uint8_t bit_num); -extern int tps65090_update(struct device *dev, int reg, uint8_t val, - uint8_t bit_num); #endif /*__LINUX_MFD_TPS65090_H */ -- cgit v1.2.3 From cd9b76effbe924680b628adc76826174d984e24c Mon Sep 17 00:00:00 2001 From: Bitan Biswas Date: Mon, 6 Aug 2012 11:17:25 +0530 Subject: ARM: tegra: lp0 WAKE2 status clear Tegra pmc WAKE2 status registers also need to be cleared before re-entering lp0 mode. Change-Id: I1bd5c48baf86ba23d0352594e97c360d363ce991 Signed-off-by: Bitan Biswas Reviewed-on: http://git-master/r/121185 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Laxman Dewangan (cherry picked from commit 7f9749a0050aa4bbe770f1a061f5ae8c8545dfa8) Reviewed-on: http://git-master/r/123459 Reviewed-by: Simone Willett Tested-by: Simone Willett --- arch/arm/mach-tegra/pm-irq.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-tegra/pm-irq.c b/arch/arm/mach-tegra/pm-irq.c index 4a3f3c31830c..4e3c06835b2f 100644 --- a/arch/arm/mach-tegra/pm-irq.c +++ b/arch/arm/mach-tegra/pm-irq.c @@ -284,10 +284,15 @@ static int tegra_pm_irq_syscore_suspend(void) wake_enb = 0xffffffff; } - /* Clear PMC Wake Status register while going to suspend */ + /* Clear PMC Wake Status registers while going to suspend */ temp = readl(pmc + PMC_WAKE_STATUS); if (temp) pmc_32kwritel(temp, PMC_WAKE_STATUS); +#ifndef CONFIG_ARCH_TEGRA_2x_SOC + temp = readl(pmc + PMC_WAKE2_STATUS); + if (temp) + pmc_32kwritel(temp, PMC_WAKE2_STATUS); +#endif write_pmc_wake_level(wake_level); -- cgit v1.2.3 From 570d481ef040897064b1336287650493bcc99658 Mon Sep 17 00:00:00 2001 From: Roger Hsieh Date: Mon, 30 Jul 2012 16:20:38 +0800 Subject: arm: tegra: fuse: check SENSE_DONE after fuse programming Make fuse burning take effect by checking SENSE_DONE. Without this chip options will not be available on fuse registers until power on reset or LP0 resume. Bug 1020726 Change-Id: Id547d1ea51b023ba904f5751c2ad65667375777d Signed-off-by: Roger Hsieh Reviewed-on: http://git-master/r/119271 Reviewed-by: Varun Wadekar (cherry picked from commit 940211c305fe0bed54b19847633800b77c369a46) Reviewed-on: http://git-master/r/123460 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Simone Willett Tested-by: Simone Willett --- arch/arm/mach-tegra/tegra_odm_fuses.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/mach-tegra/tegra_odm_fuses.c b/arch/arm/mach-tegra/tegra_odm_fuses.c index 06b831c31967..ae82ed56f0f0 100644 --- a/arch/arm/mach-tegra/tegra_odm_fuses.c +++ b/arch/arm/mach-tegra/tegra_odm_fuses.c @@ -53,6 +53,7 @@ #define NFUSES 64 #define STATE_IDLE (0x4 << 16) +#define SENSE_DONE (0x1 << 30) /* since fuse burning is irreversible, use this for testing */ #define ENABLE_FUSE_BURNING 1 @@ -607,6 +608,17 @@ static void fuse_program_array(int pgm_cycles) } fuse_power_disable(); + + /* + * Wait until done (polling) + * this one needs to use fuse_sense done, the FSM follows a periodic + * sequence that includes idle + */ + do { + udelay(1); + reg = tegra_fuse_readl(FUSE_CTRL); + } while ((reg & (0x1 << 30)) != SENSE_DONE); + } static int fuse_set(enum fuse_io_param io_param, u32 *param, int size) -- cgit v1.2.3 From 99eb017e5c216b881eca280264924e966165058a Mon Sep 17 00:00:00 2001 From: Venu Byravarasu Date: Mon, 30 Jul 2012 16:27:32 +0530 Subject: arm: tegra: usb: Remove HSIC phy params As HSIC phy parameters are not customizable, removing them from platform_data structure. bug 1024260 Change-Id: I00fcc0559be43ad336b5b03a7a47443dfaa80d06 Signed-off-by: Venu Byravarasu Reviewed-on: http://git-master/r/119298 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Venkat Moganty (cherry picked from commit 8fa2ae311f67f90a85a746a659a75bb431314df3) Reviewed-on: http://git-master/r/123461 Reviewed-by: Simone Willett Tested-by: Simone Willett --- include/linux/platform_data/tegra_usb.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/include/linux/platform_data/tegra_usb.h b/include/linux/platform_data/tegra_usb.h index 81b27e89631c..59f928aaa07f 100644 --- a/include/linux/platform_data/tegra_usb.h +++ b/include/linux/platform_data/tegra_usb.h @@ -64,17 +64,6 @@ struct tegra_ulpi_config { int phy_restore_gpio; }; -/** - * configuration structure for setting up hsic phy - */ -struct tegra_hsic_config { - u8 sync_start_delay; - u8 idle_wait_delay; - u8 term_range_adj; - u8 elastic_underrun_limit; - u8 elastic_overrun_limit; -}; - /** * Platform specific operations that will be controlled * during the phy operations. @@ -133,7 +122,6 @@ struct tegra_usb_platform_data { union { struct tegra_utmi_config utmi; struct tegra_ulpi_config ulpi; - struct tegra_hsic_config hsic; } u_cfg; struct tegra_usb_phy_platform_ops *ops; -- cgit v1.2.3 From dbc17ec2ad69cba786dd198b2cd344ecfe63ad5e Mon Sep 17 00:00:00 2001 From: Venu Byravarasu Date: Mon, 30 Jul 2012 16:34:24 +0530 Subject: arm: tegra: remove hsic phy params from boards As HSIC phy params are not customizable, removing them from board files. bug 1024260 Change-Id: I6b7702c95810c683ab3d9f79e975657f3f601cd0 Signed-off-by: Venu Byravarasu Reviewed-on: http://git-master/r/119300 Reviewed-by: Simone Willett Tested-by: Simone Willett (cherry picked from commit f34ad144dd221836787fd9bc6871274174364a66) Reviewed-on: http://git-master/r/123462 Reviewed-by: Automatic_Commit_Validation_User --- arch/arm/mach-tegra/board-cardhu.c | 14 -------------- arch/arm/mach-tegra/board-enterprise.c | 9 --------- 2 files changed, 23 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu.c b/arch/arm/mach-tegra/board-cardhu.c index 3f0f19612d0d..fbfaf77499a3 100644 --- a/arch/arm/mach-tegra/board-cardhu.c +++ b/arch/arm/mach-tegra/board-cardhu.c @@ -1082,13 +1082,6 @@ static struct tegra_usb_platform_data tegra_ehci2_hsic_xmm_pdata = { .remote_wakeup_supported = false, .power_off_on_suspend = false, }, - .u_cfg.hsic = { - .sync_start_delay = 9, - .idle_wait_delay = 17, - .term_range_adj = 0, - .elastic_underrun_limit = 16, - .elastic_overrun_limit = 16, - }, .ops = &hsic_xmm_plat_ops, }; #endif @@ -1172,13 +1165,6 @@ static struct tegra_usb_platform_data tegra_ehci2_hsic_pdata = { .remote_wakeup_supported = false, .power_off_on_suspend = false, }, - .u_cfg.hsic = { - .sync_start_delay = 9, - .idle_wait_delay = 17, - .term_range_adj = 0, - .elastic_underrun_limit = 16, - .elastic_overrun_limit = 16, - }, .ops = &hsic_plat_ops, }; diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c index 6f872264a43e..bf1bd159480f 100644 --- a/arch/arm/mach-tegra/board-enterprise.c +++ b/arch/arm/mach-tegra/board-enterprise.c @@ -736,18 +736,9 @@ static struct tegra_usb_platform_data tegra_ehci2_hsic_xmm_pdata = { .remote_wakeup_supported = false, .power_off_on_suspend = false, }, - .u_cfg.hsic = { - .sync_start_delay = 9, - .idle_wait_delay = 17, - .term_range_adj = 0, - .elastic_underrun_limit = 16, - .elastic_overrun_limit = 16, - }, .ops = &hsic_xmm_plat_ops, }; - - static struct tegra_usb_platform_data tegra_udc_pdata = { .port_otg = true, .has_hostpc = true, -- cgit v1.2.3 From 2a256188f6cdca0873388e1ea560dae0d5d63a2c Mon Sep 17 00:00:00 2001 From: Venu Byravarasu Date: Mon, 30 Jul 2012 18:17:34 +0530 Subject: arm: tegra: usb_phy: Hard code HSIC phy params As HSIC does not have any customizable phy params, hard coding them in the phy driver. bug 1024260 Change-Id: I64d5c7f91b077134b54b0aadaf44f129ceaa99e5 Signed-off-by: Venu Byravarasu Reviewed-on: http://git-master/r/119299 Reviewed-by: Simone Willett Tested-by: Simone Willett (cherry picked from commit ae0fe0f2527af92bc0ba9213ea0668ec6c7b19e8) Reviewed-on: http://git-master/r/123464 Reviewed-by: Automatic_Commit_Validation_User --- arch/arm/mach-tegra/tegra2_usb_phy.c | 14 +++++++++----- arch/arm/mach-tegra/tegra3_usb_phy.c | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-tegra/tegra2_usb_phy.c b/arch/arm/mach-tegra/tegra2_usb_phy.c index c7f4a771b1d8..2feb2e96f55e 100644 --- a/arch/arm/mach-tegra/tegra2_usb_phy.c +++ b/arch/arm/mach-tegra/tegra2_usb_phy.c @@ -277,6 +277,11 @@ #define DBG(stuff...) do {} while (0) #endif +/* define HSIC phy params */ +#define HSIC_SYNC_START_DELAY 9 +#define HSIC_IDLE_WAIT_DELAY 17 +#define HSIC_ELASTIC_UNDERRUN_LIMIT 16 +#define HSIC_ELASTIC_OVERRUN_LIMIT 16 static DEFINE_SPINLOCK(utmip_pad_lock); static int utmip_pad_count; @@ -1051,7 +1056,6 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy) { unsigned long val; void __iomem *base = phy->regs; - struct tegra_hsic_config *config = &phy->pdata->u_cfg.hsic; DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); if (phy->phy_clk_on) { @@ -1077,13 +1081,13 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy) writel(val, base + USB_SUSP_CTRL); val = readl(base + UTMIP_XCVR_UHSIC_HSRX_CFG0); - val |= UHSIC_IDLE_WAIT(config->idle_wait_delay); - val |= UHSIC_ELASTIC_UNDERRUN_LIMIT(config->elastic_underrun_limit); - val |= UHSIC_ELASTIC_OVERRUN_LIMIT(config->elastic_overrun_limit); + val |= UHSIC_IDLE_WAIT(HSIC_IDLE_WAIT_DELAY); + val |= UHSIC_ELASTIC_UNDERRUN_LIMIT(HSIC_ELASTIC_UNDERRUN_LIMIT); + val |= UHSIC_ELASTIC_OVERRUN_LIMIT(HSIC_ELASTIC_OVERRUN_LIMIT); writel(val, base + UTMIP_XCVR_UHSIC_HSRX_CFG0); val = readl(base + UHSIC_HSRX_CFG1); - val |= UHSIC_HS_SYNC_START_DLY(config->sync_start_delay); + val |= UHSIC_HS_SYNC_START_DLY(HSIC_SYNC_START_DELAY); writel(val, base + UHSIC_HSRX_CFG1); val = readl(base + UHSIC_MISC_CFG0); diff --git a/arch/arm/mach-tegra/tegra3_usb_phy.c b/arch/arm/mach-tegra/tegra3_usb_phy.c index d1612d71e5de..38d8c414b194 100644 --- a/arch/arm/mach-tegra/tegra3_usb_phy.c +++ b/arch/arm/mach-tegra/tegra3_usb_phy.c @@ -473,6 +473,11 @@ #define PHY_DBG(stuff...) do {} while (0) #endif +/* define HSIC phy params */ +#define HSIC_SYNC_START_DELAY 9 +#define HSIC_IDLE_WAIT_DELAY 17 +#define HSIC_ELASTIC_UNDERRUN_LIMIT 16 +#define HSIC_ELASTIC_OVERRUN_LIMIT 16 static u32 utmip_rctrl_val, utmip_tctrl_val; static DEFINE_SPINLOCK(utmip_pad_lock); @@ -2212,7 +2217,6 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy) { unsigned long val; void __iomem *base = phy->regs; - struct tegra_hsic_config *config = &phy->pdata->u_cfg.hsic; DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); @@ -2238,13 +2242,13 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy) writel(val, base + USB_SUSP_CTRL); val = readl(base + UHSIC_HSRX_CFG0); - val |= UHSIC_IDLE_WAIT(config->idle_wait_delay); - val |= UHSIC_ELASTIC_UNDERRUN_LIMIT(config->elastic_underrun_limit); - val |= UHSIC_ELASTIC_OVERRUN_LIMIT(config->elastic_overrun_limit); + val |= UHSIC_IDLE_WAIT(HSIC_IDLE_WAIT_DELAY); + val |= UHSIC_ELASTIC_UNDERRUN_LIMIT(HSIC_ELASTIC_UNDERRUN_LIMIT); + val |= UHSIC_ELASTIC_OVERRUN_LIMIT(HSIC_ELASTIC_OVERRUN_LIMIT); writel(val, base + UHSIC_HSRX_CFG0); val = readl(base + UHSIC_HSRX_CFG1); - val |= UHSIC_HS_SYNC_START_DLY(config->sync_start_delay); + val |= UHSIC_HS_SYNC_START_DLY(HSIC_SYNC_START_DELAY); writel(val, base + UHSIC_HSRX_CFG1); /* WAR HSIC TX */ -- cgit v1.2.3 From 869961ce87cbfa491f754cbe6f6d83dc323d79b1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 7 May 2012 10:03:17 +0100 Subject: mfd: Fix tps65090 ifdefs for suspend mode CONFIG_PM also covers runtime only PM. Signed-off-by: Mark Brown Acked-by: Venu Byravarasu Signed-off-by: Samuel Ortiz (Cherry-picked from mainline 1ca5513af77307eccea7efd4d12ef5c14f1b12ab) Change-Id: I5d8d35f72f46dec28d62e6b01fbc915049185ec3 Signed-off-by: Laxman Dewangan Reviewed-on: http://git-master/r/120368 Reviewed-by: Automatic_Commit_Validation_User (cherry picked from commit 4cf205f2c1ed24511e672bb8ffb8720516216dc8) Signed-off-by: Peter Zu Change-Id: I754e9e8b94e87455d64303014eaae72115a58d68 Reviewed-on: http://git-master/r/123465 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/mfd/tps65090.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index a66d4df51293..ac7e8b1f0034 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c @@ -334,7 +334,7 @@ static int __devexit tps65090_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int tps65090_i2c_suspend(struct i2c_client *client, pm_message_t state) { if (client->irq) @@ -363,7 +363,7 @@ static struct i2c_driver tps65090_driver = { }, .probe = tps65090_i2c_probe, .remove = __devexit_p(tps65090_i2c_remove), -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP .suspend = tps65090_i2c_suspend, .resume = tps65090_i2c_resume, #endif -- cgit v1.2.3 From 0843971852383510a82bba81a08d2186757dd2d4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 7 May 2012 10:03:18 +0100 Subject: mfd: Don't use I2C-specific suspend and resume operations for tps65090 The legacy suspend operations have been deprecated and printing warnings on boot for over a year now. Signed-off-by: Mark Brown Acked-by: Venu Byravarasu Signed-off-by: Samuel Ortiz (Cherry-picked from mainline b6c9eeef4e775e1fff76f4395d11638dc198271d) Change-Id: Ia8b79787c813327fe1d1ccb5a5ad19da57f2212f Signed-off-by: Laxman Dewangan Reviewed-on: http://git-master/r/120369 (cherry picked from commit b7582d0944f6329e8eb3804fd0a53eaacefe4395) Signed-off-by: Peter Zu Change-Id: I844f6f7962794c52a15a498fd6f83c5b413a9984 Reviewed-on: http://git-master/r/123466 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/mfd/tps65090.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index ac7e8b1f0034..6dc4c345ea68 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c @@ -335,21 +335,27 @@ static int __devexit tps65090_i2c_remove(struct i2c_client *client) } #ifdef CONFIG_PM_SLEEP -static int tps65090_i2c_suspend(struct i2c_client *client, pm_message_t state) +static int tps65090_suspend(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); if (client->irq) disable_irq(client->irq); return 0; } -static int tps65090_i2c_resume(struct i2c_client *client) +static int tps65090_resume(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); if (client->irq) enable_irq(client->irq); return 0; } #endif +static const struct dev_pm_ops tps65090_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(tps65090_suspend, tps65090_resume) +}; + static const struct i2c_device_id tps65090_id_table[] = { { "tps65090", 0 }, { }, @@ -360,13 +366,10 @@ static struct i2c_driver tps65090_driver = { .driver = { .name = "tps65090", .owner = THIS_MODULE, + .pm = &tps65090_pm_ops, }, .probe = tps65090_i2c_probe, .remove = __devexit_p(tps65090_i2c_remove), -#ifdef CONFIG_PM_SLEEP - .suspend = tps65090_i2c_suspend, - .resume = tps65090_i2c_resume, -#endif .id_table = tps65090_id_table, }; -- cgit v1.2.3 From 78ba5f14e2c34117cf38c3e5d17f47af86761a3c Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 2 Aug 2012 15:27:53 -0400 Subject: asoc: tegra: fix compilation error in max98095 change 4b70cc537cadc787b748c7c246d703a240b08985 introduced a compilation error. Signed-off-by: Rhyland Klein Change-Id: I59e54537d9bb4b30e807478e5b7634db0813a739 Reviewed-on: http://git-master/r/120443 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Ankit Gupta (Engrg-SW) Reviewed-by: Scott Peterson (cherry picked from commit c5dea888253285e23107585805b7728ebe46e17e) Reviewed-on: http://git-master/r/123467 Reviewed-by: Simone Willett Tested-by: Simone Willett --- sound/soc/tegra/tegra_max98095.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/tegra/tegra_max98095.c b/sound/soc/tegra/tegra_max98095.c index f77c327b4b00..1d03980f276f 100644 --- a/sound/soc/tegra/tegra_max98095.c +++ b/sound/soc/tegra/tegra_max98095.c @@ -157,7 +157,7 @@ static int tegra_max98095_hw_params(struct snd_pcm_substream *substream, } i2s_daifmt = SND_SOC_DAIFMT_NB_NF; - i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master; ? + i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master ? SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM; switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) { -- cgit v1.2.3 From 3ed20a53af7876d26906fbb04c4d310b2a28b92f Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Thu, 2 Aug 2012 15:29:35 -0400 Subject: ALSA: usb-audio: fix compilation error change 8843c49092b6ed903e88eded1f1c9b9a7f432dfe introduced a compliation error if CONFIG_SWITCH is not enabled. Signed-off-by: Rhyland Klein Change-Id: I4b4c547394f424bd90837726b08d9feccd4207de Reviewed-on: http://git-master/r/120444 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Ravindra Lokhande Reviewed-by: Scott Peterson (cherry picked from commit 991fbf047fca8a4fa729d090b5c3f65a89acb9ba) Reviewed-on: http://git-master/r/123468 Reviewed-by: Simone Willett Tested-by: Simone Willett --- sound/usb/card.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/usb/card.c b/sound/usb/card.c index fca3f56fbb30..d5201ca996e4 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -755,7 +755,9 @@ static int __init snd_usb_audio_init(void) err = usb_register(&usb_audio_driver); if (err) { +#ifdef CONFIG_SWITCH switch_dev_unregister(&usb_switch_dev); +#endif } return err; -- cgit v1.2.3 From 5ce9f015ff62c3394334fce91da87ee3398b0991 Mon Sep 17 00:00:00 2001 From: Mohan T Date: Thu, 9 Aug 2012 09:51:11 +0530 Subject: arm: config: tegra3: enable ipv4/ipv6 filters Android jb need ip filters to be enabled to track data uses. Bug 1019233 Change-Id: I8073643a4a7c34e428c02682a3afc5a23fbcf344 Signed-off-by: Mohan T Reviewed-on: http://git-master/r/122051 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Rakesh Kumar GVS: Gerrit_Virtual_Submit Reviewed-by: Bharat Nihalani (cherry picked from commit bbdf4403412df9151864bd633519f828ea27c8c6) Reviewed-on: http://git-master/r/123469 Reviewed-by: Simone Willett Tested-by: Simone Willett --- arch/arm/configs/tegra3_android_defconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/configs/tegra3_android_defconfig b/arch/arm/configs/tegra3_android_defconfig index 7a4064c52840..0eb50c7eb645 100644 --- a/arch/arm/configs/tegra3_android_defconfig +++ b/arch/arm/configs/tegra3_android_defconfig @@ -145,16 +145,25 @@ CONFIG_IP_NF_MATCH_ECN=y CONFIG_IP_NF_MATCH_TTL=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_TARGET_REJECT_SKERR=y CONFIG_IP_NF_TARGET_LOG=y CONFIG_NF_NAT=y CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_IP_NF_TARGET_NETMAP=y CONFIG_IP_NF_TARGET_REDIRECT=y CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y CONFIG_IP_NF_ARPTABLES=y CONFIG_IP_NF_ARPFILTER=y CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_NF_CONNTRACK_IPV6=y CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_TARGET_LOG=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_TARGET_REJECT_SKERR=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y CONFIG_NET_SCHED=y CONFIG_NET_SCH_HTB=y CONFIG_NET_SCH_INGRESS=y -- cgit v1.2.3 From a7611457ff2628b72ed9b24c77fc287cb08ffb3a Mon Sep 17 00:00:00 2001 From: Preetham Chandru Date: Thu, 9 Aug 2012 13:51:39 +0530 Subject: usb: ehci: tegra: Fix Slab corruption error Give ownership of the DMA buffer back to the processor first and then free the buffer. Otherwise processor won't be able to access the dma mapped buffers and this would lead to slab corruption. When the DMA buffer is freed without a call to dma_sync_single_for_cpu(), the kernel won't be able to set the buffer as POISON FREE and when we acquire this memory back again the kernel will start printing slab corruption output as the memory is not set to POISON FREE Bug 1017884 Bug 1018161 Reviewed-on: http://git-master/r/#change,122151 Signed-off-by: Preetham Chandru R Change-Id: I00d6cb185cd2314cccb56f968eb0a05288588c13 Reviewed-on: http://git-master/r/122390 Reviewed-by: Simone Willett Tested-by: Simone Willett (cherry picked from commit 642d37a0eee196d0ce811dd11bb7af5ba281ee3a) Signed-off-by: Peter Zu Change-Id: I3ff611a3674536a93233da53488840fb77c5d4ef Reviewed-on: http://git-master/r/123470 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/usb/host/ehci-tegra.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 51670a91726e..e04e824cbafd 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -137,8 +137,6 @@ static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) { - usb_hcd_unmap_urb_for_dma(hcd, urb); - free_align_buffer(urb); if (urb->transfer_dma) { enum dma_data_direction dir; @@ -148,6 +146,9 @@ static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, urb->transfer_dma, urb->transfer_buffer_length, DMA_FROM_DEVICE); } + + usb_hcd_unmap_urb_for_dma(hcd, urb); + free_align_buffer(urb); } static irqreturn_t tegra_ehci_irq(struct usb_hcd *hcd) -- cgit v1.2.3 From a2f12bcb8942818e5d70fb46244ff38ec5fbb62d Mon Sep 17 00:00:00 2001 From: Suresh Mangipudi Date: Thu, 9 Aug 2012 13:54:57 +0530 Subject: arm: tegra: usb_phy: remote-wake for LS devices Remote wakeup was not working for low speed devices. Remote wakeup interrupt is now handled properly for low speed devices. Bug 1029608 Change-Id: If224f30ccc6275b97d50120fe04d9aa53d495e2e Signed-off-by: Suresh Mangipudi Reviewed-on: http://git-master/r/122367 Reviewed-by: Simone Willett Tested-by: Simone Willett (cherry picked from commit c065d9e47085fbb98924d986c3915f279e504fc8) Reviewed-on: http://git-master/r/123471 Reviewed-by: Automatic_Commit_Validation_User --- arch/arm/mach-tegra/tegra3_usb_phy.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-tegra/tegra3_usb_phy.c b/arch/arm/mach-tegra/tegra3_usb_phy.c index 38d8c414b194..4fbeb74fc347 100644 --- a/arch/arm/mach-tegra/tegra3_usb_phy.c +++ b/arch/arm/mach-tegra/tegra3_usb_phy.c @@ -1228,6 +1228,8 @@ static int utmi_phy_irq(struct tegra_usb_phy *phy) { void __iomem *base = phy->regs; unsigned long val = 0; + bool remote_wakeup = false; + int irq_status = IRQ_HANDLED; if (phy->phy_clk_on) { DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); @@ -1239,8 +1241,10 @@ static int utmi_phy_irq(struct tegra_usb_phy *phy) usb_phy_fence_read(phy); /* check if there is any remote wake event */ - if (utmi_phy_remotewake_detected(phy)) + if (utmi_phy_remotewake_detected(phy)) { pr_info("%s: utmip remote wake detected\n", __func__); + remote_wakeup = true; + } if (phy->pdata->u_data.host.hot_plug) { val = readl(base + USB_SUSP_CTRL); @@ -1250,17 +1254,23 @@ static int utmi_phy_irq(struct tegra_usb_phy *phy) writel(val , (base + USB_SUSP_CTRL)); pr_info("%s: usb device plugged-in\n", __func__); val = readl(base + USB_USBSTS); - if (!(val & USB_USBSTS_PCI)) - return IRQ_NONE; + if (!(val & USB_USBSTS_PCI)) { + irq_status = IRQ_NONE; + goto exit; + } val = readl(base + USB_PORTSC); val &= ~(USB_PORTSC_WKCN | USB_PORTSC_RWC_BITS); writel(val , (base + USB_PORTSC)); } else if (!phy->phy_clk_on) { - return IRQ_NONE; + if (remote_wakeup) + irq_status = IRQ_HANDLED; + else + irq_status = IRQ_NONE; + goto exit; } } - - return IRQ_HANDLED; +exit: + return irq_status; } static void utmi_phy_enable_obs_bus(struct tegra_usb_phy *phy) -- cgit v1.2.3 From cb884bc6bed605b96cff64afb37d7a385cb6b8a5 Mon Sep 17 00:00:00 2001 From: Nikesh Oswal Date: Thu, 26 Jul 2012 15:58:46 +0530 Subject: alsa: hda: add alsa ctl to query max channels add alsa ctl to query maximum supported channels Bug: 998697 Signed-off-by: Nikesh Oswal Change-Id: Id2f0e6a62d2413615f13a0c18757c05610ef0c2c Reviewed-on: http://git-master/r/118602 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Scott Peterson (cherry picked from commit 93fa2d495c82c5b63572e62e8bba6a6acf3269f9) Reviewed-on: http://git-master/r/123472 Reviewed-by: Simone Willett Tested-by: Simone Willett --- sound/pci/hda/hda_codec.c | 25 +++++++++++++++++++++++++ sound/pci/hda/hda_codec.h | 1 + sound/pci/hda/hda_eld.c | 4 ++++ 3 files changed, 30 insertions(+) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 91b2e4689175..ff10a630da92 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2840,6 +2840,16 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, return change; } +int snd_hda_max_pcm_ch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xFFFFFFFF; + return 0; +} + int snd_hda_hdmi_decode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -2850,6 +2860,15 @@ int snd_hda_hdmi_decode_info(struct snd_kcontrol *kcontrol, return 0; } +static int snd_hda_max_pcm_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = codec->max_pcm_channels; + return 0; +} + static int snd_hda_hdmi_decode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -2894,6 +2913,12 @@ static struct snd_kcontrol_new dig_mixes[] = { .info = snd_hda_hdmi_decode_info, .get = snd_hda_hdmi_decode_get, }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "HDA Maximum PCM Channels", + .info = snd_hda_max_pcm_ch_info, + .get = snd_hda_max_pcm_ch_get, + }, { } /* end */ }; diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 1c5dc6d73d6b..6cba73ce1997 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -868,6 +868,7 @@ struct hda_codec { #endif unsigned int recv_dec_cap; + unsigned int max_pcm_channels; /* codec-specific additional proc output */ void (*proc_widget_hook)(struct snd_info_buffer *buffer, struct hda_codec *codec, hda_nid_t nid); diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index a8042e14f5de..862dd35260d0 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -427,6 +427,10 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, codec->recv_dec_cap |= (1 << AUDIO_CODING_TYPE_AC3); } else if (eld->sad[i].format == AUDIO_CODING_TYPE_DTS) { codec->recv_dec_cap |= (1 << AUDIO_CODING_TYPE_DTS); + } else if (eld->sad[i].format == AUDIO_CODING_TYPE_LPCM) { + codec->max_pcm_channels = + eld->sad[i].channels > codec->max_pcm_channels ? + eld->sad[i].channels : codec->max_pcm_channels; } } -- cgit v1.2.3 From 63efbd193470322a8283dd79918d8ccebb1b6afe Mon Sep 17 00:00:00 2001 From: Chaitanya Bandi Date: Tue, 10 Jul 2012 18:29:19 +0530 Subject: arm: tegra: enterprise: Use pll_p as clk source for PWR_I2C Using pll_p as clock source for PWR_I2C and set bus frequency to 390Khz to make clock divider as 0x82. Bug 1001924 Change-Id: Ib7936b0da9a754cc6b4858eb40a941eee606ac65 Signed-off-by: Chaitanya Bandi Reviewed-on: http://git-master/r/114577 Reviewed-by: Simone Willett Tested-by: Simone Willett (cherry picked from commit ce9fc97cf95c463dff8156dffd5632e5336e4adc) Reviewed-on: http://git-master/r/123473 Reviewed-by: Automatic_Commit_Validation_User --- arch/arm/mach-tegra/board-enterprise.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c index bf1bd159480f..0df4167290c0 100644 --- a/arch/arm/mach-tegra/board-enterprise.c +++ b/arch/arm/mach-tegra/board-enterprise.c @@ -194,6 +194,7 @@ static __initdata struct tegra_clk_init_table enterprise_clk_init_table[] = { { "audio3", "i2s3_sync", 0, false}, { "vi", "pll_p", 0, false}, { "vi_sensor", "pll_p", 0, false}, + { "i2c5", "pll_p", 3200000, false}, { NULL, NULL, 0, 0}, }; @@ -249,7 +250,7 @@ static struct tegra_i2c_platform_data enterprise_i2c4_platform_data = { static struct tegra_i2c_platform_data enterprise_i2c5_platform_data = { .adapter_nr = 4, .bus_count = 1, - .bus_clk_rate = { 400000, 0 }, + .bus_clk_rate = { 390000, 0 }, .scl_gpio = {TEGRA_GPIO_PZ6, 0}, .sda_gpio = {TEGRA_GPIO_PZ7, 0}, .arb_recovery = arb_lost_recovery, -- cgit v1.2.3 From fd34a72d152169f4f90e5e5cc2151b441c97d86b Mon Sep 17 00:00:00 2001 From: Vinayak Pane Date: Tue, 17 Jul 2012 19:06:54 -0700 Subject: arm: tegra: xmm: device set to null in unregister hsic_unregister is being called multiple times during two step enumeration process of xmm. In failure cases when enumeration does not complete properly, kernel panic is seen because of extra unregister-ehci device. Bug 1016593 Change-Id: Ibaeb20ed0dab0e906741fdfad78f7d89a3672f60 Signed-off-by: Vinayak Pane Reviewed-on: http://git-master/r/116626 Reviewed-by: Simone Willett Tested-by: Simone Willett (cherry picked from commit 675dfd18c952e6cf5748aaa305086d86b0358582) Reviewed-on: http://git-master/r/123474 Reviewed-by: Automatic_Commit_Validation_User --- arch/arm/mach-tegra/baseband-xmm-power.c | 9 ++++----- arch/arm/mach-tegra/baseband-xmm-power.h | 2 +- arch/arm/mach-tegra/baseband-xmm-power2.c | 2 +- arch/arm/mach-tegra/board-enterprise.c | 10 ++++++++-- arch/arm/mach-tegra/include/mach/tegra-bb-power.h | 2 +- drivers/misc/tegra-baseband/bb-m7400.c | 2 +- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-tegra/baseband-xmm-power.c b/arch/arm/mach-tegra/baseband-xmm-power.c index 9513bdc5d45f..03a96f5e8e49 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power.c +++ b/arch/arm/mach-tegra/baseband-xmm-power.c @@ -66,7 +66,7 @@ static struct usb_device_id xmm_pm_ids[] = { .driver_info = 0 }, {} }; - +MODULE_DEVICE_TABLE(usb, xmm_pm_ids); static struct gpio tegra_baseband_gpios[] = { { -1, GPIOF_OUT_INIT_LOW, "BB_RSTn" }, @@ -335,11 +335,10 @@ static int xmm_power_off(struct platform_device *device) /* unregister usb host controller */ if (pdata->hsic_unregister) - pdata->hsic_unregister(data->hsic_device); + pdata->hsic_unregister(&data->hsic_device); else pr_err("%s: hsic_unregister is missing\n", __func__); - /* set IPC_HSIC_ACTIVE low */ gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); @@ -822,7 +821,7 @@ static void xmm_device_remove_handler(struct usb_device *udev) if (usbdev == udev) { pr_info("Remove device %d <%s %s>\n", udev->devnum, udev->manufacturer, udev->product); - usbdev = 0; + usbdev = NULL; } } @@ -1043,7 +1042,7 @@ static int xmm_power_driver_remove(struct platform_device *device) /* unregister usb host controller */ if (pdata->hsic_unregister) - pdata->hsic_unregister(data->hsic_device); + pdata->hsic_unregister(&data->hsic_device); else pr_err("%s: hsic_unregister is missing\n", __func__); diff --git a/arch/arm/mach-tegra/baseband-xmm-power.h b/arch/arm/mach-tegra/baseband-xmm-power.h index 69140891319d..2ac6deececb7 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power.h +++ b/arch/arm/mach-tegra/baseband-xmm-power.h @@ -41,7 +41,7 @@ enum baseband_type { struct baseband_power_platform_data { enum baseband_type baseband_type; struct platform_device* (*hsic_register)(void); - void (*hsic_unregister)(struct platform_device *); + void (*hsic_unregister)(struct platform_device **); union { struct { int mdm_reset; diff --git a/arch/arm/mach-tegra/baseband-xmm-power2.c b/arch/arm/mach-tegra/baseband-xmm-power2.c index 3c6285c0a070..fcbcdca5c24a 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power2.c +++ b/arch/arm/mach-tegra/baseband-xmm-power2.c @@ -119,7 +119,7 @@ static void xmm_power2_step1(struct work_struct *work) /* unregister usb host controller */ if (pdata->hsic_unregister) - pdata->hsic_unregister(data->hsic_device); + pdata->hsic_unregister(&data->hsic_device); else pr_err("%s: hsic_unregister is missing\n", __func__); diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c index 0df4167290c0..2675f0f0c524 100644 --- a/arch/arm/mach-tegra/board-enterprise.c +++ b/arch/arm/mach-tegra/board-enterprise.c @@ -832,9 +832,15 @@ error: return NULL; } -void tegra_usb_hsic_host_unregister(struct platform_device *pdev) +void tegra_usb_hsic_host_unregister(struct platform_device **platdev) { - platform_device_unregister(pdev); + struct platform_device *pdev = *platdev; + + if (pdev && &pdev->dev) { + platform_device_unregister(pdev); + *platdev = NULL; + } else + pr_err("%s: no platform device\n", __func__); } static void enterprise_usb_init(void) diff --git a/arch/arm/mach-tegra/include/mach/tegra-bb-power.h b/arch/arm/mach-tegra/include/mach/tegra-bb-power.h index e0b7e3de326f..96e36116f04f 100644 --- a/arch/arm/mach-tegra/include/mach/tegra-bb-power.h +++ b/arch/arm/mach-tegra/include/mach/tegra-bb-power.h @@ -50,7 +50,7 @@ union tegra_bb_gpio_id { }; typedef struct platform_device* (*ehci_register_cb)(void); -typedef void (*ehci_unregister_cb)(struct platform_device *); +typedef void (*ehci_unregister_cb)(struct platform_device **); struct tegra_bb_pdata { union tegra_bb_gpio_id *id; diff --git a/drivers/misc/tegra-baseband/bb-m7400.c b/drivers/misc/tegra-baseband/bb-m7400.c index adabefdb100d..edde7d1786ed 100644 --- a/drivers/misc/tegra-baseband/bb-m7400.c +++ b/drivers/misc/tegra-baseband/bb-m7400.c @@ -241,7 +241,7 @@ static int m7400_attrib_write(struct device *dev, int value) } else { /* Unregister ehci controller */ if (ehci_device != NULL) - pdata->ehci_unregister(ehci_device); + pdata->ehci_unregister(&ehci_device); /* Signal AP going down */ m7400_apdown_handshake(); -- cgit v1.2.3 From 0b39ff87dc621e1bc53fb4fe682dc66d336a4496 Mon Sep 17 00:00:00 2001 From: Mayuresh Kulkarni Date: Tue, 24 Jul 2012 12:47:24 +0530 Subject: video: tegra: host: use strcmp in nvhost_bus_match - replace the usage of strncmp with strcmp in nvhost_bus_match() - strncmp was needed when we had device name as . but now the device name is which matches with the driver name. - multiple devices get bind with the same driver using id_table which uses .version field as an index in id_table Change-Id: If0b6f0ee18626d5e7ff801b8515ef5168069c3f2 Signed-off-by: Mayuresh Kulkarni Reviewed-on: http://git-master/r/117953 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Ken Adams Reviewed-by: Terje Bergstrom (cherry picked from commit ece74a0888415460a005d52bcf2d5f6cf535597d) Reviewed-on: http://git-master/r/123475 Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/video/tegra/host/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/tegra/host/bus.c b/drivers/video/tegra/host/bus.c index 758a5ca4ad94..f22dac288051 100644 --- a/drivers/video/tegra/host/bus.c +++ b/drivers/video/tegra/host/bus.c @@ -96,7 +96,7 @@ static int nvhost_bus_match(struct device *_dev, struct device_driver *drv) if (ndrv->id_table) return nvhost_bus_match_id(dev, ndrv->id_table) != NULL; else /* driver does not support id_table */ - return !strncmp(dev->name, drv->name, strlen(drv->name)); + return !strcmp(dev->name, drv->name); } static int nvhost_drv_probe(struct device *_dev) -- cgit v1.2.3 From 6cc291b8e2330743225d842f107be8f9e504484a Mon Sep 17 00:00:00 2001 From: Vinayak Pane Date: Tue, 24 Jul 2012 21:13:56 -0700 Subject: arm: tegra: xmm: repair ipc_ap_wake_state at reset Preparing strict checking for ipc_ap_wake_state during modem initialization. Modify the flashless xmm wake irq part to avoid mixing with flashed modem irq handler. Remove unused init1 workqueue from the driver. Bug 1003141 Change-Id: I7b06b1783a140c0cc5121478e4983fab39862d7c Signed-off-by: Vinayak Pane Reviewed-on: http://git-master/r/118475 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Steve Lin (cherry picked from commit e7a7520c6494c6610835bd6e5c83e790a05892eb) Reviewed-on: http://git-master/r/123476 Reviewed-by: Simone Willett Tested-by: Simone Willett --- arch/arm/mach-tegra/baseband-xmm-power.c | 111 ++++++++++-------------------- arch/arm/mach-tegra/baseband-xmm-power.h | 15 +++- arch/arm/mach-tegra/baseband-xmm-power2.c | 21 ++---- 3 files changed, 53 insertions(+), 94 deletions(-) diff --git a/arch/arm/mach-tegra/baseband-xmm-power.c b/arch/arm/mach-tegra/baseband-xmm-power.c index 03a96f5e8e49..9923bcdf4bd7 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power.c +++ b/arch/arm/mach-tegra/baseband-xmm-power.c @@ -77,18 +77,9 @@ static struct gpio tegra_baseband_gpios[] = { { -1, GPIOF_IN, "IPC_HSIC_SUS_REQ" }, }; -static enum { - IPC_AP_WAKE_UNINIT, - IPC_AP_WAKE_IRQ_READY, - IPC_AP_WAKE_INIT1, - IPC_AP_WAKE_INIT2, - IPC_AP_WAKE_L, - IPC_AP_WAKE_H, -} ipc_ap_wake_state; - static enum baseband_xmm_powerstate_t baseband_xmm_powerstate; +static enum ipc_ap_wake_state_t ipc_ap_wake_state; static struct workqueue_struct *workqueue; -static struct work_struct init1_work; static struct work_struct init2_work; static struct work_struct L2_resume_work; static struct work_struct autopm_resume_work; @@ -256,7 +247,6 @@ static int xmm_power_on(struct platform_device *device) /* reset the state machine */ baseband_xmm_powerstate = BBXMM_PS_INIT; modem_sleep_flag = false; - ipc_ap_wake_state = IPC_AP_WAKE_INIT2; pr_debug("%s wake_st(%d) modem version %lu\n", __func__, ipc_ap_wake_state, modem_ver); @@ -264,6 +254,8 @@ static int xmm_power_on(struct platform_device *device) /* register usb host controller */ if (!modem_flash) { pr_debug("%s - %d\n", __func__, __LINE__); + + ipc_ap_wake_state = IPC_AP_WAKE_INIT2; /* register usb host controller only once */ if (register_hsic_device) { pr_debug("%s: register usb host controller\n", @@ -291,7 +283,7 @@ static int xmm_power_on(struct platform_device *device) pr_debug("%s: reset flash modem\n", __func__); modem_power_on = false; - ipc_ap_wake_state = IPC_AP_WAKE_INIT1; + ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); xmm_power_reset_on(pdata); @@ -551,41 +543,11 @@ void baseband_xmm_set_power_status(unsigned int status) } EXPORT_SYMBOL_GPL(baseband_xmm_set_power_status); -irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id) + +irqreturn_t xmm_power_ipc_ap_wake_irq(int value) { struct baseband_power_platform_data *data = xmm_power_drv_data.pdata; struct xmm_power_data *drv = &xmm_power_drv_data; - int value; - - value = gpio_get_value(data->modem.xmm.ipc_ap_wake); - pr_debug("%s g(%d), wake_st(%d)\n", __func__, value, ipc_ap_wake_state); - - /* modem initialization/bootup part*/ - if (unlikely(ipc_ap_wake_state < IPC_AP_WAKE_IRQ_READY)) { - pr_err("%s - spurious irq\n", __func__); - return IRQ_HANDLED; - } else if (ipc_ap_wake_state == IPC_AP_WAKE_IRQ_READY) { - if (!value) { - pr_debug("%s - IPC_AP_WAKE_INIT1" - " - got falling edge\n", __func__); - /* go to IPC_AP_WAKE_INIT1 state */ - ipc_ap_wake_state = IPC_AP_WAKE_INIT1; - queue_work(workqueue, &init1_work); - } else - pr_debug("%s - IPC_AP_WAKE_INIT1" - " - wait for falling edge\n", __func__); - return IRQ_HANDLED; - } else if (ipc_ap_wake_state == IPC_AP_WAKE_INIT1) { - if (!value) { - pr_debug("%s - got falling edge at INIT1\n", __func__); - /* go to IPC_AP_WAKE_INIT2 state */ - ipc_ap_wake_state = IPC_AP_WAKE_INIT2; - queue_work(workqueue, &init2_work); - } else - pr_debug("%s - IPC_AP_WAKE_INIT1" - " - got rising edge\n", __func__); - return IRQ_HANDLED; - } /* modem wakeup part */ if (!value) { @@ -645,41 +607,41 @@ irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id) /* save gpio state */ ipc_ap_wake_state = IPC_AP_WAKE_H; } - return IRQ_HANDLED; } EXPORT_SYMBOL(xmm_power_ipc_ap_wake_irq); -static void xmm_power_init1_work(struct work_struct *work) +static irqreturn_t ipc_ap_wake_irq(int irq, void *dev_id) { - struct baseband_power_platform_data *pdata = xmm_power_drv_data.pdata; + struct baseband_power_platform_data *data = xmm_power_drv_data.pdata; int value; - pr_debug("%s {\n", __func__); - - /* check if IPC_HSIC_ACTIVE high */ - value = gpio_get_value(pdata->modem.xmm.ipc_hsic_active); - if (value != 1) { - pr_err("%s - expected IPC_HSIC_ACTIVE high!\n", __func__); - return; - } - - /* wait 100 ms */ - msleep(100); - - /* set IPC_HSIC_ACTIVE low */ - gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); - - /* wait 10 ms */ - usleep_range(10000, 11000); - - /* set IPC_HSIC_ACTIVE high */ - gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 1); + value = gpio_get_value(data->modem.xmm.ipc_ap_wake); + pr_debug("%s g(%d), wake_st(%d)\n", __func__, value, ipc_ap_wake_state); - /* wait 20 ms */ - msleep(20); + /* modem wakeup part */ + if (likely(ipc_ap_wake_state >= IPC_AP_WAKE_INIT2)) + return xmm_power_ipc_ap_wake_irq(value); - pr_debug("%s }\n", __func__); + /* modem initialization/bootup part*/ + if (unlikely(ipc_ap_wake_state < IPC_AP_WAKE_IRQ_READY)) { + pr_err("%s - spurious irq\n", __func__); + } else if (ipc_ap_wake_state == IPC_AP_WAKE_IRQ_READY) { + if (value) { + /* make state ready for falling edge */ + ipc_ap_wake_state = IPC_AP_WAKE_INIT1; + pr_debug("%s - got rising edge\n", __func__); + } + } else if (ipc_ap_wake_state == IPC_AP_WAKE_INIT1) { + if (!value) { + pr_debug("%s - got falling edge at INIT1\n", __func__); + /* go to IPC_AP_WAKE_INIT2 state */ + ipc_ap_wake_state = IPC_AP_WAKE_INIT2; + queue_work(workqueue, &init2_work); + } else + pr_debug("%s - unexpected rising edge\n", __func__); + } + return IRQ_HANDLED; } static void xmm_power_init2_work(struct work_struct *work) @@ -959,7 +921,7 @@ static int xmm_power_driver_probe(struct platform_device *device) ipc_ap_wake_state = IPC_AP_WAKE_UNINIT; err = request_threaded_irq( gpio_to_irq(pdata->modem.xmm.ipc_ap_wake), - NULL, xmm_power_ipc_ap_wake_irq, + NULL, ipc_ap_wake_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "IPC_AP_WAKE_IRQ", NULL); if (err < 0) { @@ -972,9 +934,9 @@ static int xmm_power_driver_probe(struct platform_device *device) if (err < 0) pr_err("%s: enable_irq_wake error\n", __func__); - pr_debug("%s: AP_WAKE_INIT1\n", __func__); - /* ver 1130 or later starts in INIT1 state */ - ipc_ap_wake_state = IPC_AP_WAKE_INIT1; + pr_debug("%s: set state IPC_AP_WAKE_IRQ_READY\n", __func__); + /* ver 1130 or later start in IRQ_READY state */ + ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; } /* init work queue */ @@ -989,7 +951,6 @@ static int xmm_power_driver_probe(struct platform_device *device) queue_work(workqueue, &xmm_power_drv_data.work); /* init work objects */ - INIT_WORK(&init1_work, xmm_power_init1_work); INIT_WORK(&init2_work, xmm_power_init2_work); INIT_WORK(&L2_resume_work, xmm_power_l2_resume_work); INIT_WORK(&autopm_resume_work, xmm_power_autopm_resume); diff --git a/arch/arm/mach-tegra/baseband-xmm-power.h b/arch/arm/mach-tegra/baseband-xmm-power.h index 2ac6deececb7..97a26e033caa 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power.h +++ b/arch/arm/mach-tegra/baseband-xmm-power.h @@ -15,7 +15,7 @@ */ #ifndef BASEBAND_XMM_POWER_H -#define BASREBAND_XMM_POWER_H +#define BASEBAND_XMM_POWER_H #include #include @@ -102,9 +102,18 @@ enum baseband_xmm_powerstate_t { BBXMM_PS_LAST = -1, }; -irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id); +enum ipc_ap_wake_state_t { + IPC_AP_WAKE_UNINIT, + IPC_AP_WAKE_IRQ_READY, + IPC_AP_WAKE_INIT1, + IPC_AP_WAKE_INIT2, + IPC_AP_WAKE_L, + IPC_AP_WAKE_H, +}; + +irqreturn_t xmm_power_ipc_ap_wake_irq(int value); void baseband_xmm_set_power_status(unsigned int status); extern struct xmm_power_data xmm_power_drv_data; -#endif /* BASREBAND_XMM_POWER_H */ +#endif /* BASEBAND_XMM_POWER_H */ diff --git a/arch/arm/mach-tegra/baseband-xmm-power2.c b/arch/arm/mach-tegra/baseband-xmm-power2.c index fcbcdca5c24a..a79cd6fb499f 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power2.c +++ b/arch/arm/mach-tegra/baseband-xmm-power2.c @@ -49,16 +49,7 @@ MODULE_PARM_DESC(XYZ, static struct workqueue_struct *workqueue; static bool free_ipc_ap_wake_irq; - -static enum { - IPC_AP_WAKE_UNINIT, - IPC_AP_WAKE_IRQ_READY, - IPC_AP_WAKE_INIT1, - IPC_AP_WAKE_INIT2, - IPC_AP_WAKE_L, - IPC_AP_WAKE_H, -} ipc_ap_wake_state; - +static enum ipc_ap_wake_state_t ipc_ap_wake_state; static irqreturn_t xmm_power2_ipc_ap_wake_irq(int irq, void *dev_id) { @@ -66,8 +57,6 @@ static irqreturn_t xmm_power2_ipc_ap_wake_irq(int irq, void *dev_id) struct xmm_power_data *data = dev_id; struct baseband_power_platform_data *pdata = data->pdata; - pr_debug("%s\n", __func__); - /* check for platform data */ if (!pdata) return IRQ_HANDLED; @@ -79,8 +68,8 @@ static irqreturn_t xmm_power2_ipc_ap_wake_irq(int irq, void *dev_id) pr_err("%s - spurious irq\n", __func__); else if (ipc_ap_wake_state == IPC_AP_WAKE_IRQ_READY) { if (!value) { - pr_debug("%s: IPC_AP_WAKE_INIT1 got falling edge\n", - __func__); + pr_debug("%s: IPC_AP_WAKE_IRQ_READY got falling edge\n", + __func__); /* go to IPC_AP_WAKE_INIT2 state */ ipc_ap_wake_state = IPC_AP_WAKE_INIT2; /* queue work */ @@ -88,7 +77,7 @@ static irqreturn_t xmm_power2_ipc_ap_wake_irq(int irq, void *dev_id) BBXMM_WORK_INIT_FLASHLESS_PM_STEP2; queue_work(workqueue, &data->work); } else - pr_debug("%s: IPC_AP_WAKE_INIT1" + pr_debug("%s: IPC_AP_WAKE_IRQ_READY" " wait for falling edge\n", __func__); } else { if (!value) { @@ -98,7 +87,7 @@ static irqreturn_t xmm_power2_ipc_ap_wake_irq(int irq, void *dev_id) pr_debug("%s - rising\n", __func__); ipc_ap_wake_state = IPC_AP_WAKE_H; } - return xmm_power_ipc_ap_wake_irq(irq, dev_id); + return xmm_power_ipc_ap_wake_irq(value); } return IRQ_HANDLED; -- cgit v1.2.3 From c3f2e8c77c8e9a2a04c243fc2e639c90024e6162 Mon Sep 17 00:00:00 2001 From: Hunk Lin Date: Tue, 31 Jul 2012 00:19:09 +0800 Subject: MPU6050: Disable irq when suspend all sensors When we suspend all sensors, MPU6050 continue generating irqs. So set MPUREG_INT_ENABLE to 0 for saving power. Bug 1021448 Signed-off-by: Hunk Lin Change-Id: I90acb0b5e297c61c205a20b8eb54e6164a4d5b32 Reviewed-on: http://git-master/r/119344 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Prem Sasidharan GVS: Gerrit_Virtual_Submit Reviewed-by: Varun Wadekar (cherry picked from commit 420cba2c46f70f77945653be51656b6ae89d5397) Reviewed-on: http://git-master/r/123477 Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/misc/inv_mpu/mpu6050/mldl_cfg.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/misc/inv_mpu/mpu6050/mldl_cfg.c b/drivers/misc/inv_mpu/mpu6050/mldl_cfg.c index 22af0c200985..920f4ae8a4b7 100644 --- a/drivers/misc/inv_mpu/mpu6050/mldl_cfg.c +++ b/drivers/misc/inv_mpu/mpu6050/mldl_cfg.c @@ -1786,6 +1786,16 @@ int inv_mpu_suspend(struct mldl_cfg *mldl_cfg, return result; } } + /* Disable irq when suspend all sensors */ + if (sensors == INV_ALL_SENSORS) { + result = inv_serial_single_write( + gyro_handle, mldl_cfg->mpu_chip_info->addr, + MPUREG_INT_ENABLE, 0); + if (result) { + LOG_RESULT_LOCATION(result); + return result; + } + } mldl_cfg->inv_mpu_cfg->requested_sensors = (~sensors) & INV_ALL_SENSORS; return result; -- cgit v1.2.3 From 88977030123b53447a7cc7a286e2e944489270c1 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Tue, 31 Jul 2012 15:01:04 +0300 Subject: video: tegra: nvmap: fix usermode input validation nvmap_pin_ids accepts a list of handles to pin, which are passed directly from usermode when called from nvmap_ioctl_pinop. However, if invalid handles are passed in, the function might still access them as valid handles, and cause a crash. Bug 1023954 Change-Id: I6b98a2ef448bb496be7d569ddd4fb516fc399cba Signed-off-by: Tuomas Tynkkynen Reviewed-on: http://git-master/r/119667 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Juha Tukkinen (cherry picked from commit 70d4ced2d12a1251202d67ffae7f5c0b3013cc94) Reviewed-on: http://git-master/r/123478 Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/video/tegra/nvmap/nvmap.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c index b7fd695d04ee..a0dcf26337f8 100644 --- a/drivers/video/tegra/nvmap/nvmap.c +++ b/drivers/video/tegra/nvmap/nvmap.c @@ -3,7 +3,7 @@ * * Memory manager for Tegra GPU * - * Copyright (c) 2009-2011, NVIDIA Corporation. + * Copyright (c) 2009-2012, NVIDIA Corporation. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -271,7 +271,7 @@ int nvmap_pin_ids(struct nvmap_client *client, * if the caller crashes after pinning a global handle, the handle * will be permanently leaked. */ nvmap_ref_lock(client); - for (i = 0; i < nr && !ret; i++) { + for (i = 0; i < nr; i++) { ref = _nvmap_validate_id_locked(client, ids[i]); if (ref) { atomic_inc(&ref->pin); @@ -280,19 +280,19 @@ int nvmap_pin_ids(struct nvmap_client *client, struct nvmap_handle *verify; nvmap_ref_unlock(client); verify = nvmap_validate_get(client, ids[i]); - if (verify) + if (verify) { nvmap_warn(client, "%s pinning unreferenced " "handle %p\n", current->group_leader->comm, h[i]); - else + } else { + h[i] = NULL; ret = -EPERM; + } nvmap_ref_lock(client); } } nvmap_ref_unlock(client); - nr = i; - if (ret) goto out; @@ -317,6 +317,9 @@ out: if (ret) { nvmap_ref_lock(client); for (i = 0; i < nr; i++) { + if(!ids[i]) + continue; + ref = _nvmap_validate_id_locked(client, ids[i]); if (!ref) { nvmap_warn(client, "%s freed handle %p " @@ -330,7 +333,8 @@ out: nvmap_ref_unlock(client); for (i = 0; i < nr; i++) - nvmap_handle_put(h[i]); + if(h[i]) + nvmap_handle_put(h[i]); } return ret; -- cgit v1.2.3 From ba607c2d64b131b79ed93c683be206c55c8de4a4 Mon Sep 17 00:00:00 2001 From: Vinayak Pane Date: Tue, 29 May 2012 18:00:26 -0700 Subject: arm: tegra: xmm: protect xmm power state Added protection locks for xmm power state. Moving prints outside of spinlock. Revisit spinlock on global flags and rearrange in irq. Avoid kernel crash in case of remote-wakeup detected. Protect ipc_ap_wake_state in xmm on & off. Bug 1010131 Change-Id: Id53598b09bececd6f4ff1a948a492e6fcc56628c Signed-off-by: Vinayak Pane Reviewed-on: http://git-master/r/108427 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Michael Hsu GVS: Gerrit_Virtual_Submit Reviewed-by: Steve Lin (cherry picked from commit cd0b0f629c7709411600a944a72b06225a523bac) Reviewed-on: http://git-master/r/123480 Reviewed-by: Simone Willett Tested-by: Simone Willett --- arch/arm/mach-tegra/baseband-xmm-power.c | 132 +++++++++++++++++++------------ arch/arm/mach-tegra/baseband-xmm-power.h | 16 ++-- 2 files changed, 90 insertions(+), 58 deletions(-) diff --git a/arch/arm/mach-tegra/baseband-xmm-power.c b/arch/arm/mach-tegra/baseband-xmm-power.c index 9923bcdf4bd7..5a7cecde526b 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power.c +++ b/arch/arm/mach-tegra/baseband-xmm-power.c @@ -81,12 +81,12 @@ static enum baseband_xmm_powerstate_t baseband_xmm_powerstate; static enum ipc_ap_wake_state_t ipc_ap_wake_state; static struct workqueue_struct *workqueue; static struct work_struct init2_work; -static struct work_struct L2_resume_work; +static struct work_struct l2_resume_work; static struct work_struct autopm_resume_work; static bool register_hsic_device; static struct wake_lock wakelock; static struct usb_device *usbdev; -static bool CP_initiated_L2toL0; +static bool cp_initiated_l2tol0; static bool modem_power_on; static int power_onoff; static int reenable_autosuspend; @@ -164,6 +164,17 @@ static int tegra_baseband_rail_off(void) return 0; } +static inline enum baseband_xmm_powerstate_t baseband_xmm_get_power_status(void) +{ + enum baseband_xmm_powerstate_t status; + unsigned long flags; + + spin_lock_irqsave(&xmm_lock, flags); + status = baseband_xmm_powerstate; + spin_unlock_irqrestore(&xmm_lock, flags); + return status; +} + static int baseband_modem_power_on(struct baseband_power_platform_data *data) { /* set IPC_HSIC_ACTIVE active */ @@ -230,6 +241,7 @@ static int xmm_power_on(struct platform_device *device) struct baseband_power_platform_data *pdata = device->dev.platform_data; struct xmm_power_data *data = &xmm_power_drv_data; + unsigned long flags; int ret; pr_debug("%s {\n", __func__); @@ -239,13 +251,13 @@ static int xmm_power_on(struct platform_device *device) pr_err("%s: !pdata\n", __func__); return -EINVAL; } - if (baseband_xmm_powerstate != BBXMM_PS_UNINIT) + if (baseband_xmm_get_power_status() != BBXMM_PS_UNINIT) return -EINVAL; tegra_baseband_rail_on(); /* reset the state machine */ - baseband_xmm_powerstate = BBXMM_PS_INIT; + baseband_xmm_set_power_status(BBXMM_PS_INIT); modem_sleep_flag = false; pr_debug("%s wake_st(%d) modem version %lu\n", __func__, @@ -255,7 +267,10 @@ static int xmm_power_on(struct platform_device *device) if (!modem_flash) { pr_debug("%s - %d\n", __func__, __LINE__); + spin_lock_irqsave(&xmm_lock, flags); ipc_ap_wake_state = IPC_AP_WAKE_INIT2; + spin_unlock_irqrestore(&xmm_lock, flags); + /* register usb host controller only once */ if (register_hsic_device) { pr_debug("%s: register usb host controller\n", @@ -282,8 +297,11 @@ static int xmm_power_on(struct platform_device *device) */ pr_debug("%s: reset flash modem\n", __func__); + modem_power_on = false; + spin_lock_irqsave(&xmm_lock, flags); ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; + spin_unlock_irqrestore(&xmm_lock, flags); gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); xmm_power_reset_on(pdata); @@ -302,14 +320,14 @@ static int xmm_power_off(struct platform_device *device) struct baseband_power_platform_data *pdata = device->dev.platform_data; struct xmm_power_data *data = &xmm_power_drv_data; - int ret; unsigned long flags; pr_debug("%s {\n", __func__); - if (baseband_xmm_powerstate == BBXMM_PS_UNINIT) + if (baseband_xmm_get_power_status() == BBXMM_PS_UNINIT) return -EINVAL; + /* check for device / platform data */ if (!device) { pr_err("%s: !device\n", __func__); @@ -320,7 +338,10 @@ static int xmm_power_off(struct platform_device *device) return -EINVAL; } + spin_lock_irqsave(&xmm_lock, flags); ipc_ap_wake_state = IPC_AP_WAKE_UNINIT; + spin_unlock_irqrestore(&xmm_lock, flags); + ret = disable_irq_wake(gpio_to_irq(pdata->modem.xmm.ipc_ap_wake)); if (ret < 0) pr_err("%s: disable_irq_wake error\n", __func__); @@ -342,13 +363,15 @@ static int xmm_power_off(struct platform_device *device) /* sleep 1ms */ usleep_range(1000, 2000); - baseband_xmm_powerstate = BBXMM_PS_UNINIT; - modem_sleep_flag = false; - CP_initiated_L2toL0 = false; + baseband_xmm_set_power_status(BBXMM_PS_UNINIT); + spin_lock_irqsave(&xmm_lock, flags); + modem_sleep_flag = false; + cp_initiated_l2tol0 = false; wakeup_pending = false; system_suspending = false; spin_unlock_irqrestore(&xmm_lock, flags); + /* start registration process once again on xmm on */ register_hsic_device = true; @@ -429,23 +452,31 @@ static void xmm_power_l2_resume(void) if (!pdata) return; + /* erroneous remote-wakeup might call this from irq */ + if (in_interrupt() || in_atomic()) { + pr_err("%s: not allowed in interrupt\n", __func__); + return; + } + /* claim the wakelock here to avoid any system suspend */ if (!wake_lock_active(&wakelock)) wake_lock_timeout(&wakelock, HZ*2); - modem_sleep_flag = false; + spin_lock_irqsave(&xmm_lock, flags); + modem_sleep_flag = false; wakeup_pending = false; - spin_unlock_irqrestore(&xmm_lock, flags); - if (CP_initiated_L2toL0) { + if (cp_initiated_l2tol0) { + cp_initiated_l2tol0 = false; + queue_work(workqueue, &l2_resume_work); + spin_unlock_irqrestore(&xmm_lock, flags); pr_info("CP L2->L0\n"); - CP_initiated_L2toL0 = false; - queue_work(workqueue, &L2_resume_work); } else { /* set the slave wakeup request */ - pr_info("AP/CP L2->L0\n"); value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake); + spin_unlock_irqrestore(&xmm_lock, flags); if (value) { + pr_info("AP/CP L2->L0\n"); drv->hostwake = 0; /* wake bb */ gpio_set_value(pdata->modem.xmm.ipc_bb_wake, 1); @@ -473,16 +504,21 @@ retry: } } - +/* this function holds xmm_lock */ void baseband_xmm_set_power_status(unsigned int status) { struct baseband_power_platform_data *data = xmm_power_drv_data.pdata; int value = 0; unsigned long flags; - if (baseband_xmm_powerstate == status) + if (baseband_xmm_get_power_status() == status) return; - pr_debug("%s\n", __func__); + + /* avoid prints inside spinlock */ + if (status <= BBXMM_PS_L2) + pr_info("%s\n", status == BBXMM_PS_L0 ? "L0" : "L2"); + + spin_lock_irqsave(&xmm_lock, flags); switch (status) { case BBXMM_PS_L0: if (modem_sleep_flag) { @@ -490,7 +526,6 @@ void baseband_xmm_set_power_status(unsigned int status) * xmm_power_driver_handle_resume(data); */ } - pr_info("L0\n"); baseband_xmm_powerstate = status; if (!wake_lock_active(&wakelock)) wake_lock_timeout(&wakelock, HZ*2); @@ -506,15 +541,13 @@ void baseband_xmm_set_power_status(unsigned int status) } break; case BBXMM_PS_L2: - pr_info("L2\n"); baseband_xmm_powerstate = status; - spin_lock_irqsave(&xmm_lock, flags); if (wakeup_pending) { spin_unlock_irqrestore(&xmm_lock, flags); pr_debug("%s: wakeup pending\n", __func__); xmm_power_l2_resume(); + spin_lock_irqsave(&xmm_lock, flags); } else { - spin_unlock_irqrestore(&xmm_lock, flags); if (wake_lock_active(&wakelock)) wake_unlock(&wakelock); modem_sleep_flag = true; @@ -522,15 +555,14 @@ void baseband_xmm_set_power_status(unsigned int status) break; case BBXMM_PS_L2TOL0: pr_debug("L2TOL0\n"); - spin_lock_irqsave(&xmm_lock, flags); system_suspending = false; wakeup_pending = false; - spin_unlock_irqrestore(&xmm_lock, flags); /* do this only from L2 state */ if (baseband_xmm_powerstate == BBXMM_PS_L2) { baseband_xmm_powerstate = status; - pr_debug("BB XMM POWER STATE = %d\n", status); + spin_unlock_irqrestore(&xmm_lock, flags); xmm_power_l2_resume(); + spin_lock_irqsave(&xmm_lock, flags); } baseband_xmm_powerstate = status; break; @@ -539,6 +571,7 @@ void baseband_xmm_set_power_status(unsigned int status) baseband_xmm_powerstate = status; break; } + spin_unlock_irqrestore(&xmm_lock, flags); pr_debug("BB XMM POWER STATE = %d\n", status); } EXPORT_SYMBOL_GPL(baseband_xmm_set_power_status); @@ -552,38 +585,40 @@ irqreturn_t xmm_power_ipc_ap_wake_irq(int value) /* modem wakeup part */ if (!value) { pr_debug("%s - falling\n", __func__); - if (drv->hostwake == 0) { - /* AP L2 to L0 wakeup */ - pr_debug("received wakeup ap l2->l0\n"); - drv->hostwake = 1; - wake_up_interruptible(&drv->bb_wait); - } + spin_lock(&xmm_lock); + + /* AP L2 to L0 wakeup */ + pr_debug("received wakeup ap l2->l0\n"); + drv->hostwake = 1; + wake_up_interruptible(&drv->bb_wait); + /* First check it a CP ack or CP wake */ value = gpio_get_value(data->modem.xmm.ipc_bb_wake); if (value) { pr_debug("cp ack for bb_wake\n"); ipc_ap_wake_state = IPC_AP_WAKE_L; + spin_unlock(&xmm_lock); return IRQ_HANDLED; } - spin_lock(&xmm_lock); wakeup_pending = true; - if (system_suspending) { - spin_unlock(&xmm_lock); - pr_info("Set wakeup_pending = 1 in system_" - " suspending!!!\n"); - } else { - if (baseband_xmm_powerstate == BBXMM_PS_L2) { - CP_initiated_L2toL0 = true; + if (system_suspending) + pr_info("set wakeup_pending 1 in system_suspending\n"); + else { + if (baseband_xmm_powerstate == BBXMM_PS_L2 || + baseband_xmm_powerstate == BBXMM_PS_L2TOL0) { + cp_initiated_l2tol0 = true; spin_unlock(&xmm_lock); baseband_xmm_set_power_status(BBXMM_PS_L2TOL0); - } else { - CP_initiated_L2toL0 = true; - spin_unlock(&xmm_lock); - } + spin_lock(&xmm_lock); + } else + cp_initiated_l2tol0 = true; + } + /* save gpio state */ ipc_ap_wake_state = IPC_AP_WAKE_L; + spin_unlock(&xmm_lock); } else { pr_debug("%s - rising\n", __func__); value = gpio_get_value(data->modem.xmm.ipc_hsic_active); @@ -845,9 +880,9 @@ static int xmm_power_pm_notifier_event(struct notifier_block *this, if (wakeup_pending && (baseband_xmm_powerstate == BBXMM_PS_L2)) { wakeup_pending = false; + cp_initiated_l2tol0 = true; spin_unlock_irqrestore(&xmm_lock, flags); pr_info("%s : Service Pending CP wakeup\n", __func__); - CP_initiated_L2toL0 = true; baseband_xmm_set_power_status(BBXMM_PS_L2TOL0); return NOTIFY_OK; } @@ -952,13 +987,13 @@ static int xmm_power_driver_probe(struct platform_device *device) /* init work objects */ INIT_WORK(&init2_work, xmm_power_init2_work); - INIT_WORK(&L2_resume_work, xmm_power_l2_resume_work); + INIT_WORK(&l2_resume_work, xmm_power_l2_resume_work); INIT_WORK(&autopm_resume_work, xmm_power_autopm_resume); /* init state variables */ register_hsic_device = true; - CP_initiated_L2toL0 = false; - baseband_xmm_powerstate = BBXMM_PS_UNINIT; + cp_initiated_l2tol0 = false; + baseband_xmm_set_power_status(BBXMM_PS_UNINIT); spin_lock_irqsave(&xmm_lock, flags); wakeup_pending = false; system_suspending = false; @@ -987,9 +1022,8 @@ static int xmm_power_driver_remove(struct platform_device *device) usb_unregister_notify(&usb_xmm_nb); /* free baseband irq(s) */ - if (modem_flash && modem_pm) { + if (modem_flash && modem_pm) free_irq(gpio_to_irq(pdata->modem.xmm.ipc_ap_wake), NULL); - } /* free baseband gpio(s) */ gpio_free_array(tegra_baseband_gpios, diff --git a/arch/arm/mach-tegra/baseband-xmm-power.h b/arch/arm/mach-tegra/baseband-xmm-power.h index 97a26e033caa..55c81833ba04 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power.h +++ b/arch/arm/mach-tegra/baseband-xmm-power.h @@ -90,15 +90,13 @@ struct xmm_power_data { }; enum baseband_xmm_powerstate_t { - BBXMM_PS_UNINIT = 0, - BBXMM_PS_INIT = 1, - BBXMM_PS_L0 = 2, - BBXMM_PS_L0TOL2 = 3, - BBXMM_PS_L2 = 4, - BBXMM_PS_L2TOL0 = 5, - BBXMM_PS_L2TOL3 = 6, - BBXMM_PS_L3 = 7, - BBXMM_PS_L3TOL0 = 8, + BBXMM_PS_L0 = 0, + BBXMM_PS_L2 = 1, + BBXMM_PS_L0TOL2 = 2, + BBXMM_PS_L2TOL0 = 3, + BBXMM_PS_UNINIT = 4, + BBXMM_PS_INIT = 5, + BBXMM_PS_L3 = 6, BBXMM_PS_LAST = -1, }; -- cgit v1.2.3 From 8def0b1717c80e997b99ea71852f5722c25318d4 Mon Sep 17 00:00:00 2001 From: Suresh Mangipudi Date: Wed, 1 Aug 2012 11:20:58 +0530 Subject: arm: tegra: usb: link ulpi resume sequence lp0 resume for link_ulpi_phy has been modified.To fix the issue of frequent disconnects while resuming from LP0. Bug 997267 Change-Id: If92b8245b154e9b872b80d80a2ab359c87107a39 Signed-off-by: Suresh Mangipudi Reviewed-on: http://git-master/r/119511 Reviewed-by: Simone Willett Tested-by: Simone Willett (cherry picked from commit d228a8472dfa7b12e8841bc340ce54b9a7c1db10) Reviewed-on: http://git-master/r/123481 Reviewed-by: Automatic_Commit_Validation_User --- arch/arm/mach-tegra/tegra2_usb_phy.c | 186 +++++++++++++++++++++++++++-------- arch/arm/mach-tegra/tegra_usb_phy.h | 1 + 2 files changed, 147 insertions(+), 40 deletions(-) diff --git a/arch/arm/mach-tegra/tegra2_usb_phy.c b/arch/arm/mach-tegra/tegra2_usb_phy.c index 2feb2e96f55e..892e3ba8ec71 100644 --- a/arch/arm/mach-tegra/tegra2_usb_phy.c +++ b/arch/arm/mach-tegra/tegra2_usb_phy.c @@ -47,11 +47,13 @@ #define USB_USBSTS_SRI (1 << 7) #define USB_USBSTS_HCH (1 << 12) +#define USB_USBINTR 0x148 + #define USB_ASYNCLISTADDR 0x158 #define USB_TXFILLTUNING 0x164 #define USB_FIFO_TXFILL_THRES(x) (((x) & 0x1f) << 16) -#define USB_FIFO_TXFILL_MASK 0x1f0000 +#define USB_FIFO_TXFILL_MASK 0x3f0000 #define ULPI_VIEWPORT 0x170 #define ULPI_WAKEUP (1 << 31) @@ -69,6 +71,7 @@ #define USB_PORTSC_PP (1 << 12) #define USB_PORTSC_LS(x) (((x) & 0x3) << 10) #define USB_PORTSC_SUSP (1 << 7) +#define USB_PORTSC_RESUME (1 << 6) #define USB_PORTSC_OCC (1 << 5) #define USB_PORTSC_PEC (1 << 3) #define USB_PORTSC_PE (1 << 2) @@ -715,7 +718,8 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy) val |= USB_PHY_CLK_VALID_INT_ENB; writel(val, base + USB_SUSP_CTRL); } else { - /* Disable PHY clock valid interrupts while going into suspend*/ + /* Disable PHY clock valid interrupts + while going into suspend*/ val = readl(base + USB_SUSP_CTRL); val &= ~USB_PHY_CLK_VALID_INT_ENB; writel(val, base + USB_SUSP_CTRL); @@ -937,7 +941,8 @@ static int utmi_phy_resume(struct tegra_usb_phy *phy) if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RESET, 0, 2500) < 0) { - pr_err("%s: timeout waiting for reset\n", __func__); + pr_err("%s: timeout waiting for reset\n", + __func__); } val = readl(base + USB_USBMODE_REG_OFFSET); @@ -954,7 +959,8 @@ static int utmi_phy_resume(struct tegra_usb_phy *phy) if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RS, USB_USBCMD_RS, 2500) < 0) { - pr_err("%s: timeout waiting for run bit\n", __func__); + pr_err("%s: timeout waiting for run bit\n", + __func__); } /* Enable Port Power */ @@ -964,7 +970,8 @@ static int utmi_phy_resume(struct tegra_usb_phy *phy) udelay(10); DBG("USB_USBSTS[0x%x] USB_PORTSC[0x%x]\n", - readl(base + USB_USBSTS), readl(base + USB_PORTSC)); + readl(base + USB_USBSTS), + readl(base + USB_PORTSC)); } } else { /* Restoring the pad powers */ @@ -1358,7 +1365,7 @@ static int ulpi_link_phy_open(struct tegra_usb_phy *phy) phy->ulpi_vp = otg_ulpi_create(&ulpi_viewport_access_ops, 0); phy->ulpi_vp->io_priv = phy->regs + ULPI_VIEWPORT; - + phy->linkphy_init = true; return err; } @@ -1454,49 +1461,74 @@ static int ulpi_link_phy_power_on(struct tegra_usb_phy *phy) } val = readl(base + USB_SUSP_CTRL); - val |= UHSIC_RESET; - writel(val, base + USB_SUSP_CTRL); - val = readl(base + ULPI_TIMING_CTRL_0); - val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP; - writel(val, base + ULPI_TIMING_CTRL_0); + /* Case for lp0 */ + if (!(val & UHSIC_RESET)) { + val |= UHSIC_RESET; + writel(val, base + USB_SUSP_CTRL); - val = readl(base + USB_SUSP_CTRL); - val |= ULPI_PHY_ENABLE; - writel(val, base + USB_SUSP_CTRL); + val = 0; + writel(val, base + ULPI_TIMING_CTRL_1); - val = readl(base + USB_SUSP_CTRL); - val |= USB_SUSP_CLR; - writel(val, base + USB_SUSP_CTRL); + ulpi_set_trimmer(phy); - if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, - USB_PHY_CLK_VALID, 2500)) - pr_err("%s: timeout waiting for phy to stabilize\n", __func__); + val = readl(base + ULPI_TIMING_CTRL_0); + val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP; + writel(val, base + ULPI_TIMING_CTRL_0); +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAA, TEGRA_TRI_NORMAL); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAB, TEGRA_TRI_NORMAL); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_UDA, TEGRA_TRI_NORMAL); +#endif + val = readl(base + USB_SUSP_CTRL); + val |= ULPI_PHY_ENABLE; + writel(val, base + USB_SUSP_CTRL); - if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, USB_CLKEN, - USB_CLKEN, 2500)) - pr_err("%s: timeout waiting for AHB clock\n", __func__); + if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, + USB_PHY_CLK_VALID, USB_PHY_CLK_VALID, 2500) < 0) + pr_err("%s: timeout waiting for phy" \ + "to stabilize\n", __func__); - val = readl(base + USB_SUSP_CTRL); - val &= ~USB_SUSP_CLR; - writel(val, base + USB_SUSP_CTRL); + val = readl(base + USB_TXFILLTUNING); + if ((val & USB_FIFO_TXFILL_MASK) != + USB_FIFO_TXFILL_THRES(0x10)) { + val = USB_FIFO_TXFILL_THRES(0x10); + writel(val, base + USB_TXFILLTUNING); + } + } else { + /* Case for auto resume*/ + val = readl(base + USB_SUSP_CTRL); + val |= USB_SUSP_CLR; + writel(val, base + USB_SUSP_CTRL); - val = 0; - writel(val, base + ULPI_TIMING_CTRL_1); + if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, + USB_PHY_CLK_VALID, USB_PHY_CLK_VALID, 2500) < 0) + pr_err("%s: timeout waiting for phy" \ + "to stabilize\n", __func__); - ulpi_set_trimmer(phy); + if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, + USB_CLKEN, USB_CLKEN, 2500) < 0) + pr_err("%s: timeout waiting for AHB clock\n", __func__); - /* Fix VbusInvalid due to floating VBUS */ - ret = otg_io_write(phy->ulpi_vp, 0x40, 0x08); - if (ret) { - pr_err("%s: ulpi write failed\n", __func__); - return ret; + val = readl(base + USB_SUSP_CTRL); + val &= ~USB_SUSP_CLR; + writel(val, base + USB_SUSP_CTRL); } + if (phy->linkphy_init) { + /* To be done only incase of coldboot*/ + /* Fix VbusInvalid due to floating VBUS */ + ret = otg_io_write(phy->ulpi_vp, 0x40, 0x08); + if (ret) { + pr_err("%s: ulpi write failed\n", __func__); + return ret; + } - ret = otg_io_write(phy->ulpi_vp, 0x80, 0x0B); - if (ret) { - pr_err("%s: ulpi write failed\n", __func__); - return ret; + ret = otg_io_write(phy->ulpi_vp, 0x80, 0x0B); + if (ret) { + pr_err("%s: ulpi write failed\n", __func__); + return ret; + } + phy->linkphy_init = false; } val = readl(base + USB_PORTSC); @@ -1514,6 +1546,7 @@ static inline void ulpi_link_phy_set_tristate(bool enable) #ifdef CONFIG_ARCH_TEGRA_2x_SOC int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL; + tegra_pinmux_set_tristate(TEGRA_PINGROUP_CDEV2, tristate); tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAA, tristate); tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAB, tristate); tegra_pinmux_set_tristate(TEGRA_PINGROUP_UDA, tristate); @@ -1539,6 +1572,7 @@ static void ulpi_link_phy_restore_end(struct tegra_usb_phy *phy) { unsigned long val; void __iomem *base = phy->regs; + int ret; DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); @@ -1547,6 +1581,13 @@ static void ulpi_link_phy_restore_end(struct tegra_usb_phy *phy) writel(val, base + ULPI_TIMING_CTRL_0); ulpi_link_phy_set_tristate(false); + + udelay(10); + ret = otg_io_write(phy->ulpi_vp, 0x55, 0x04); + if (ret) { + pr_err("%s: ulpi write failed\n", __func__); + return; + } } static int ulpi_link_phy_resume(struct tegra_usb_phy *phy) @@ -1566,7 +1607,70 @@ static int ulpi_link_phy_resume(struct tegra_usb_phy *phy) return status; } -static inline void ulpi_pinmux_bypass(struct tegra_usb_phy *phy, bool enable) +static int ulpi_link_phy_pre_resume(struct tegra_usb_phy *phy, + bool remote_wakeup) +{ + int status = 0; + unsigned long val; + void __iomem *base = phy->regs; + DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); + + val = readl(base + USB_PORTSC); + if (val & USB_PORTSC_RESUME) { + + val = readl(base + USB_USBCMD); + val &= ~USB_USBCMD_RS; + writel(val, base + USB_USBCMD); + + /* detect remote wakeup */ + msleep(20); + + val = readl(base + USB_PORTSC); + + /* Poll until the controller clears RESUME and SUSPEND */ + if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, + USB_PORTSC_RESUME, 0, 2500)) + pr_err("%s: timeout waiting for RESUME\n", __func__); + if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, + USB_PORTSC_SUSP, 0, 2500)) + pr_err("%s: timeout waiting for SUSPEND\n", __func__); + + /* Since we skip remote wakeup event, + put controller in suspend again and + resume port later */ + val = readl(base + USB_PORTSC); + val |= USB_PORTSC_SUSP; + writel(val, base + USB_PORTSC); + mdelay(4); + /* Wait until port suspend completes */ + if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, + USB_PORTSC_SUSP, USB_PORTSC_SUSP, 2500)) + pr_err("%s: timeout waiting for" \ + "PORT_SUSPEND\n", __func__); + + /* Disable interrupts */ + writel(0, base + USB_USBINTR); + /* Clear the run bit to stop SOFs - 2LS WAR */ + val = readl(base + USB_USBCMD); + val &= ~USB_USBCMD_RS; + writel(val, base + USB_USBCMD); + if (usb_phy_reg_status_wait(base + USB_USBSTS, + USB_USBSTS_HCH, USB_USBSTS_HCH, 2000)) { + pr_err("%s: timeout waiting for" \ + "USB_USBSTS_HCH\n", __func__); + } + usb_phy_wait_for_sof(phy); + + val = readl(base + USB_USBCMD); + val |= USB_USBCMD_RS; + writel(val, base + USB_USBCMD); + } + return status; +} + + +static inline void ulpi_pinmux_bypass(struct tegra_usb_phy *phy, + bool enable) { unsigned long val; void __iomem *base = phy->regs; @@ -1799,7 +1903,8 @@ static int ulpi_null_phy_power_on(struct tegra_usb_phy *phy) val = readl(base + ULPIS2S_CTRL); val |= ULPIS2S_ENA; val |= ULPIS2S_SUPPORT_DISCONNECT; - val |= ULPIS2S_SPARE((phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) ? 3 : 1); + val |= ULPIS2S_SPARE((phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) + ? 3 : 1); val |= ULPIS2S_PLLU_MASTER_BLASTER60; writel(val, base + ULPIS2S_CTRL); @@ -1910,6 +2015,7 @@ static struct tegra_usb_phy_ops ulpi_link_phy_ops = { .power_on = ulpi_link_phy_power_on, .power_off = ulpi_link_phy_power_off, .resume = ulpi_link_phy_resume, + .pre_resume = ulpi_link_phy_pre_resume, }; static struct tegra_usb_phy_ops ulpi_null_phy_ops = { diff --git a/arch/arm/mach-tegra/tegra_usb_phy.h b/arch/arm/mach-tegra/tegra_usb_phy.h index 674e8b8ffd18..05aa88296619 100644 --- a/arch/arm/mach-tegra/tegra_usb_phy.h +++ b/arch/arm/mach-tegra/tegra_usb_phy.h @@ -98,6 +98,7 @@ struct tegra_usb_phy { bool ulpi_clk_padout_ena; bool pmc_sleepwalk; bool bus_reseting; + bool linkphy_init; }; int usb_phy_reg_status_wait(void __iomem *reg, u32 mask, -- cgit v1.2.3 From 98582a55ea256bf9f3fd27a7ea06b7481489179f Mon Sep 17 00:00:00 2001 From: Suresh Mangipudi Date: Wed, 1 Aug 2012 16:57:51 +0530 Subject: arm: tegra: usbphy: disable PLLU clock Disable the MASTER_BLASTER clock for the null phy interface when usb_bus is suspended. Bug 992861 Change-Id: I86ff559148f9a128ee48bbea2564493f4286b420 Signed-off-by: Suresh Mangipudi Reviewed-on: http://git-master/r/120006 Reviewed-by: Simone Willett Tested-by: Simone Willett (cherry picked from commit 6e789ddf027ae942bfb7e442cc66e218f919bb28) Reviewed-on: http://git-master/r/123482 Reviewed-by: Automatic_Commit_Validation_User --- arch/arm/mach-tegra/tegra3_usb_phy.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-tegra/tegra3_usb_phy.c b/arch/arm/mach-tegra/tegra3_usb_phy.c index 4fbeb74fc347..feb5463ef6aa 100644 --- a/arch/arm/mach-tegra/tegra3_usb_phy.c +++ b/arch/arm/mach-tegra/tegra3_usb_phy.c @@ -2666,6 +2666,9 @@ static void ulpi_null_phy_close(struct tegra_usb_phy *phy) static int ulpi_null_phy_power_off(struct tegra_usb_phy *phy) { + unsigned int val; + void __iomem *base = phy->regs; + DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); if (!phy->phy_clk_on) { @@ -2677,6 +2680,9 @@ static int ulpi_null_phy_power_off(struct tegra_usb_phy *phy) phy->phy_clk_on = false; phy->hw_accessible = false; ulpi_null_phy_set_tristate(true); + val = readl(base + ULPIS2S_CTRL); + val &= ~ULPIS2S_PLLU_MASTER_BLASTER60; + writel(val, base + ULPIS2S_CTRL); return 0; } -- cgit v1.2.3 From 762f7c716aeb9d8f557174708674ca3ae1cf2bea Mon Sep 17 00:00:00 2001 From: Rakesh Bodla Date: Wed, 8 Aug 2012 11:15:31 +0530 Subject: arm: tegra: usb_phy: remove duplicate code Remove duplicate code. Change-Id: I9c9979f489d93c458f5e494fbb69008b89578b8d Signed-off-by: Rakesh Bodla Reviewed-on: http://git-master/r/121988 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Venkat Moganty (cherry picked from commit 89c0dc999188865e0e6d58327d7beafb65587ea2) Reviewed-on: http://git-master/r/123483 Reviewed-by: Simone Willett Tested-by: Simone Willett --- arch/arm/mach-tegra/tegra3_usb_phy.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/arm/mach-tegra/tegra3_usb_phy.c b/arch/arm/mach-tegra/tegra3_usb_phy.c index feb5463ef6aa..af9eaab782c7 100644 --- a/arch/arm/mach-tegra/tegra3_usb_phy.c +++ b/arch/arm/mach-tegra/tegra3_usb_phy.c @@ -636,12 +636,6 @@ static void utmip_setup_pmc_wake_detect(struct tegra_usb_phy *phy) val &= ~USBON_VAL(inst); writel(val, pmc_base + PMC_UTMIP_UHSIC_FAKE); - /* Enable which type of event can trigger a walk, - in this case usb_line_wake */ - val = readl(pmc_base + PMC_SLEEPWALK_CFG); - val |= UTMIP_LINEVAL_WALK_EN(inst); - writel(val, pmc_base + PMC_SLEEPWALK_CFG); - /* Enable which type of event can trigger a walk, * in this case usb_line_wake */ val = readl(pmc_base + PMC_SLEEPWALK_CFG); -- cgit v1.2.3 From 3036c2fb5f28465c357731ff3ed1d56d1c6a8585 Mon Sep 17 00:00:00 2001 From: Rakesh Bodla Date: Wed, 8 Aug 2012 12:18:03 +0530 Subject: usb: otg: tegra: fix compilations errors Werror flag is enabled now. Fixing the compilations errors when DEBUG is enabled. Change-Id: I909dd177eedfd72f1f71d1a546fc40c301bd1aa7 Signed-off-by: Rakesh Bodla Reviewed-on: http://git-master/r/122033 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Venkat Moganty (cherry picked from commit eb623030d171e1369760107886636f2985b39fc3) Reviewed-on: http://git-master/r/123484 Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/usb/otg/tegra-otg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/otg/tegra-otg.c b/drivers/usb/otg/tegra-otg.c index 0519c86fa7c7..a0043db62252 100644 --- a/drivers/usb/otg/tegra-otg.c +++ b/drivers/usb/otg/tegra-otg.c @@ -230,7 +230,7 @@ static void irq_work(struct work_struct *work) status = tegra->int_status; /* Debug prints */ - DBG("%s(%d) status = 0x%x\n", __func__, __LINE__, status); + DBG("%s(%d) status = 0x%lx\n", __func__, __LINE__, status); if ((status & USB_ID_INT_STATUS) && (status & USB_VBUS_INT_STATUS)) DBG("%s(%d) got vbus & id interrupt\n", __func__, __LINE__); @@ -260,10 +260,10 @@ static irqreturn_t tegra_otg_irq(int irq, void *data) spin_lock_irqsave(&tegra->lock, flags); val = otg_readl(tegra, USB_PHY_WAKEUP); - DBG("%s(%d) interrupt val = 0x%x\n", __func__, __LINE__, val); + DBG("%s(%d) interrupt val = 0x%lx\n", __func__, __LINE__, val); if (val & (USB_VBUS_INT_EN | USB_ID_INT_EN)) { - DBG("%s(%d) PHY_WAKEUP = 0x%x\n", __func__, __LINE__, val); + DBG("%s(%d) PHY_WAKEUP = 0x%lx\n", __func__, __LINE__, val); otg_writel(tegra, val, USB_PHY_WAKEUP); if ((val & USB_ID_INT_STATUS) || (val & USB_VBUS_INT_STATUS)) { tegra->int_status = val; -- cgit v1.2.3 From 1720ea034d6913886b82541e2f2742de1faf785c Mon Sep 17 00:00:00 2001 From: Rakesh Bodla Date: Wed, 8 Aug 2012 14:14:53 +0530 Subject: usb: gadget: tegra: fix compilation issue Fixing the potential compilation this is currently masked as CONFIG_USB_OTG_UTILS is enabled. Change-Id: Ie10e5fc252156b8b904d387d87a11136fcc3f4c1 Signed-off-by: Rakesh Bodla Reviewed-on: http://git-master/r/122043 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Venkat Moganty (cherry picked from commit a50e57e22bb42aa20e59686af148d24f09291c54) Reviewed-on: http://git-master/r/123485 Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/usb/gadget/tegra_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/tegra_udc.c b/drivers/usb/gadget/tegra_udc.c index db5b72856e8e..3e82222054bc 100644 --- a/drivers/usb/gadget/tegra_udc.c +++ b/drivers/usb/gadget/tegra_udc.c @@ -2658,7 +2658,7 @@ static int __init tegra_udc_probe(struct platform_device *pdev) } #else /* Power down the phy if cable is not connected */ - if (!vbus_enabled()) + if (!vbus_enabled(udc)) tegra_usb_phy_power_off(udc->phy); #endif -- cgit v1.2.3 From 0c8630aca8234b27c42c5b790aedf72c5c97c05a Mon Sep 17 00:00:00 2001 From: Rakesh Bodla Date: Wed, 8 Aug 2012 14:36:13 +0530 Subject: arm: tegra: usb_phy: fix null pointer dereference Fixing the null pointer dereference crash. Also modifying USB driver not to give up in case if there is no avdd_usb regulator. Bug 1029852 Change-Id: I3232b7fa1580a0dc1aadd47b138e5eeae05af6f0 Signed-off-by: Rakesh Bodla Reviewed-on: http://git-master/r/121984 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Venkat Moganty (cherry picked from commit 48d8c7c91ea5acddf23f74abc801c89c9f16680f) Reviewed-on: http://git-master/r/123486 Reviewed-by: Simone Willett Tested-by: Simone Willett --- arch/arm/mach-tegra/usb_phy.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c index 78f60e1aafb1..7df5db0c91fe 100644 --- a/arch/arm/mach-tegra/usb_phy.c +++ b/arch/arm/mach-tegra/usb_phy.c @@ -284,8 +284,6 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev) ERR("inst:[%d] couldn't get regulator avdd_usb: %ld\n", phy->inst, PTR_ERR(phy->vdd_reg)); phy->vdd_reg = NULL; - err = PTR_ERR(phy->vdd_reg); - goto fail_io; } err = tegra_usb_phy_get_clocks(phy); -- cgit v1.2.3 From 07e99a1ae297fea4c019115a73313220f8c68e21 Mon Sep 17 00:00:00 2001 From: Allen Yu Date: Wed, 8 Aug 2012 14:50:40 +0800 Subject: power: smb349: correct charger status When tegra-otg suspends with charger cable connected, the charger state and type should not be changed, neither should the charger callback be executed. SMB349 has a debounce delay of ~20ms +/- 3 after cable is unpluged and will stop all I2C functions for 2.3ms when getting reset to POR. Add 50ms' delay before reading charger status to avoid I2C error and make sure we get the right charger state. Bug 1024735 Change-Id: I1667b23df768b46b524c6578c4bee09e131d9f96 Signed-off-by: Allen Yu Reviewed-on: http://git-master/r/120905 Reviewed-by: Bharat Nihalani GVS: Gerrit_Virtual_Submit (cherry picked from commit 71f038602f3417417aec99470fabb287ec8886fd) Reviewed-on: http://git-master/r/123487 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/power/smb349-charger.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/power/smb349-charger.c b/drivers/power/smb349-charger.c index 134b8154a2b9..c6dc43158b82 100644 --- a/drivers/power/smb349-charger.c +++ b/drivers/power/smb349-charger.c @@ -406,6 +406,19 @@ static int smb349_enable_charging(struct regulator_dev *rdev, int ret; if (!max_uA) { + /* Wait for SMB349 to debounce and get reset to POR when cable is unpluged */ + msleep(50); + + ret = smb349_read(client, SMB349_STS_REG_C); + if (ret < 0) { + dev_err(&client->dev, "%s(): Failed in reading register" + "0x%02x\n", __func__, SMB349_STS_REG_C); + return ret; + } + + if (ret & CHARGING) + return 0; + charger->state = stopped; charger->chrg_type = NONE; } else { -- cgit v1.2.3 From c454e30bf4575ad4a8df15b40f7121d6aa46787b Mon Sep 17 00:00:00 2001 From: Krishna Yarlagadda Date: Wed, 8 Aug 2012 17:01:10 +0530 Subject: USB: otg: delay device disconnect Device disconnect during resume might fail if notification clients for this device removal are not ready. Disconnecting device after the resume is complete. Bug 1024496 Change-Id: Ia806e177d2dd2b1b43d3fea7a4af45f0d4a93cd4 Signed-off-by: Krishna Yarlagadda Reviewed-on: http://git-master/r/122079 Reviewed-by: Simone Willett Tested-by: Simone Willett (cherry picked from commit df73b460996b2f6e2c0b0d93b3679d6dca9d4615) Reviewed-on: http://git-master/r/123488 Reviewed-by: Automatic_Commit_Validation_User --- drivers/usb/otg/tegra-otg.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/usb/otg/tegra-otg.c b/drivers/usb/otg/tegra-otg.c index a0043db62252..521fbac412f4 100644 --- a/drivers/usb/otg/tegra-otg.c +++ b/drivers/usb/otg/tegra-otg.c @@ -533,7 +533,6 @@ static void tegra_otg_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct tegra_otg_data *tegra = platform_get_drvdata(pdev); - struct otg_transceiver *otg = &tegra->otg; int val; unsigned long flags; DBG("%s(%d) BEGIN\n", __func__, __LINE__); @@ -548,10 +547,6 @@ static void tegra_otg_resume(struct device *dev) DBG("%s(%d) PHY WAKEUP register : 0x%x\n", __func__, __LINE__, val); clk_disable(tegra->clk); - /* Handle if host cable is replaced with device during suspend state */ - if (otg->state == OTG_STATE_A_HOST && (val & USB_ID_STATUS)) - tegra_change_otg_state(tegra, OTG_STATE_A_SUSPEND); - /* Enable interrupt and call work to set to appropriate state */ spin_lock_irqsave(&tegra->lock, flags); if (tegra->builtin_host) @@ -561,7 +556,7 @@ static void tegra_otg_resume(struct device *dev) USB_ID_PIN_WAKEUP_EN; spin_unlock_irqrestore(&tegra->lock, flags); - irq_work(&tegra->work); + schedule_work(&tegra->work); enable_interrupt(tegra, true); -- cgit v1.2.3 From a357f921c76f858fbd12a94cbcf4a146d45d1f6d Mon Sep 17 00:00:00 2001 From: Venu Byravarasu Date: Wed, 8 Aug 2012 17:29:36 +0530 Subject: usb: host: fix tegra_ehci_remove() warnings usb_put_hcd calls hcd_release which frees up memory allocated for hcd. As iounmap is called after usb_put_hcd and it is trying to access hcd->regs, getting warning messages during unload of USB. Hence fixing it. bug 1023362 Change-Id: Ic339395edad9a76a9eeae290eff3517d2c714477 Signed-off-by: Venu Byravarasu Reviewed-on: http://git-master/r/122088 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Krishna Yarlagadda Tested-by: Krishna Yarlagadda Reviewed-by: Venkat Moganty (cherry picked from commit 7b3a327acb3a63fddc14f2b3ecd19a7ea8f41b3e) Reviewed-on: http://git-master/r/123489 Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/usb/host/ehci-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index e04e824cbafd..af6fa87fb645 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -551,10 +551,10 @@ static int tegra_ehci_remove(struct platform_device *pdev) tegra_usb_phy_power_on(tegra->phy); usb_remove_hcd(hcd); - usb_put_hcd(hcd); tegra_usb_phy_power_off(tegra->phy); tegra_usb_phy_close(tegra->phy); iounmap(hcd->regs); + usb_put_hcd(hcd); return 0; } -- cgit v1.2.3 From 5c3244318c2e3509e673964007f1b3331de608d7 Mon Sep 17 00:00:00 2001 From: Karthik Ramakrishnan Date: Wed, 20 Jun 2012 00:23:07 -0700 Subject: arm: tegra: enterprise: Pinmux changes for Enterprise A04 Pinmux configurations updated according to the schematics of Enterprise A04. The unused pins are marked Tristate and turned low. The directions are updated for other pins. Bug 990845 Change-Id: I787bdd77848af59b5c33d030f0c040e7431d6c06 Signed-Off-By: Karthik Ramakrishnan Reviewed-on: http://git-master/r/105205 Reviewed-by: Simone Willett Tested-by: Simone Willett (cherry picked from commit 79fa97af045b942bb61507bbeffb0fa6d7055347) Signed-off-by: Peter Zu Change-Id: I3e0ae511b76a89fec8dd8f00304388a6dcabdf4b Reviewed-on: http://git-master/r/123490 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Simone Willett Tested-by: Simone Willett --- arch/arm/mach-tegra/board-enterprise-pinmux.c | 322 ++++++++++++++++---------- 1 file changed, 202 insertions(+), 120 deletions(-) diff --git a/arch/arm/mach-tegra/board-enterprise-pinmux.c b/arch/arm/mach-tegra/board-enterprise-pinmux.c index 4fcd7360833c..1a19dbf95f4a 100644 --- a/arch/arm/mach-tegra/board-enterprise-pinmux.c +++ b/arch/arm/mach-tegra/board-enterprise-pinmux.c @@ -156,7 +156,6 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_common[] = { /* SDMMC4 pinmux */ DEFAULT_PINMUX(SDMMC4_CLK, SDMMC4, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC4_CMD, SDMMC4, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(SDMMC4_DAT0, SDMMC4, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(SDMMC4_DAT1, SDMMC4, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(SDMMC4_DAT2, SDMMC4, PULL_UP, NORMAL, INPUT), @@ -195,47 +194,7 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_common[] = { DEFAULT_PINMUX(ULPI_DATA5, ULPI, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(ULPI_DATA6, ULPI, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(ULPI_DATA7, ULPI, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(ULPI_CLK, ULPI, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(ULPI_DIR, ULPI, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(ULPI_NXT, ULPI, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(ULPI_STP, ULPI, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP3_DIN, I2S2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(GPIO_PV2, RSVD1, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PV3, RSVD1, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_PWR1, DISPLAYA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_PWR2, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_CS0_N, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_DC0, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_DE, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D0, DISPLAYA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_D1, DISPLAYA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_D2, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D3, DISPLAYA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_D4, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D5, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D6, RSVD1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D7, RSVD1, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_D8, DISPLAYA, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(LCD_D9, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D11, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D12, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D13, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D14, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D15, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D16, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D17, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D18, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D19, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D20, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D21, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D22, RSVD1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D23, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_CS1_N, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_M1, DISPLAYA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_DC1, DISPLAYA, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(VI_D0, RSVD1, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(VI_D1, SDMMC2, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(VI_D2, SDMMC2, NORMAL, NORMAL, INPUT), @@ -246,84 +205,27 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_common[] = { DEFAULT_PINMUX(VI_D10, RSVD1, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(VI_MCLK, VI, PULL_UP, NORMAL, INPUT), - DEFAULT_PINMUX(UART2_RXD, IRDA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(UART2_TXD, IRDA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(UART2_RTS_N, UARTB, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(UART2_CTS_N, UARTB, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(UART3_TXD, UARTC, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(UART3_RXD, UARTC, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(UART3_CTS_N, UARTC, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(UART3_RTS_N, UARTC, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PU0, UARTA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PU1, UARTA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PU2, UARTA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PU3, UARTA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PU4, PWM1, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PU5, PWM2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PU6, PWM3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP4_FS, I2S3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP4_DIN, I2S3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP4_DOUT, I2S3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP4_SCLK, I2S3, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(GMI_AD8, PWM0, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(GMI_AD9, NAND, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(GMI_AD10, NAND, NORMAL, NORMAL, OUTPUT), #if IS_EXTERNAL_PWM DEFAULT_PINMUX(GMI_AD11, PWM3, NORMAL, NORMAL, OUTPUT), #endif - DEFAULT_PINMUX(GMI_A16, UARTD, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GMI_A17, UARTD, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GMI_A18, UARTD, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GMI_A19, UARTD, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(CAM_MCLK, VI_ALT2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PCC1, I2S4, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PBB0, I2S4, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PBB3, VGP3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PBB7, I2S4, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PCC2, I2S4, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(JTAG_RTCK, RTCK, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(KB_ROW0, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_ROW1, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_ROW2, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_ROW3, KBC, PULL_UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW10, KBC, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW12, KBC, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(KB_COL0, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_COL1, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_COL2, KBC, PULL_UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_COL3, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_COL4, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_COL5, KBC, PULL_UP, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PV0, RSVD, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(CLK_32K_OUT, BLINK, PULL_DOWN, TRISTATE, OUTPUT), DEFAULT_PINMUX(SYS_CLK_REQ, SYSCLK, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(OWR, OWR, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP1_FS, I2S0, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP1_DIN, I2S0, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP1_DOUT, I2S0, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP1_SCLK, I2S0, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(CLK1_REQ, DAP, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, INPUT), -#if 0 /* For HDA realtek Codec */ - DEFAULT_PINMUX(SPDIF_IN, DAP2, PULL_DOWN, NORMAL, INPUT), -#else - DEFAULT_PINMUX(SPDIF_IN, SPDIF, NORMAL, NORMAL, INPUT), -#endif -#if 0 /* For HDA realtek Codec */ - DEFAULT_PINMUX(DAP2_FS, HDA, PULL_DOWN, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_DIN, HDA, PULL_DOWN, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_DOUT, HDA, PULL_DOWN, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_SCLK, HDA, PULL_DOWN, NORMAL, INPUT), -#else - DEFAULT_PINMUX(DAP2_FS, I2S1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_DIN, I2S1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_DOUT, I2S1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_SCLK, I2S1, NORMAL, NORMAL, INPUT), -#endif DEFAULT_PINMUX(SPI2_CS1_N, SPI2, PULL_UP, NORMAL, INPUT), - DEFAULT_PINMUX(SPI1_MOSI, SPI1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SPI1_SCK, SPI1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SPI1_MISO, SPI1, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(PEX_L0_PRSNT_N, PCIE, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(PEX_L0_RST_N, PCIE, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(PEX_L0_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), @@ -336,25 +238,8 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_common[] = { DEFAULT_PINMUX(PEX_L2_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), CEC_PINMUX(HDMI_CEC, CEC, NORMAL, TRISTATE, OUTPUT, DEFAULT, DISABLE), DEFAULT_PINMUX(HDMI_INT, RSVD0, NORMAL, TRISTATE, INPUT), - - /* Gpios */ - /* SDMMC1 CD gpio */ - DEFAULT_PINMUX(GMI_IORDY, RSVD1, PULL_UP, NORMAL, INPUT), - /* SDMMC1 WP gpio */ DEFAULT_PINMUX(VI_D11, RSVD1, PULL_UP, NORMAL, INPUT), - - /* Touch panel GPIO */ - /* Touch IRQ */ - DEFAULT_PINMUX(GMI_AD12, NAND, NORMAL, NORMAL, INPUT), - - /* Touch RESET */ - DEFAULT_PINMUX(GMI_AD14, NAND, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GMI_AD15, NAND, PULL_UP, TRISTATE, INPUT), - - /* Power rails GPIO */ - DEFAULT_PINMUX(KB_ROW8, KBC, PULL_UP, NORMAL, INPUT), - VI_PINMUX(VI_D6, VI, NORMAL, NORMAL, OUTPUT, DISABLE, DISABLE), VI_PINMUX(VI_D8, SDMMC2, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), VI_PINMUX(VI_D9, SDMMC2, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), @@ -366,6 +251,97 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_common[] = { static __initdata struct tegra_pingroup_config enterprise_pinmux_a03[] = { DEFAULT_PINMUX(LCD_PWR0, DISPLAYA, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(LCD_D10, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(SDMMC4_CMD, SDMMC4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_CLK, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DIR, ULPI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(ULPI_NXT, ULPI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(ULPI_STP, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DIN, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV3, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PWR1, DISPLAYA, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PWR2, DISPLAYA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(LCD_CS0_N, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_DC0, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_DE, DISPLAYA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(LCD_D0, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D1, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D2, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D3, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D4, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D5, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D6, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D7, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D8, DISPLAYA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(LCD_D9, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D11, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D12, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D13, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D14, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D15, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D16, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D17, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D18, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D19, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D20, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D21, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D22, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D23, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_CS1_N, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_M1, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_DC1, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(UART2_RXD, IRDA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(UART2_TXD, IRDA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART2_RTS_N, UARTB, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART2_CTS_N, UARTB, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(UART3_TXD, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART3_RXD, UARTC, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(UART3_CTS_N, UARTC, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(UART3_RTS_N, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU0, UARTA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU1, UARTA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GPIO_PU2, UARTA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GPIO_PU3, UARTA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU4, PWM1, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PU5, PWM2, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GPIO_PU6, PWM3, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(DAP4_FS, I2S3, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP4_DIN, I2S3, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(DAP4_DOUT, I2S3, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP4_SCLK, I2S3, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_A16, UARTD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_A17, UARTD, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GMI_A18, UARTD, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GMI_A19, UARTD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(CAM_MCLK, VI_ALT2, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PCC1, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB0, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB3, VGP3, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB7, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PCC2, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW10, KBC, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(KB_ROW12, KBC, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(KB_COL3, KBC, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PV0, RSVD, PULL_UP, TRISTATE, INPUT), + DEFAULT_PINMUX(DAP1_FS, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DIN, I2S0, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(DAP1_DOUT, I2S0, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP1_SCLK, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(SPDIF_IN, SPDIF, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(DAP2_FS, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DIN, I2S1, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(DAP2_DOUT, I2S1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP2_SCLK, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPI1_MOSI, SPI1, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI1_SCK, SPI1, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI1_MISO, SPI1, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_IORDY, RSVD1, PULL_UP, TRISTATE, INPUT), + DEFAULT_PINMUX(GMI_AD12, NAND, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GMI_AD14, NAND, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(KB_ROW8, KBC, PULL_UP, TRISTATE, INPUT), }; static __initdata struct tegra_pingroup_config enterprise_unused_pinmux_common[] = { @@ -426,9 +402,100 @@ static __initdata struct tegra_pingroup_config enterprise_unused_pinmux_common[] DEFAULT_PINMUX(SPI2_MISO, SPI2, PULL_DOWN, TRISTATE, OUTPUT), }; -static __initdata struct tegra_pingroup_config enterprise_unused_pinmux_a02[] = { - DEFAULT_PINMUX(LCD_D10, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), - DEFAULT_PINMUX(LCD_PWR0, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), +static __initdata struct tegra_pingroup_config enterprise_pinmux_a02[] = { + DEFAULT_PINMUX(LCD_D10, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PWR0, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SDMMC4_CMD, SDMMC4, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_CLK, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DIR, ULPI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(ULPI_NXT, ULPI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(ULPI_STP, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DIN, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV3, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_PWR1, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_PWR2, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_CS0_N, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_DC0, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_DE, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D0, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D1, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D2, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D3, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D4, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D5, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D6, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D7, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D8, DISPLAYA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(LCD_D9, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D11, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D12, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D13, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D14, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D15, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D16, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D17, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D18, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D19, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D20, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D21, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D22, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D23, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_CS1_N, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_M1, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_DC1, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART2_RXD, IRDA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART2_TXD, IRDA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART2_RTS_N, UARTB, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART2_CTS_N, UARTB, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_TXD, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART3_RXD, UARTC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_CTS_N, UARTC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_RTS_N, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU0, UARTA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU1, UARTA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PU2, UARTA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PU3, UARTA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU4, PWM1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU5, PWM2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PU6, PWM3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_FS, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DIN, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DOUT, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_SCLK, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A16, UARTD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_A17, UARTD, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A18, UARTD, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A19, UARTD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(CAM_MCLK, VI_ALT2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PCC1, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB0, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB3, VGP3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB7, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PCC2, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW10, KBC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW12, KBC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL3, KBC, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV0, RSVD, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_FS, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DIN, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DOUT, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_SCLK, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPDIF_IN, SPDIF, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_FS, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DIN, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DOUT, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_SCLK, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPI1_MOSI, SPI1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPI1_SCK, SPI1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPI1_MISO, SPI1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_IORDY, RSVD1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD12, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD14, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW8, KBC, PULL_UP, NORMAL, INPUT), }; static struct tegra_gpio_table gpio_table[] = { @@ -515,6 +582,19 @@ static __initdata struct pin_info_low_power_mode enterprise_unused_gpio_pins_a02 PIN_GPIO_LPM("LCD_PWR0", TEGRA_GPIO_PB2, 0, 0), }; +static __initdata struct pin_info_low_power_mode enterprise_gpio_pins_a03[] = { + PIN_GPIO_LPM("GPIO_PV3", TEGRA_GPIO_PV3, 0, 0), + PIN_GPIO_LPM("LCD_DC0", TEGRA_GPIO_PN6, 0, 0), + PIN_GPIO_LPM("LCD_D5", TEGRA_GPIO_PE5, 0, 0), + PIN_GPIO_LPM("LCD_D20", TEGRA_GPIO_PM4, 0, 0), + PIN_GPIO_LPM("LCD_DC1", TEGRA_GPIO_PD2, 0, 0), + PIN_GPIO_LPM("GPIO_PU4", TEGRA_GPIO_PU4, 0, 0), + PIN_GPIO_LPM("KB_COL3", TEGRA_GPIO_PQ3, 0, 0), + PIN_GPIO_LPM("SPI1_MOSI", TEGRA_GPIO_PX4, 0, 0), + PIN_GPIO_LPM("SPI1_MISO", TEGRA_GPIO_PX7, 0, 0), + PIN_GPIO_LPM("SPI1_SCK", TEGRA_GPIO_PX5, 0, 0), +}; + static void enterprise_set_unused_pin_gpio(struct pin_info_low_power_mode *lpm_pin_info, int list_count) { @@ -564,13 +644,15 @@ int __init enterprise_pinmux_init(void) ARRAY_SIZE(enterprise_unused_gpio_pins_common)); if (board_info.fab < BOARD_FAB_A03) { - tegra_pinmux_config_table(enterprise_unused_pinmux_a02, - ARRAY_SIZE(enterprise_unused_pinmux_a02)); + tegra_pinmux_config_table(enterprise_pinmux_a02, + ARRAY_SIZE(enterprise_pinmux_a02)); enterprise_set_unused_pin_gpio(enterprise_unused_gpio_pins_a02, ARRAY_SIZE(enterprise_unused_gpio_pins_a02)); } else { tegra_pinmux_config_table(enterprise_pinmux_a03, ARRAY_SIZE(enterprise_pinmux_a03)); + enterprise_set_unused_pin_gpio(enterprise_gpio_pins_a03, + ARRAY_SIZE(enterprise_gpio_pins_a03)); } return 0; -- cgit v1.2.3 From e3050ba3341010c5a237ac59807d2220f407ec1d Mon Sep 17 00:00:00 2001 From: Ilan Aelion Date: Fri, 10 Aug 2012 13:53:10 -0600 Subject: video: tegra: dc: disuse notifier Due to issues with rcu notifiers on secureos, modifying dc flip notifications to use a simple callback instead. Bug 1028850 Change-Id: Iebf2a6d64d7316e3df2b88444201f9f9a29698c5 Signed-off-by: Ilan Aelion (cherry picked from commit 62c5a94c283de070d8a8d9ace60f944100216afc) Reviewed-on: http://git-master/r/#change,123103 Reviewed-on: http://git-master/r/123789 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Pradeep Thiruchelvam Tested-by: Varun Colbert Tested-by: Sang-Hun Lee --- arch/arm/mach-tegra/include/mach/dc.h | 5 ++-- drivers/misc/tegra-throughput.c | 36 ++++++++------------------- drivers/video/tegra/dc/ext/dev.c | 46 ++++++++++++++++++++++------------- 3 files changed, 41 insertions(+), 46 deletions(-) diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h index 47210c1cd87b..b60a913ff083 100644 --- a/arch/arm/mach-tegra/include/mach/dc.h +++ b/arch/arm/mach-tegra/include/mach/dc.h @@ -25,7 +25,6 @@ #include #include #include -#include #define TEGRA_MAX_DC 2 #define DC_N_WINDOWS 3 @@ -585,8 +584,8 @@ struct tegra_dc_edid { struct tegra_dc_edid *tegra_dc_get_edid(struct tegra_dc *dc); void tegra_dc_put_edid(struct tegra_dc_edid *edid); -int tegra_dc_register_flip_notifier(struct notifier_block *nb); -int tegra_dc_unregister_flip_notifier(struct notifier_block *nb); +int tegra_dc_set_flip_callback(void (*callback)(void)); +int tegra_dc_unset_flip_callback(void); int tegra_dc_get_panel_sync_rate(void); #endif diff --git a/drivers/misc/tegra-throughput.c b/drivers/misc/tegra-throughput.c index 26573d8afc1a..366b0ecc10e6 100644 --- a/drivers/misc/tegra-throughput.c +++ b/drivers/misc/tegra-throughput.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -45,12 +44,10 @@ static void set_throughput_hint(struct work_struct *work) nvhost_scale3d_set_throughput_hint(throughput_hint); } -static int throughput_flip_notifier(struct notifier_block *nb, - unsigned long val, - void *data) +static int throughput_flip_callback(void) { - /* only register flips when a single display is active */ - if (val != 1 || multiple_app_disable) + /* only register flips when a single app is active */ + if (multiple_app_disable) return NOTIFY_DONE; else { long timediff; @@ -65,7 +62,7 @@ static int throughput_flip_notifier(struct notifier_block *nb, last_frame_time = (unsigned short) timediff; if (last_frame_time == 0) { - pr_warn("%s: notifications %lld nsec apart\n", + pr_warn("%s: flips %lld nsec apart\n", __func__, now.tv64 - last_flip.tv64); return NOTIFY_DONE; } @@ -82,10 +79,6 @@ static int throughput_flip_notifier(struct notifier_block *nb, return NOTIFY_OK; } -static struct notifier_block throughput_flip_nb = { - .notifier_call = throughput_flip_notifier, -}; - static int sync_rate; static int throughput_active_app_count; @@ -104,17 +97,15 @@ static void reset_target_frame_time(void) __func__, sync_rate, target_frame_time); } -static int notifier_initialized; +static int callback_initialized; static int throughput_open(struct inode *inode, struct file *file) { - int need_init = 0; - spin_lock(&lock); - if (!notifier_initialized) { - notifier_initialized = 1; - need_init = 1; + if (!callback_initialized) { + callback_initialized = 1; + tegra_dc_set_flip_callback(throughput_flip_callback); } throughput_active_app_count++; @@ -123,8 +114,6 @@ static int throughput_open(struct inode *inode, struct file *file) spin_unlock(&lock); - if (need_init) - tegra_dc_register_flip_notifier(&throughput_flip_nb); pr_debug("throughput_open node %p file %p\n", inode, file); @@ -133,23 +122,18 @@ static int throughput_open(struct inode *inode, struct file *file) static int throughput_release(struct inode *inode, struct file *file) { - int need_deinit = 0; - spin_lock(&lock); throughput_active_app_count--; if (throughput_active_app_count == 0) { reset_target_frame_time(); multiple_app_disable = 0; - notifier_initialized = 0; - need_deinit = 1; + callback_initialized = 0; + tegra_dc_unset_flip_callback(); } spin_unlock(&lock); - if (need_deinit) - tegra_dc_unregister_flip_notifier(&throughput_flip_nb); - pr_debug("throughput_release node %p file %p\n", inode, file); return 0; diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c index 92e42ce32ac2..8ec015cbde9b 100644 --- a/drivers/video/tegra/dc/ext/dev.c +++ b/drivers/video/tegra/dc/ext/dev.c @@ -274,31 +274,40 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext, return 0; } -static struct srcu_notifier_head tegra_dc_flip_notifier_list; -static bool init_tegra_dc_flip_notifier_list_called; -static int __init init_tegra_dc_flip_notifier_list(void) +static void (*flip_callback)(void); +static spinlock_t flip_callback_lock; +static bool init_tegra_dc_flip_callback_called; + +static int __init init_tegra_dc_flip_callback(void) { - srcu_init_notifier_head(&tegra_dc_flip_notifier_list); - init_tegra_dc_flip_notifier_list_called = true; + spin_lock_init(&flip_callback_lock); + init_tegra_dc_flip_callback_called = true; return 0; } -pure_initcall(init_tegra_dc_flip_notifier_list); +pure_initcall(init_tegra_dc_flip_callback); -int tegra_dc_register_flip_notifier(struct notifier_block *nb) +int tegra_dc_set_flip_callback(void (*callback)(void)) { - WARN_ON(!init_tegra_dc_flip_notifier_list_called); + WARN_ON(!init_tegra_dc_flip_callback_called); + + spin_lock(&flip_callback_lock); + flip_callback = callback; + spin_unlock(&flip_callback_lock); - return srcu_notifier_chain_register( - &tegra_dc_flip_notifier_list, nb); + return 0; } -EXPORT_SYMBOL(tegra_dc_register_flip_notifier); +EXPORT_SYMBOL(tegra_dc_set_flip_callback); -int tegra_dc_unregister_flip_notifier(struct notifier_block *nb) +int tegra_dc_unset_flip_callback() { - return srcu_notifier_chain_unregister(&tegra_dc_flip_notifier_list, nb); + spin_lock(&flip_callback_lock); + flip_callback = NULL; + spin_unlock(&flip_callback_lock); + + return 0; } -EXPORT_SYMBOL(tegra_dc_unregister_flip_notifier); +EXPORT_SYMBOL(tegra_dc_unset_flip_callback); static void tegra_dc_ext_flip_worker(struct work_struct *work) { @@ -353,9 +362,12 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work) tegra_dc_update_windows(wins, nr_win); /* TODO: implement swapinterval here */ tegra_dc_sync_windows(wins, nr_win); - if (!tegra_dc_has_multiple_dc()) - srcu_notifier_call_chain(&tegra_dc_flip_notifier_list, - 1UL, NULL); + if (!tegra_dc_has_multiple_dc()) { + spin_lock(&flip_callback_lock); + if (flip_callback) + flip_callback(); + spin_unlock(&flip_callback_lock); + } } for (i = 0; i < DC_N_WINDOWS; i++) { -- cgit v1.2.3 From e712a1c6b380f2588adf7f1ee525430e92a08fee Mon Sep 17 00:00:00 2001 From: Kerwin Wan Date: Tue, 14 Aug 2012 17:31:11 +0800 Subject: power: max17048: update charge status when resume bug 1033234 original change is http://git-master/r/123301 Change-Id: I8722d3657bb61493bc5b58de584904fdf961e580 Signed-off-by: Kerwin Wan Reviewed-on: http://git-master/r/123917 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Varun Wadekar --- drivers/power/max17048_battery.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/power/max17048_battery.c b/drivers/power/max17048_battery.c index 770d5bc64c0b..ba3d6440ab3d 100644 --- a/drivers/power/max17048_battery.c +++ b/drivers/power/max17048_battery.c @@ -221,10 +221,11 @@ static void max17048_work(struct work_struct *work) if (chip->vcell != chip->lasttime_vcell || chip->soc != chip->lasttime_soc || - chip->status != chip->lasttime_status) { + chip->status != chip->lasttime_status) { chip->lasttime_vcell = chip->vcell; chip->lasttime_soc = chip->soc; + chip->lasttime_status = chip->status; power_supply_changed(&chip->battery); } @@ -239,14 +240,13 @@ static void max17048_battery_status(enum charging_states status, chip->ac_online = 0; chip->usb_online = 0; - if (chrg_type == AC) - chip->ac_online = 1; - else if (chrg_type == USB) - chip->usb_online = 1; - - if (status == progress) + if (status == progress) { chip->status = POWER_SUPPLY_STATUS_CHARGING; - else + if (chrg_type == AC) + chip->ac_online = 1; + else if (chrg_type == USB) + chip->usb_online = 1; + } else chip->status = POWER_SUPPLY_STATUS_DISCHARGING; @@ -592,6 +592,8 @@ static int max17048_resume(struct i2c_client *client) return ret; } + update_charger_status(); + schedule_work(&chip->work); return 0; } -- cgit v1.2.3 From 6cad35db0d5c1f34040eae5a716ec357cdd48451 Mon Sep 17 00:00:00 2001 From: Narayan Reddy Date: Fri, 27 Jul 2012 15:27:53 +0530 Subject: net: wireless: bcmdhd: Update to 5.90.195.75 Bug 1023045 Bug 1026444 Reviewed-on: http://git-master/r/117637 (cherry picked from commit 57716f1d1f8381ff50874cb81c326e203909b4f3) Signed-off-by: Narayan Reddy Change-Id: I9da8fd7775cafae9284380723c81cb2bbfe61006 Reviewed-on: http://git-master/r/123986 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Rakesh Goyal GVS: Gerrit_Virtual_Submit Reviewed-by: Pradeep Thiruchelvam --- drivers/net/wireless/bcmdhd/Makefile | 8 +- drivers/net/wireless/bcmdhd/dhd.h | 6 +- drivers/net/wireless/bcmdhd/dhd_common.c | 127 ++++- drivers/net/wireless/bcmdhd/dhd_linux.c | 57 +- drivers/net/wireless/bcmdhd/include/bcmdevs.h | 3 +- drivers/net/wireless/bcmdhd/include/epivers.h | 9 +- drivers/net/wireless/bcmdhd/include/hndpmu.h | 5 +- drivers/net/wireless/bcmdhd/include/sbchipc.h | 18 +- drivers/net/wireless/bcmdhd/include/siutils.h | 4 +- drivers/net/wireless/bcmdhd/include/wlioctl.h | 10 +- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 780 +++++++++++++++++++++----- drivers/net/wireless/bcmdhd/wl_cfg80211.h | 7 + drivers/net/wireless/bcmdhd/wl_cfgp2p.c | 48 +- drivers/net/wireless/bcmdhd/wl_cfgp2p.h | 11 +- drivers/net/wireless/bcmdhd/wl_iw.c | 1 + 15 files changed, 902 insertions(+), 192 deletions(-) diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 2851388cf194..50fac43948e2 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -8,9 +8,15 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ -DNEW_COMPAT_WIRELESS -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT \ -DEMBEDDED_PLATFORM \ - -DSET_RANDOM_MAC_SOFTAP -DWL_CFG80211_STA_EVENT \ -Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include +# Only for JB (disable on ICS) +DHDCFLAGS += -DSET_RANDOM_MAC_SOFTAP -DWL_CFG80211_STA_EVENT + +# for WFD IE support +DHDCFLAGS += -DWLWFDIE + + ifeq ($(CONFIG_BCMDHD_WIFI_CONTROL_FUNC),y) DHDCFLAGS += -DCONFIG_WIFI_CONTROL_FUNC else diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 5ff5c218ddcf..871c2bfb51d2 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd.h 328934 2012-04-23 05:15:42Z $ + * $Id: dhd.h 333052 2012-05-12 02:09:28Z $ */ /**************** @@ -437,10 +437,14 @@ extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled); extern int dhd_pno_clean(dhd_pub_t *dhd); extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, int pno_repeat, int pno_freq_expo_max); +extern int dhd_pno_set_ex(dhd_pub_t *dhd, wl_pfn_t* ssidnet, int nssid, + ushort pno_interval, int pno_repeat, int pno_expo_max, int pno_lost_time); extern int dhd_pno_get_status(dhd_pub_t *dhd); extern int dhd_dev_pno_reset(struct net_device *dev); extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, int pno_repeat, int pno_freq_expo_max); +extern int dhd_dev_pno_set_ex(struct net_device *dev, wl_pfn_t* ssidnet, int nssid, + ushort pno_interval, int pno_repeat, int pno_expo_max, int pno_lost_time); extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled); extern int dhd_dev_get_pno_status(struct net_device *dev); #endif /* PNO_SUPPORT */ diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index d9810ace1cb4..3ccc55d87d4b 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_common.c 329682 2012-04-26 09:20:38Z $ + * $Id: dhd_common.c 331276 2012-05-04 08:05:57Z $ */ #include #include @@ -1890,12 +1890,13 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) return ret; } - if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) - return (ret); memset(iovbuf, 0, sizeof(iovbuf)); #ifndef WL_SCHED_SCAN + if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) + return (ret); + if ((pfn_enabled) && (dhd_is_associated(dhd, NULL, NULL) == TRUE)) { DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__)); return ret; @@ -1939,9 +1940,10 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, err = -1; return err; } - +#ifndef WL_SCHED_SCAN if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) return (err); +#endif /* !WL_SCHED_SCAN */ /* Check for broadcast ssid */ for (k = 0; k < nssid; k++) { @@ -2034,6 +2036,123 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, return err; } +int +dhd_pno_set_ex(dhd_pub_t *dhd, wl_pfn_t* ssidnet, int nssid, ushort pno_interval, + int pno_repeat, int pno_expo_max, int pno_lost_time) +{ + int err = -1; + char iovbuf[128]; + int k, i; + wl_pfn_param_t pfn_param; + wl_pfn_t pfn_element; + uint len = 0; + + DHD_TRACE(("%s nssid=%d pno_interval=%d\n", __FUNCTION__, nssid, pno_interval)); + + if ((!dhd) && (!ssidnet)) { + DHD_ERROR(("%s error exit\n", __FUNCTION__)); + err = -1; + return err; + } + + if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) + return (err); + + /* Check for broadcast ssid */ + for (k = 0; k < nssid; k++) { + if (!ssidnet[k].ssid.SSID_len) { + DHD_ERROR(("%d: Broadcast SSID is ilegal for PNO setting\n", k)); + return err; + } + } +/* #define PNO_DUMP 1 */ +#ifdef PNO_DUMP + { + int j; + for (j = 0; j < nssid; j++) { + DHD_ERROR(("%d: scan for %s size =%d\n", j, + ssidnet[j].ssid.SSID, ssidnet[j].ssid.SSID_len)); + } + } +#endif /* PNO_DUMP */ + + /* clean up everything */ + if ((err = dhd_pno_clean(dhd)) < 0) { + DHD_ERROR(("%s failed error=%d\n", __FUNCTION__, err)); + return err; + } + memset(iovbuf, 0, sizeof(iovbuf)); + memset(&pfn_param, 0, sizeof(pfn_param)); + memset(&pfn_element, 0, sizeof(pfn_element)); + + /* set pfn parameters */ + pfn_param.version = htod32(PFN_VERSION); + pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT)); + + /* check and set extra pno params */ + if ((pno_repeat != 0) || (pno_expo_max != 0)) { + pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT); + pfn_param.repeat = (uchar) (pno_repeat); + pfn_param.exp = (uchar) (pno_expo_max); + } + + /* set up pno scan fr */ + if (pno_interval != 0) + pfn_param.scan_freq = htod32(pno_interval); + + if (pfn_param.scan_freq > PNO_SCAN_MAX_FW_SEC) { + DHD_ERROR(("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW_SEC)); + return err; + } + if (pfn_param.scan_freq < PNO_SCAN_MIN_FW_SEC) { + DHD_ERROR(("%s pno freq less %d sec\n", __FUNCTION__, PNO_SCAN_MIN_FW_SEC)); + return err; + } + + /* network lost time */ + pfn_param.lost_network_timeout = htod32(pno_lost_time); + + len = bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf, sizeof(iovbuf)); + if ((err = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0)) < 0) { + DHD_ERROR(("%s pfn_set failed for error=%d\n", + __FUNCTION__, err)); + return err; + } else { + DHD_TRACE(("%s pfn_set OK with PNO time=%d repeat=%d max_adjust=%d\n", + __FUNCTION__, pfn_param.scan_freq, + pfn_param.repeat, pfn_param.exp)); + } + + /* set all pfn ssid */ + for (i = 0; i < nssid; i++) { + pfn_element.flags = htod32(ssidnet[i].flags); + pfn_element.infra = htod32(ssidnet[i].infra); + pfn_element.auth = htod32(ssidnet[i].auth); + pfn_element.wpa_auth = htod32(ssidnet[i].wpa_auth); + pfn_element.wsec = htod32(ssidnet[i].wsec); + + memcpy((char *)pfn_element.ssid.SSID, ssidnet[i].ssid.SSID, ssidnet[i].ssid.SSID_len); + pfn_element.ssid.SSID_len = htod32(ssidnet[i].ssid.SSID_len); + + if ((len = + bcm_mkiovar("pfn_add", (char *)&pfn_element, + sizeof(pfn_element), iovbuf, sizeof(iovbuf))) > 0) { + if ((err = + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0)) < 0) { + DHD_ERROR(("%s pfn_add failed with ssidnet[%d] error=%d\n", + __FUNCTION__, i, err)); + return err; + } else { + DHD_TRACE(("%s pfn_add OK with ssidnet[%d]\n", __FUNCTION__, i)); + } + } else { + DHD_ERROR(("%s bcm_mkiovar failed with ssidnet[%d]\n", __FUNCTION__, i)); + } + } + + return err; +} + int dhd_pno_get_status(dhd_pub_t *dhd) { diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 6ba7df1cac32..44879e4a1170 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c 329682 2012-04-26 09:20:38Z $ + * $Id: dhd_linux.c 333885 2012-05-18 00:39:03Z $ */ #include @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -1526,9 +1525,12 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) tout_ctrl = DHD_PACKET_TIMEOUT_MS; if (event.event_type == WLC_E_BTA_HCI_EVENT) { dhd_bta_doevt(dhdp, data, event.datalen); - } else if (event.event_type == WLC_E_PFN_NET_FOUND) { + } +#ifdef PNO_SUPPORT + if (event.event_type == WLC_E_PFN_NET_FOUND) { tout_ctrl *= 2; } +#endif /* PNO_SUPPORT */ } else { tout_rx = DHD_PACKET_TIMEOUT_MS; } @@ -2603,7 +2605,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen, void *dev) } dhd_state |= DHD_ATTACH_STATE_NET_ALLOC; - SET_NETDEV_DEV(net, (struct device *)dev); /* Allocate primary dhd_info */ if (!(dhd = MALLOC(osh, sizeof(dhd_info_t)))) { DHD_ERROR(("%s: OOM - alloc dhd_info\n", __FUNCTION__)); @@ -2941,16 +2942,20 @@ dhd_concurrent_fw(dhd_pub_t *dhd) bcm_mkiovar("p2p", 0, 0, buf, sizeof(buf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0) { - DHD_TRACE(("%s: Get P2P failed (error=%d)\n", __FUNCTION__, ret)); + DHD_ERROR(("%s: Get P2P failed (error=%d)\n", __FUNCTION__, ret)); } else if (buf[0] == 1) { DHD_TRACE(("%s: P2P is supported\n", __FUNCTION__)); return 1; } } - return 0; + return ret; } #endif +/* + * dhd_preinit_ioctls makes special pre-setting in the firmware before radio turns on + * returns : 0 if all settings passed or negative value if anything failed +*/ int dhd_preinit_ioctls(dhd_pub_t *dhd) { @@ -2959,7 +2964,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ #if !defined(WL_CFG80211) uint up = 0; -#endif +#endif /* defined(WL_CFG80211) */ uint power_mode = PM_FAST; uint32 dongle_align = DHD_SDALIGN; uint32 glom = 0; @@ -3043,19 +3048,31 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* SET_RANDOM_MAC_SOFTAP */ DHD_TRACE(("Firmware = %s\n", fw_path)); + #if !defined(AP) && defined(WLP2P) /* Check if firmware with WFD support used */ +#if defined(WL_ENABLE_P2P_IF) + if ((ret = dhd_concurrent_fw(dhd)) < 0) { + DHD_ERROR(("%s error : firmware can't support p2p mode\n", __FUNCTION__)); + goto done; + } +#endif /* (WL_ENABLE_P2P_IF) */ + if ((!op_mode && strstr(fw_path, "_p2p") != NULL) #if defined(WL_ENABLE_P2P_IF) - || (op_mode == 0x04) ||(dhd_concurrent_fw(dhd)) + || (op_mode == WFD_MASK) || (dhd_concurrent_fw(dhd) == 1) #endif ) { bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { - DHD_ERROR(("%s APSTA for WFD failed ret= %d\n", __FUNCTION__, ret)); + DHD_ERROR(("%s APSTA setting failed ret= %d\n", __FUNCTION__, ret)); } else { dhd->op_mode |= WFD_MASK; +#if !defined(WL_ENABLE_P2P_IF) + /* ICS back capability : disable any packet filtering for p2p only mode */ + dhd_pkt_filter_enable = FALSE; +#endif /*!defined(WL_ENABLE_P2P_IF) */ } } #endif @@ -3100,16 +3117,20 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if defined(ARP_OFFLOAD_SUPPORT) arpoe = 0; #endif /* (ARP_OFFLOAD_SUPPORT) */ + /* disable any filtering for SoftAP mode */ dhd_pkt_filter_enable = FALSE; } } #endif +#if !defined(WL_ENABLE_P2P_IF) + /* ICS mode setting for sta */ if ((dhd->op_mode != WFD_MASK) && (dhd->op_mode != HOSTAPD_MASK)) { /* STA only operation mode */ dhd->op_mode |= STA_MASK; dhd_pkt_filter_enable = TRUE; } +#endif /* !defined(WL_ENABLE_P2P_IF) */ DHD_ERROR(("Firmware up: fw_path=%s op_mode=%d, " "Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", @@ -3262,6 +3283,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) dhd->pktfilter[1] = NULL; dhd->pktfilter[2] = NULL; dhd->pktfilter[3] = NULL; + /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */ dhd->pktfilter[4] = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB"; #if defined(SOFTAP) if (ap_fw_loaded) { @@ -4448,6 +4470,17 @@ dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr, pno_repeat, pno_freq_expo_max)); } +/* Linux wrapper to call common dhd_pno_set_ex */ +int +dhd_dev_pno_set_ex(struct net_device *dev, wl_pfn_t* ssidnet, int nssid, + ushort pno_interval, int pno_repeat, int pno_expo_max, int pno_lost_time) +{ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + + return (dhd_pno_set_ex(&dhd->pub, ssidnet, nssid, + pno_interval, pno_repeat, pno_expo_max, pno_lost_time)); +} + /* Linux wrapper to get pno status */ int dhd_dev_get_pno_status(struct net_device *dev) @@ -4466,9 +4499,9 @@ static void dhd_hang_process(struct work_struct *work) struct net_device *dev; dhd = (dhd_info_t *)container_of(work, dhd_info_t, work_hang); - dev = dhd->iflist[0]->net; + dev = dhd->iflist[0]->net; - if (dev) { + if (dev) { rtnl_lock(); dev_close(dev); rtnl_unlock(); @@ -4478,7 +4511,7 @@ static void dhd_hang_process(struct work_struct *work) #if defined(WL_CFG80211) wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); #endif - } + } } int net_os_send_hang_message(struct net_device *dev) diff --git a/drivers/net/wireless/bcmdhd/include/bcmdevs.h b/drivers/net/wireless/bcmdhd/include/bcmdevs.h index 287f1c65fc9a..4d2f5763a3d9 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmdevs.h +++ b/drivers/net/wireless/bcmdhd/include/bcmdevs.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmdevs.h 295140 2011-11-09 17:22:01Z $ + * $Id: bcmdevs.h 332966 2012-05-11 22:40:21Z $ */ @@ -373,6 +373,7 @@ #define BFL2_EXTLNA_TX 0x08000000 #define BFL2_4313_RADIOREG 0x10000000 +#define BFL2_SECI_LOPWR_DIS 0x20000000 diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index 3bff73e2a6bc..5df25c16b7d9 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -23,6 +23,7 @@ * */ + #ifndef _epivers_h_ #define _epivers_h_ @@ -32,17 +33,17 @@ #define EPI_RC_NUMBER 195 -#define EPI_INCREMENTAL_NUMBER 61 +#define EPI_INCREMENTAL_NUMBER 75 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 195, 61 +#define EPI_VERSION 5, 90, 195, 75 -#define EPI_VERSION_NUM 0x055ac33d +#define EPI_VERSION_NUM 0x055ac34b #define EPI_VERSION_DEV 5.90.195 -#define EPI_VERSION_STR "5.90.195.61" +#define EPI_VERSION_STR "5.90.195.75" #endif diff --git a/drivers/net/wireless/bcmdhd/include/hndpmu.h b/drivers/net/wireless/bcmdhd/include/hndpmu.h index 69a834c6b7eb..9bfc8c9275a9 100644 --- a/drivers/net/wireless/bcmdhd/include/hndpmu.h +++ b/drivers/net/wireless/bcmdhd/include/hndpmu.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndpmu.h 277737 2011-08-16 17:54:59Z $ + * $Id: hndpmu.h 335486 2012-05-28 09:47:55Z $ */ #ifndef _hndpmu_h_ @@ -31,4 +31,7 @@ extern void si_pmu_otp_power(si_t *sih, osl_t *osh, bool on); extern void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength); +extern void si_pmu_set_otp_wr_volts(si_t *sih); +extern void si_pmu_set_otp_rd_volts(si_t *sih); + #endif /* _hndpmu_h_ */ diff --git a/drivers/net/wireless/bcmdhd/include/sbchipc.h b/drivers/net/wireless/bcmdhd/include/sbchipc.h index 8f757509b95d..53bd2a1d5580 100644 --- a/drivers/net/wireless/bcmdhd/include/sbchipc.h +++ b/drivers/net/wireless/bcmdhd/include/sbchipc.h @@ -5,7 +5,7 @@ * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer, * GPIO interface, extbus, and support for serial and parallel flashes. * - * $Id: sbchipc.h 311371 2012-01-28 05:47:25Z $ + * $Id: sbchipc.h 333924 2012-05-18 04:48:52Z $ * * Copyright (C) 1999-2011, Broadcom Corporation * @@ -1441,18 +1441,18 @@ typedef volatile struct { #define CCTRL4331_EXT_LNA_G (1<<2) #define CCTRL4331_SPROM_GPIO13_15 (1<<3) #define CCTRL4331_EXTPA_EN (1<<4) -#define CCTRL4331_GPIOCLK_ON_SPROMCS <1<<5) +#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) #define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) #define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) #define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) #define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) -#define CCTRL4331_PCIE_AUXCLKEN <1<<10) -#define CCTRL4331_PCIE_PIPE_PLLDOWN <1<<11) -#define CCTRL4331_EXTPA_EN2 (1<<12) -#define CCTRL4331_EXT_LNA_A (1<<13) -#define CCTRL4331_BT_SHD0_ON_GPIO4 <1<<16) -#define CCTRL4331_BT_SHD1_ON_GPIO5 <1<<17) -#define CCTRL4331_EXTPA_ANA_EN (1<<24) +#define CCTRL4331_PCIE_AUXCLKEN (1<<10) +#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) +#define CCTRL4331_EXTPA_EN2 (1<<12) +#define CCTRL4331_EXT_LNA_A (1<<13) +#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) +#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) +#define CCTRL4331_EXTPA_ANA_EN (1<<24) #define CST4331_XTAL_FREQ 0x00000001 diff --git a/drivers/net/wireless/bcmdhd/include/siutils.h b/drivers/net/wireless/bcmdhd/include/siutils.h index 6a7b93c7b977..4e7aeb71cb02 100644 --- a/drivers/net/wireless/bcmdhd/include/siutils.h +++ b/drivers/net/wireless/bcmdhd/include/siutils.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: siutils.h 285387 2011-09-21 18:38:37Z $ + * $Id: siutils.h 335486 2012-05-28 09:47:55Z $ */ @@ -222,6 +222,8 @@ static INLINE void * si_seci_init(si_t *sih, uint8 use_seci) {return NULL;} extern bool si_is_otp_disabled(si_t *sih); extern bool si_is_otp_powered(si_t *sih); extern void si_otp_power(si_t *sih, bool on); +extern void si_set_otp_wr_volts(si_t *sih); +extern void si_set_otp_rd_volts(si_t *sih); extern bool si_is_sprom_available(si_t *sih); diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h index 91274a0c680b..5ec0c9ade197 100644 --- a/drivers/net/wireless/bcmdhd/include/wlioctl.h +++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wlioctl.h 312596 2012-02-03 02:53:30Z $ + * $Id: wlioctl.h 331292 2012-05-04 09:04:23Z $ */ @@ -1460,6 +1460,14 @@ typedef struct wl_sampledata { } wl_sampledata_t; +#define WL_CHAN_VALID_HW (1 << 0) +#define WL_CHAN_VALID_SW (1 << 1) +#define WL_CHAN_BAND_5G (1 << 2) +#define WL_CHAN_RADAR (1 << 3) +#define WL_CHAN_INACTIVE (1 << 4) +#define WL_CHAN_PASSIVE (1 << 5) +#define WL_CHAN_RESTRICTED (1 << 6) + #define WL_ERROR_VAL 0x00000001 #define WL_TRACE_VAL 0x00000002 diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index f728c14622a1..7f3e332dbfce 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -84,17 +84,15 @@ u32 wl_dbg_level = WL_DBG_ERR; * All the chnages in world regulatory domain are to be done here. */ static const struct ieee80211_regdomain brcm_regdom = { - .n_reg_rules = 5, + .n_reg_rules = 4, .alpha2 = "99", .reg_rules = { /* IEEE 802.11b/g, channels 1..11 */ - REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), + REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), /* IEEE 802.11b/g, channels 12..13. No HT40 * channel fits here. */ - REG_RULE(2467-10, 2472+10, 20, 6, 20, - NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS), + /* If any */ /* * IEEE 802.11 channel 14 - is for JP only, * we need cfg80211 to allow it (reg_flags = 0); so that @@ -231,6 +229,8 @@ static s32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); static s32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data, bool completed); +static s32 wl_ibss_join_done(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data, bool completed); static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, @@ -296,6 +296,7 @@ static void wl_free_wdev(struct wl_priv *wl); static s32 wl_inform_bss(struct wl_priv *wl); static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi); +static s32 wl_inform_ibss(struct wl_priv *wl, const u8 *bssid); static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev); static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy); @@ -335,7 +336,6 @@ static void wl_link_up(struct wl_priv *wl); static void wl_link_down(struct wl_priv *wl); static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype); static void wl_init_conf(struct wl_conf *conf); -static s32 wl_update_wiphybands(struct wl_priv *wl); /* * iscan handler @@ -704,7 +704,7 @@ static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy) *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX); if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf, - sizeof(WL_EXTRA_BUF_MAX), false))) { + WL_EXTRA_BUF_MAX, false))) { WL_ERR(("Failed to get associated bss info, use temp channel \n")); chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN); } @@ -925,6 +925,11 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) if (wl->p2p_supported) { memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN); + + /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases + */ + WL_DBG(("P2P: GO_NEG_PHASE status cleared ")); + wl_clr_p2p_status(wl, GO_NEG_PHASE); if (wl->p2p->vif_created) { if (wl_get_drv_status(wl, SCANNING, dev)) { wl_notify_escan_complete(wl, dev, true, true); @@ -1004,6 +1009,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, default: return -EINVAL; } + WL_DBG(("%s : ap (%d), infra (%d), iftype: (%d)\n", ndev->name, ap, infra, type)); if (ap) { wl_set_mode_by_netdev(wl, ndev, mode); @@ -1019,7 +1025,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, */ chspec = wl_cfg80211_get_shared_freq(wiphy); - wlif_type = ap ? WL_P2P_IF_GO : WL_P2P_IF_CLIENT; + wlif_type = WL_P2P_IF_GO; WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n", ndev->name, ap, infra, type)); wl_set_p2p_status(wl, IF_CHANGING); @@ -1043,6 +1049,14 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, WL_ERR(("Cannot change the interface for GO or SOFTAP\n")); return -EINVAL; } + } else { + infra = htod32(infra); + err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true); + if (err) { + WL_ERR(("WLC_SET_INFRA error (%d)\n", err)); + return -EAGAIN; + } + wl_set_mode_by_netdev(wl, ndev, mode); } ndev->ieee80211_ptr->iftype = type; @@ -1587,6 +1601,8 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); } + wl_clr_p2p_status(wl, GO_NEG_PHASE); + WL_DBG(("P2P: GO_NEG_PHASE status cleared \n")); p2p_scan(wl) = true; } } else { @@ -1625,10 +1641,13 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, } else { wpsie_len = 0; } - err = wl_cfgp2p_set_management_ie(wl, ndev, -1, - VNDR_IE_PRBREQ_FLAG, wpsie, wpsie_len); - if (unlikely(err)) { - goto scan_out; + if (wpsie_len > 0) { + err = wl_cfgp2p_set_management_ie(wl, + ndev, -1, VNDR_IE_PRBREQ_FLAG, + wpsie, wpsie_len); + if (unlikely(err)) { + goto scan_out; + } } } } @@ -1808,86 +1827,192 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params) { struct wl_priv *wl = wiphy_priv(wiphy); - struct cfg80211_bss *bss; - struct ieee80211_channel *chan; struct wl_join_params join_params; - struct cfg80211_ssid ssid; - s32 scan_retry = 0; + struct wlc_ssid ssid; + struct ether_addr bssid; + size_t join_params_size = 0; + s32 wsec = 0; + s32 bcnprd; s32 err = 0; - bool rollback_lock = false; WL_TRACE(("In\n")); CHECK_SYS_UP(wl); - if (params->bssid) { - WL_ERR(("Invalid bssid\n")); - return -EOPNOTSUPP; - } - bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len); - if (!bss) { - memcpy(ssid.ssid, params->ssid, params->ssid_len); - ssid.ssid_len = params->ssid_len; - do { - if (unlikely - (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) == - -EBUSY)) { - wl_delay(150); - } else { - break; - } - } while (++scan_retry < WL_SCAN_RETRY_MAX); - /* to allow scan_inform to propagate to cfg80211 plane */ - if (rtnl_is_locked()) { - rtnl_unlock(); - rollback_lock = true; - } - - /* wait 4 secons till scan done.... */ - schedule_timeout_interruptible(4 * HZ); - if (rollback_lock) - rtnl_lock(); - bss = cfg80211_get_ibss(wiphy, NULL, - params->ssid, params->ssid_len); - } - if (bss) { - wl->ibss_starter = false; - WL_DBG(("Found IBSS\n")); - } else { - wl->ibss_starter = true; - } - chan = params->channel; - if (chan) - wl->channel = ieee80211_frequency_to_channel(chan->center_freq); + /* - * Join with specific BSSID and cached SSID - * If SSID is zero join based on BSSID only + * Cancel ongoing scan to sync up with sme state machine of cfg80211. */ - memset(&join_params, 0, sizeof(join_params)); - memcpy((void *)join_params.ssid.SSID, (void *)params->ssid, - params->ssid_len); - join_params.ssid.SSID_len = htod32(params->ssid_len); + if (wl->scan_request) { + wl_notify_escan_complete(wl, dev, true, true); + } + /* Clean BSSID */ + bzero(&bssid, sizeof(bssid)); + wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID); + + if (params->ssid) + WL_INFO(("SSID: %s\n", params->ssid)); + else { + WL_ERR(("SSID: NULL, Not supported\n")); + err = -EOPNOTSUPP; + goto CleanUp; + } + if (params->bssid) - memcpy(&join_params.params.bssid, params->bssid, - ETHER_ADDR_LEN); + WL_INFO(("BSSID: %02X:%02X:%02X:%02X:%02X:%02X\n", + params->bssid[0], params->bssid[1], params->bssid[2], + params->bssid[3], params->bssid[4], params->bssid[5])); + + if (params->channel) + WL_INFO(("channel: %d\n", params->channel->center_freq)); + + if (params->channel_fixed) + WL_INFO(("fixed channel required\n")); + + if (params->ie && params->ie_len) + WL_INFO(("ie len: %d\n", params->ie_len)); + + if (params->beacon_interval) + WL_INFO(("beacon interval: %d\n", params->beacon_interval)); + + if (params->basic_rates) + WL_INFO(("basic rates: %08X\n", params->basic_rates)); + + if (params->privacy) + WL_INFO(("privacy required\n")); + + wl_set_drv_status(wl, CONNECTING, dev); + + /* Configure Privacy for starter */ + if (params->privacy) + wsec |= WEP_ENABLED; + + err = wldev_iovar_setint(dev, "wsec", wsec); + if (err) { + WL_ERR(("wsec failed (%d)\n", err)); + goto CleanUp; + } + + err = wldev_iovar_setint(dev, "auth", WL_AUTH_OPEN_SYSTEM); + if (err) { + WL_ERR(("auth failed (%d)\n", err)); + goto CleanUp; + } + + err = wldev_iovar_setint(dev, "wpa_auth", 0); + if (err) { + WL_ERR(("wpa_auth failed (%d)\n", err)); + goto CleanUp; + } + + /* Configure Beacon Interval for starter */ + if (params->beacon_interval) + bcnprd = params->beacon_interval; else - memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN); + bcnprd = 100; - err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, - sizeof(join_params), false); - if (unlikely(err)) { - WL_ERR(("Error (%d)\n", err)); - return err; + bcnprd = htod32(bcnprd); + err = wldev_ioctl(dev, WLC_SET_BCNPRD, &bcnprd, sizeof(bcnprd), true); + if (err) { + WL_ERR(("WLC_SET_BCNPRD failed (%d)\n", err)); + goto CleanUp; + } + + /* Configure required join parameter */ + memset(&join_params, 0, sizeof(struct wl_join_params)); + + /* SSID */ + memset(&ssid, 0, sizeof(struct wlc_ssid)); + ssid.SSID_len = MIN(params->ssid_len, 32); + join_params.ssid.SSID_len = htod32(ssid.SSID_len); + memcpy(ssid.SSID, params->ssid, ssid.SSID_len); + memcpy(join_params.ssid.SSID, params->ssid, ssid.SSID_len); + join_params_size = sizeof(join_params.ssid); + + wl_update_prof(wl, dev, NULL, &ssid, WL_PROF_SSID); + + /* BSSID */ + if (params->bssid) { + memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN); + join_params_size = sizeof(join_params.ssid) + + WL_ASSOC_PARAMS_FIXED_SIZE; + + wl_update_prof(wl, dev, NULL, params->bssid, WL_PROF_BSSID); + } else { + memcpy(&join_params.params.bssid, ðer_bcast, ETHER_ADDR_LEN); + } + + /* Channel */ + if (params->channel) { + u32 target_channel; + + target_channel = ieee80211_frequency_to_channel( + params->channel->center_freq); + if (params->channel_fixed) { + /* adding chanspec */ + wl_ch_to_chanspec(target_channel, + &join_params, &join_params_size); + } + + /* set channel for starter */ + target_channel = htod32(target_channel); + err = wldev_ioctl(dev, WLC_SET_CHANNEL, + &target_channel, sizeof(target_channel), true); + if (err) { + WL_ERR(("WLC_SET_CHANNEL failed (%d)\n", err)); + goto CleanUp; + } } + + wl->ibss_starter = false; + + err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true); + if (err) { + WL_ERR(("WLC_SET_SSID failed (%d)\n", err)); + goto CleanUp; + } + +CleanUp: + + if (err) + wl_clr_drv_status(wl, CONNECTING, dev); + + WL_TRACE(("Exit\n")); return err; } static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) { struct wl_priv *wl = wiphy_priv(wiphy); + scb_val_t scbval; + bool act = false; s32 err = 0; + u8 *curbssid; + + WL_TRACE(("Enter\n")); CHECK_SYS_UP(wl); - wl_link_down(wl); + act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT); + curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID); + if (act) { + /* + * Cancel ongoing scan to sync up with sme state machine of cfg80211. + */ + if (wl->scan_request) { + wl_notify_escan_complete(wl, dev, true, true); + } + wl_set_drv_status(wl, DISCONNECTING, dev); + scbval.val = DOT11_RC_DISASSOC_LEAVING; + memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN); + scbval.val = htod32(scbval.val); + err = wldev_ioctl(dev, WLC_DISASSOC, &scbval, + sizeof(scb_val_t), true); + if (unlikely(err)) { + wl_clr_drv_status(wl, DISCONNECTING, dev); + WL_ERR(("error (%d)\n", err)); + return err; + } + } + WL_TRACE(("Exit\n")); return err; } @@ -2216,8 +2341,9 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, */ WL_DBG(("ASSOC2 p2p index : %d sme->ie_len %d\n", wl_cfgp2p_find_idx(wl, dev), sme->ie_len)); - wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), - VNDR_IE_PRBREQ_FLAG, sme->ie, sme->ie_len); + wl_cfgp2p_set_management_ie(wl, dev, + wl_cfgp2p_find_idx(wl, dev), VNDR_IE_PRBREQ_FLAG, + sme->ie, sme->ie_len); wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); } @@ -3328,8 +3454,8 @@ wl_cfg80211_send_at_common_channel(struct wl_priv *wl, if (wl->afx_hdl->peer_chan != WL_INVALID) wl_cfg80211_send_pending_tx_act_frm(wl); else { - WL_ERR(("Couldn't find the peer after %d retries\n", - wl->afx_hdl->retry)); + WL_ERR(("Couldn't find the peer " MACSTR " after %d retries\n", + MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), wl->afx_hdl->retry)); } wl->afx_hdl->dev = NULL; wl->afx_hdl->bssidx = WL_INVALID; @@ -3355,7 +3481,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, wl_af_params_t *af_params; wifi_p2p_ie_t *p2p_ie; wpa_ie_fixed_t *wps_ie; +#ifdef WLWFDIE wifi_wfd_ie_t *wfd_ie; +#endif /* WLWFDIE */ scb_val_t scb_val; const struct ieee80211_mgmt *mgmt; struct wl_priv *wl = wiphy_priv(wiphy); @@ -3364,7 +3492,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, s32 bssidx = 0; u32 p2pie_len = 0; u32 wpsie_len = 0; +#ifdef WLWFDIE u32 wfdie_len = 0; +#endif /* WLWFDIE */ u32 id; u32 retry = 0; bool ack = false; @@ -3414,11 +3544,13 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, /* Total length of P2P Information Element */ p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id); } +#ifdef WLWFDIE if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)(buf + ie_offset), ie_len)) != NULL) { /* Total length of WFD Information Element */ wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id); } +#endif /* WLWFDIE */ if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)(buf + ie_offset), ie_len)) != NULL) { /* Order of Vendor IE is 1) WPS IE + @@ -3430,7 +3562,11 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, sizeof(wps_ie->tag); wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_PRBRSP_FLAG, +#ifdef WLWFDIE (u8 *)wps_ie, wpsie_len + p2pie_len + wfdie_len); +#else + (u8 *)wps_ie, wpsie_len + p2pie_len); +#endif /* WLWFDIE */ } cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); goto exit; @@ -3443,8 +3579,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, WL_DBG(("Disconnect STA : %s scb_val.val %d\n", bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf), scb_val.val)); - /* Wait for the deauth event to come, supplicant will do the delete iface immediately - * and we will have problem in sending deauth frame if we delete the bss in firmware + /* Wait for the deauth event to come, supplicant will do the + * delete iface immediately and we will have problem in sending + * deauth frame if we delete the bss in firmware */ wl_delay(400); cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); @@ -3513,6 +3650,36 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, WL_DBG(("P2P PUB action_frame->len: %d chan %d category %d subtype %d\n", action_frame->len, af_params->channel, act_frm->category, act_frm->subtype)); + if (act_frm && ((act_frm->subtype == P2P_PAF_GON_REQ) || + (act_frm->subtype == P2P_PAF_GON_RSP) || + (act_frm->subtype == P2P_PAF_GON_CONF) || + (act_frm->subtype == P2P_PAF_PROVDIS_REQ))) { + wldev_iovar_setint(dev, "mpc", 0); + } + + if (act_frm->subtype == P2P_PAF_GON_REQ) { + WL_DBG(("P2P: GO_NEG_PHASE status set \n")); + wl_set_p2p_status(wl, GO_NEG_PHASE); + } else if (act_frm->subtype == P2P_PAF_GON_CONF) { + /* If we reached till GO Neg confirmation + * reset the filter + */ + WL_DBG(("P2P: GO_NEG_PHASE status cleared \n")); + wl_clr_p2p_status(wl, GO_NEG_PHASE); + } + + if (act_frm->subtype == P2P_PAF_GON_RSP) + retry_cnt = 1; + else retry_cnt = WL_ACT_FRAME_RETRY; + + if (act_frm && act_frm->subtype == P2P_PAF_DEVDIS_REQ) { + af_params->dwell_time = WL_LONG_DWELL_TIME; + } else if (act_frm && + (act_frm->subtype == P2P_PAF_PROVDIS_REQ || + act_frm->subtype == P2P_PAF_PROVDIS_RSP || + act_frm->subtype == P2P_PAF_GON_RSP)) { + af_params->dwell_time = WL_MED_DWELL_TIME; + } } else if (wl_cfgp2p_is_p2p_action(action_frame->data, action_frame->len)) { p2p_act_frm = (wifi_p2p_action_frame_t *) (action_frame->data); WL_DBG(("P2P action_frame->len: %d chan %d category %d subtype %d\n", @@ -3523,32 +3690,13 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, WL_DBG(("Service Discovery action_frame->len: %d chan %d category %d action %d\n", action_frame->len, af_params->channel, sd_act_frm->category, sd_act_frm->action)); - + af_params->dwell_time = WL_MED_DWELL_TIME; + retry_cnt = WL_ACT_FRAME_RETRY; } wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len); /* * To make sure to send successfully action frame, we have to turn off mpc */ - - if (act_frm && ((act_frm->subtype == P2P_PAF_GON_REQ) || - (act_frm->subtype == P2P_PAF_GON_RSP) || - (act_frm->subtype == P2P_PAF_GON_CONF) || - (act_frm->subtype == P2P_PAF_PROVDIS_REQ))) { - wldev_iovar_setint(dev, "mpc", 0); - } - if (act_frm->subtype == P2P_PAF_GON_RSP) - retry_cnt = 1; - else retry_cnt = WL_ACT_FRAME_RETRY; - - if (act_frm && act_frm->subtype == P2P_PAF_DEVDIS_REQ) { - af_params->dwell_time = WL_LONG_DWELL_TIME; - } else if (act_frm && - (act_frm->subtype == P2P_PAF_PROVDIS_REQ || - act_frm->subtype == P2P_PAF_PROVDIS_RSP || - act_frm->subtype == P2P_PAF_GON_RSP)) { - af_params->dwell_time = WL_MED_DWELL_TIME; - } - if (IS_P2P_SOCIAL(af_params->channel) && (IS_P2P_PUB_ACT_REQ(act_frm, &act_frm->elts[0], action_frame->len) || IS_GAS_REQ(sd_act_frm, action_frame->len)) && @@ -3560,6 +3708,18 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, /* channel offload for action request frame */ ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params); + /* We need to retry Service discovery frames as they don't get retried immediately by supplicant*/ + if ((!ack) && (IS_GAS_REQ(sd_act_frm, action_frame->len))) { + for (retry = 1; retry < retry_cnt; retry++) { + WL_DBG(("Service Discovery action_frame retry %d len: %d chan %d category %d action %d\n", + retry, action_frame->len, af_params->channel, + sd_act_frm->category, sd_act_frm->action)); + ack = (wl_cfgp2p_tx_action_frame(wl, dev, + af_params, bssidx)) ? false : true; + if (ack) + break; + } + } } else { ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true; if (!ack) { @@ -3915,13 +4075,17 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, wpa_ie_fixed_t *wpa_ie; bcm_tlv_t *wpa2_ie; wifi_p2p_ie_t *p2p_ie; +#ifdef WLWFDIE wifi_wfd_ie_t *wfd_ie; +#endif /* WLWFDIE */ bool is_bssup = false; bool update_bss = false; bool pbc = false; u16 wpsie_len = 0; u16 p2pie_len = 0; +#ifdef WLWFDIE u32 wfdie_len = 0; +#endif /* WLWFDIE */ u8 beacon_ie[IE_MAX_LEN]; s32 ie_offset = 0; s32 bssidx = 0; @@ -3979,24 +4143,30 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, } else { WL_ERR(("No P2PIE in beacon \n")); } +#ifdef WLWFDIE /* find the WFD IEs */ if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)info->tail, info->tail_len)) != NULL) { - /* Total length of P2P Information Element */ - wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id); - if ((wpsie_len + p2pie_len + wfdie_len) < IE_MAX_LEN) { - memcpy(&beacon_ie[wpsie_len + p2pie_len], wfd_ie, wfdie_len); - } else { + /* Total length of P2P Information Element */ + wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id); + if ((wpsie_len + p2pie_len + wfdie_len) < IE_MAX_LEN) { + memcpy(&beacon_ie[wpsie_len + p2pie_len], wfd_ie, wfdie_len); + } else { WL_ERR(("Found WFD IE but there is no space, (%d)(%d)(%d)\n", - wpsie_len, p2pie_len, wfdie_len)); + wpsie_len, p2pie_len, wfdie_len)); wfdie_len = 0; } } else { WL_ERR(("No WFDIE in beacon \n")); } +#endif /* WLWFDIE */ /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, +#ifdef WLWFDIE beacon_ie, wpsie_len + p2pie_len + wfdie_len); +#else + beacon_ie, wpsie_len + p2pie_len); +#endif /* WLWFDIE */ /* find the RSN_IE */ if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len, @@ -4268,7 +4438,7 @@ exit: #ifdef WL_SCHED_SCAN #define PNO_TIME 30 #define PNO_REPEAT 4 -#define PNO_FREQ_EXPO_MAX 3 +#define PNO_FREQ_EXPO_MAX 2 int wl_cfg80211_sched_scan_start(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_sched_scan_request *request) @@ -4615,8 +4785,13 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) kfree(notif_bss_info); return err; } + else if( wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_INFO) == NULL) + { + WL_DBG(("Couldn't find P2P_SEID_DEV_INFO in probe response/beacon\n")); + kfree(notif_bss_info); + return err; + } } - if (!mgmt->u.probe_resp.timestamp) { struct timeval tv; @@ -4639,6 +4814,114 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) return err; } +static s32 wl_inform_ibss(struct wl_priv *wl, const u8 *bssid) +{ + struct net_device *ndev = wl_to_prmry_ndev(wl); + struct wiphy *wiphy = wl_to_wiphy(wl); + struct wl_bss_info *bi = NULL; + struct ieee80211_channel *notify_channel; + struct ieee80211_supported_band *band; + struct cfg80211_bss *bss; + s32 err = 0; + u16 channel; + u32 freq; + u32 wsec = 0; + u16 notify_capability; + u16 notify_interval; + u8 *notify_ie; + size_t notify_ielen; + s32 notify_signal; + + WL_TRACE(("Enter\n")); + + if (wl->scan_request) { + wl_notify_escan_complete(wl, ndev, true, true); + } + + mutex_lock(&wl->usr_sync); + + *(u32 *)wl->extra_buf = htod32(WL_EXTRA_BUF_MAX); + err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, wl->extra_buf, + WL_EXTRA_BUF_MAX, false); + if (err) { + WL_ERR(("Failed to get bss info for IBSS\n")); + err = -EIO; + goto CleanUp; + } + bi = (struct wl_bss_info *)(wl->extra_buf + 4); + + if (memcmp(bssid, &bi->BSSID, ETHER_ADDR_LEN)) { + WL_ERR(("BSSID mismatch: Inform %02x:%02x:%02x:%02x:%02x:%02x," + "%02x:%02x:%02x:%02x:%02x:%02x\n", + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5], + bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2], + bi->BSSID.octet[3], bi->BSSID.octet[4], + bi->BSSID.octet[5])); + err = -EINVAL; + goto CleanUp; + } + + err = wldev_iovar_getint(ndev, "wsec", &wsec); + if (err) { + WL_ERR(("wsec failed: %d\n", err)); + err = -EIO; + goto CleanUp; + } + + channel = bi->ctl_ch ? bi->ctl_ch : + CHSPEC_CHANNEL(dtohchanspec(bi->chanspec)); + if (channel <= CH_MAX_2G_CHANNEL) + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + else + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + +#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) + freq = ieee80211_channel_to_frequency(channel); + (void)band->band; +#else + freq = ieee80211_channel_to_frequency(channel, band->band); +#endif + notify_channel = ieee80211_get_channel(wiphy, freq); + + notify_capability = dtoh16(bi->capability); + notify_interval = dtoh16(bi->beacon_period); + notify_ie = (u8 *)bi + dtoh16(bi->ie_offset); + notify_ielen = dtoh32(bi->ie_length); + notify_signal = (int16)dtoh16(bi->RSSI) * 100; + + if (wl->p2p_supported) { + notify_capability |= DOT11_CAP_IBSS; + if (wsec) + notify_capability |= DOT11_CAP_PRIVACY; + } + + WL_DBG(("BSSID %02x:%02x:%02x:%02x:%02x:%02x", + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5])); + WL_INFO(("channel: %d(%d)\n", channel, freq)); + WL_INFO(("capability: %X\n", notify_capability)); + WL_INFO(("beacon interval: %d ms\n", notify_interval)); + WL_INFO(("signal: %d dBm\n", notify_signal)); + WL_INFO(("ie_len: %d\n", notify_ielen)); + bss = cfg80211_inform_bss(wiphy, notify_channel, bssid, 0, + notify_capability, notify_interval, + notify_ie, notify_ielen, notify_signal, GFP_KERNEL); + if (!bss) { + WL_ERR(("cfg80211_inform_bss() Failed\n")); + err = -ENOMEM; + goto CleanUp; + } + + cfg80211_put_bss(bss); + err = 0; + +CleanUp: + + mutex_unlock(&wl->usr_sync); + + WL_TRACE(("Exit\n")); + return err; +} + static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev) { u32 event = ntoh32(e->event_type); @@ -4648,12 +4931,12 @@ static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net WL_DBG(("event %d, status %d flags %x\n", event, status, flags)); if (event == WLC_E_SET_SSID) { if (status == WLC_E_STATUS_SUCCESS) { - if (!wl_is_ibssmode(wl, ndev)) - return true; + return true; } } else if (event == WLC_E_LINK) { if (flags & WLC_EVENT_MSG_LINK) - return true; + if (!wl_is_ibssmode(wl, ndev)) + return true; } WL_DBG(("wl_is_linkup false\n")); @@ -4834,7 +5117,9 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, if((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DISASSOC_IND)) { reason = ntoh32(e->reason); wl->deauth_reason = reason; - WL_ERR(("Received %s event with reason code: %d\n", (event == WLC_E_DEAUTH_IND)? "WLC_E_DEAUTH_IND":"WLC_E_DISASSOC_IND", reason)); + WL_ERR(("Received %s event with reason code: %d\n", + (event == WLC_E_DEAUTH_IND)? + "WLC_E_DEAUTH_IND":"WLC_E_DISASSOC_IND", reason)); } if (wl_is_linkup(wl, e, ndev)) { wl_link_up(wl); @@ -4843,10 +5128,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); wl->deauth_reason = 0; if (wl_is_ibssmode(wl, ndev)) { - printk("cfg80211_ibss_joined\n"); - cfg80211_ibss_joined(ndev, (s8 *)&e->addr, - GFP_KERNEL); - WL_DBG(("joined in IBSS network\n")); + wl_ibss_join_done(wl, ndev, e, data, true); + WL_DBG(("wl_ibss_join_done succeeded\n")); } else { if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) { printk("wl_bss_connect_done succeeded\n"); @@ -4856,7 +5139,6 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID)); } } - } else if (wl_is_linkdown(wl, e)) { if (wl->scan_request) { if (wl->escan_on) { @@ -4880,15 +5162,21 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, scbval.val = htod32(scbval.val); wldev_ioctl(ndev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); - WL_ERR(("link down, calling cfg80211_disconnected with deauth_reason:%d\n", wl->deauth_reason)); - cfg80211_disconnected(ndev, wl->deauth_reason , NULL, 0, GFP_KERNEL); + WL_ERR(("link down, calling cfg80211_disconnected" + " with deauth_reason:%d\n", wl->deauth_reason)); + if (!wl_is_ibssmode(wl, ndev)) + cfg80211_disconnected(ndev, wl->deauth_reason, + NULL, 0, GFP_KERNEL); wl_link_down(wl); wl_init_prof(wl, ndev); } } else if (wl_get_drv_status(wl, CONNECTING, ndev)) { printk("link down, during connecting\n"); - wl_bss_connect_done(wl, ndev, e, data, false); + if (wl_is_ibssmode(wl, ndev)) + wl_ibss_join_done(wl, ndev, e, data, false); + else + wl_bss_connect_done(wl, ndev, e, data, false); } wl_clr_drv_status(wl, DISCONNECTING, ndev); @@ -5183,6 +5471,35 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, return err; } +static s32 +wl_ibss_join_done(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data, bool completed) +{ + s32 err = 0; + + WL_TRACE(("Enter\n")); + + if (wl->scan_request) { + wl_notify_escan_complete(wl, ndev, true, true); + } + if (wl_get_drv_status(wl, CONNECTING, ndev)) { + wl_clr_drv_status(wl, CONNECTING, ndev); + if (completed) { + err = wl_inform_ibss(wl, (u8 *)&e->addr); + if (err) { + WL_ERR(("wl_inform_ibss() failed: %d\n", err)); + } + wl_set_drv_status(wl, CONNECTED, ndev); + + cfg80211_ibss_joined(ndev, (u8 *)&e->addr, GFP_KERNEL); + WL_DBG(("cfg80211_ibss_joined() called with valid BSSID\n")); + } + } + + WL_TRACE(("Exit\n")); + return err; +} + static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data) @@ -5365,6 +5682,13 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, WL_ERR(("No valid band")); return -EINVAL; } + + if ((event == WLC_E_P2P_PROBREQ_MSG) && + wl->p2p && wl_get_p2p_status(wl, GO_NEG_PHASE)) { + WL_DBG(("Filtering P2P probe_req while being in GO-Neg state\n")); + goto exit; + } + #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) freq = ieee80211_channel_to_frequency(channel); #else @@ -5409,6 +5733,11 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) { wldev_iovar_setint(dev, "mpc", 1); } + + if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) { + WL_DBG(("P2P: GO_NEG_PHASE status cleared \n")); + wl_clr_p2p_status(wl, GO_NEG_PHASE); + } } else { mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1); } @@ -6044,7 +6373,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, wl_scan_results_t *list; u32 bi_length; u32 i; - + u8 *p2p_dev_addr = NULL; WL_DBG((" enter event type : %d, status : %d \n", ntoh32(e->event_type), ntoh32(e->status))); /* P2P SCAN is coming from primary interface */ @@ -6086,16 +6415,18 @@ static s32 wl_escan_handler(struct wl_priv *wl, if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) { if (dtoh16(bi->capability) & DOT11_CAP_IBSS) { - WL_ERR(("Ignoring IBSS result\n")); + WL_DBG(("Ignoring IBSS result\n")); goto exit; } } if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { - if (!memcmp(bi->BSSID.octet, + p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length); + if (p2p_dev_addr && !memcmp(p2p_dev_addr, wl->afx_hdl->pending_tx_dst_addr.octet, ETHER_ADDR_LEN)) { s32 channel = CHSPEC_CHANNEL(dtohchanspec(bi->chanspec)); - WL_DBG(("ACTION FRAME SCAN : Peer found, channel : %d\n", channel)); + WL_DBG(("ACTION FRAME SCAN : Peer " MACSTR " found, channel : %d\n", + MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), channel)); wl_clr_p2p_status(wl, SCANNING); wl->afx_hdl->peer_chan = channel; complete(&wl->act_frm_scan); @@ -6721,20 +7052,148 @@ eventmsg_out: } +static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap) +{ + struct net_device *dev = wl_to_prmry_ndev(wl); + struct ieee80211_channel *band_chan_arr = NULL; + wl_uint32_list_t *list; + u32 i, j, index, n_2g, n_5g, band, channel, array_size; + u32 *n_cnt = NULL; + chanspec_t c = 0; + s32 err = BCME_OK; + bool update; + bool ht40_allowed; + u8 *pbuf = NULL; + +#define LOCAL_BUF_LEN 1024 + pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL); + if (pbuf == NULL) { + WL_ERR(("failed to allocate local buf\n")); + return -ENOMEM; + } + + list = (wl_uint32_list_t *)(void *)pbuf; + list->count = htod32(WL_NUMCHANSPECS); + + err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL, + 0, pbuf, LOCAL_BUF_LEN, 0, &wl->ioctl_buf_sync); + if (err != 0) { + WL_ERR(("get chanspecs failed with %d\n", err)); + kfree(pbuf); + return err; + } +#undef LOCAL_BUF_LEN + + band = array_size = n_2g = n_5g = 0; + for (i = 0; i < dtoh32(list->count); i++) { + index = 0; + update = FALSE; + ht40_allowed = FALSE; + c = (chanspec_t)dtoh32(list->element[i]); + channel = CHSPEC_CHANNEL(c); + if (CHSPEC_IS40(c)) { + if (CHSPEC_SB_UPPER(c)) + channel += CH_10MHZ_APART; + else + channel -= CH_10MHZ_APART; + } + + if (CHSPEC_IS2G(c) && channel <= CH_MAX_2G_CHANNEL) { + band_chan_arr = __wl_2ghz_channels; + array_size = ARRAYSIZE(__wl_2ghz_channels); + n_cnt = &n_2g; + band = IEEE80211_BAND_2GHZ; + ht40_allowed = (bw_cap == WLC_N_BW_40ALL) ? TRUE : FALSE; + } else if (CHSPEC_IS5G(c) && channel > CH_MAX_2G_CHANNEL) { + band_chan_arr = __wl_5ghz_a_channels; + array_size = ARRAYSIZE(__wl_5ghz_a_channels); + n_cnt = &n_5g; + band = IEEE80211_BAND_5GHZ; + ht40_allowed = (bw_cap == WLC_N_BW_20ALL) ? FALSE : TRUE; + } + + for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { + if (band_chan_arr[j].hw_value == channel) { + update = TRUE; + break; + } + } + + if (update) + index = j; + else + index = *n_cnt; + + if (index < array_size) { +#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) + band_chan_arr[index].center_freq = + ieee80211_channel_to_frequency(channel); +#else + band_chan_arr[index].center_freq = + ieee80211_channel_to_frequency(channel, band); +#endif + band_chan_arr[index].hw_value = channel; + + if (CHSPEC_IS40(c) && ht40_allowed) { + u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40; + if (CHSPEC_SB_UPPER(c)) { + if (ht40_flag == IEEE80211_CHAN_NO_HT40) + band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40; + band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS; + } else { + band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40; + if (ht40_flag == IEEE80211_CHAN_NO_HT40) + band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40MINUS; + } + } else { + band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40; + if (band == IEEE80211_BAND_2GHZ) + channel |= WL_CHANSPEC_BAND_2G; + else + channel |= WL_CHANSPEC_BAND_5G; + err = wldev_iovar_getint(dev, "per_chan_info", &channel); + if (!err) { + if (channel & WL_CHAN_RADAR) { + band_chan_arr[index].flags |= IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS; + } + if (channel & WL_CHAN_PASSIVE) { + band_chan_arr[index].flags |= IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS; + } + } + } + + if (!update) + (*n_cnt)++; + } + } + + __wl_band_2ghz.n_channels = n_2g; + __wl_band_5ghz_a.n_channels = n_5g; + + kfree(pbuf); + return err; +} + s32 wl_update_wiphybands(struct wl_priv *wl) { struct wiphy *wiphy; + struct net_device *dev; u32 bandlist[3]; u32 nband = 0; u32 i = 0; s32 err = 0; int nmode = 0; - int bw_40 = 0; + int bw_cap = 0; int index = 0; WL_DBG(("Entry")); + + if (wl == NULL) + wl = wlcfg_drv_priv; + dev = wl_to_prmry_ndev(wl); + memset(bandlist, 0, sizeof(bandlist)); - err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BANDLIST, bandlist, + err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist, sizeof(bandlist), false); if (unlikely(err)) { WL_ERR(("error read bandlist (%d)\n", err)); @@ -6745,41 +7204,44 @@ s32 wl_update_wiphybands(struct wl_priv *wl) wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; - err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "nmode", &nmode); + err = wldev_iovar_getint(dev, "nmode", &nmode); if (unlikely(err)) { WL_ERR(("error reading nmode (%d)\n", err)); - } - else { + } else { /* For nmodeonly check bw cap */ - err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "mimo_bw_cap", &bw_40); + err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap); if (unlikely(err)) { WL_ERR(("error get mimo_bw_cap (%d)\n", err)); } } + err = wl_construct_reginfo(wl, bw_cap); + if (err) { + WL_ERR(("wl_construct_reginfo() fails err=%d\n", err)); + return err; + } for (i = 1; i <= nband && i < sizeof(bandlist)/sizeof(u32); i++) { index = -1; - if (bandlist[i] == WLC_BAND_5G) { + if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) { wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; - index = IEEE80211_BAND_5GHZ; - } else if (bandlist[i] == WLC_BAND_2G) { + index = IEEE80211_BAND_5GHZ; + if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G) + wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + } else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) { wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; - index = IEEE80211_BAND_2GHZ; + index = IEEE80211_BAND_2GHZ; + if (bandlist[i] == WLC_BAND_2G && bw_cap == WLC_N_BW_40ALL) + wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; } if ((index >= 0) && nmode) { - wiphy->bands[index]->ht_cap.cap = - IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40 | - IEEE80211_HT_CAP_MAX_AMSDU; + wiphy->bands[index]->ht_cap.cap |= + IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40; wiphy->bands[index]->ht_cap.ht_supported = TRUE; wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; } - - if ((index >= 0) && bw_40) { - wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; - } } wiphy_apply_custom_regulatory(wiphy, &brcm_regdom); @@ -7106,8 +7568,7 @@ static void wl_init_eq_lock(struct wl_priv *wl) static void wl_delay(u32 ms) { - if (ms < 1000 / HZ) { - cond_resched(); + if (in_atomic() || ms < 1000 / HZ) { mdelay(ms); } else { msleep(ms); @@ -7162,17 +7623,44 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, { struct wl_priv *wl; struct net_device *ndev = NULL; + struct ether_addr primary_mac; s32 ret = 0; s32 bssidx = 0; s32 pktflag = 0; wl = wlcfg_drv_priv; - if (wl->p2p && wl->p2p->vif_created) { - ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); - bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION); - } else if (wl_get_drv_status(wl, AP_CREATING, net) || + + if (wl_get_drv_status(wl, AP_CREATING, net) || wl_get_drv_status(wl, AP_CREATED, net)) { ndev = net; bssidx = 0; + } else if (wl->p2p) { + if (net == wl->p2p_net) { + net = wl_to_prmry_ndev(wl); + } + + if (!wl->p2p->on) { + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, + &wl->p2p->int_addr); + /* In case of p2p_listen command, supplicant send remain_on_channel + * without turning on P2P + */ + p2p_on(wl) = true; + ret = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0); + + if (unlikely(ret)) { + goto exit; + } + } + if (net != wl_to_prmry_ndev(wl)) { + if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) { + ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION); + } + } else { + ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); + } } if (ndev != NULL) { switch (type) { @@ -7189,7 +7677,7 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, if (pktflag) ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len); } - +exit: return ret; } diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index fba853149c35..37c8e5850c44 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -136,6 +136,12 @@ do { \ #define WL_INVALID -1 + +/* Bring down SCB Timeout to 20secs from 60secs default */ +#ifndef WL_SCB_TIMEOUT +#define WL_SCB_TIMEOUT 20 +#endif + /* driver status */ enum wl_status { WL_STATUS_READY = 0, @@ -662,5 +668,6 @@ extern int wl_cfg80211_hang(struct net_device *dev, u16 reason); extern s32 wl_mode_to_nl80211_iftype(s32 mode); int wl_cfg80211_do_driver_init(struct net_device *net); void wl_cfg80211_enable_trace(int level); +extern s32 wl_update_wiphybands(struct wl_priv *wl); extern s32 wl_cfg80211_if_is_group_owner(void); #endif /* _wl_cfg80211_h_ */ diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index a34c4ad17c25..318e122004e7 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -59,6 +59,8 @@ static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev); static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd); static int wl_cfgp2p_if_open(struct net_device *net); static int wl_cfgp2p_if_stop(struct net_device *net); +static s32 wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev, + bool notify); static const struct net_device_ops wl_cfgp2p_if_ops = { .ndo_open = wl_cfgp2p_if_open, @@ -338,6 +340,7 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, wl_p2p_if_t ifreq; s32 err; struct net_device *ndev = wl_to_prmry_ndev(wl); + u32 scb_timeout = WL_SCB_TIMEOUT; ifreq.type = if_type; ifreq.chspec = chspec; @@ -351,6 +354,15 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq), wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); + + if (unlikely(err < 0)) { + printk("'wl p2p_ifadd' error %d\n", err); + } else if (if_type == WL_P2P_IF_GO) { + err = wldev_ioctl(ndev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true); + if (unlikely(err < 0)) + printk("'wl scb_timeout' error %d\n", err); + } + return err; } @@ -387,6 +399,7 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, { wl_p2p_if_t ifreq; s32 err; + u32 scb_timeout = WL_SCB_TIMEOUT; struct net_device *netdev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); ifreq.type = if_type; @@ -404,6 +417,10 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, if (unlikely(err < 0)) { printk("'wl p2p_ifupd' error %d\n", err); + } else if (if_type == WL_P2P_IF_GO) { + err = wldev_ioctl(netdev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true); + if (unlikely(err < 0)) + printk("'wl scb_timeout' error %d\n", err); } return err; } @@ -829,10 +846,12 @@ exit: /* Check whether the given IE looks like WFA P2P IE. */ #define wl_cfgp2p_is_p2p_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P) -/* Check whether the given IE looks like WFA WFDisplay IE. */ -#define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */ -#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ - (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD) +#ifdef WLWFDIE + /* Check whether the given IE looks like WFA WFDisplay IE. */ +#define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */ +#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ + (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD) +#endif /* WLWFDIE */ /* Delete and Set a management vndr ie to firmware * Parameters: * @wl : wl_private data @@ -957,8 +976,12 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss ie_len = ie_buf[pos++]; if ((ie_id == DOT11_MNG_VS_ID) && (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) || +#ifdef WLWFDIE wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) || wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) { +#else + wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) { +#endif /* WLWFDIE */ CFGP2P_INFO(("DELELED ID : %d, Len : %d , OUI :" "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos], ie_buf[pos+1], ie_buf[pos+2])); @@ -984,8 +1007,12 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss ie_len = ie_buf[pos++]; if ((ie_id == DOT11_MNG_VS_ID) && (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) || +#ifdef WLWFDIE wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) || wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) { +#else + wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) { +#endif /* WLWFDIE */ CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI :" "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos], ie_buf[pos+1], ie_buf[pos+2])); @@ -1095,18 +1122,21 @@ wl_cfgp2p_find_p2pie(u8 *parse, u32 len) } return NULL; } + +#ifdef WLWFDIE wifi_wfd_ie_t * wl_cfgp2p_find_wfdie(u8 *parse, u32 len) { bcm_tlv_t *ie; while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) { - if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) { + if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) { return (wifi_wfd_ie_t *)ie; } } return NULL; } +#endif /* WLWFDIE */ static s32 wl_cfgp2p_vndr_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag, @@ -1230,6 +1260,7 @@ wl_cfgp2p_listen_expired(unsigned long data) struct wl_priv *wl = (struct wl_priv *) data; CFGP2P_DBG((" Enter\n")); + memset(&msg, 0, sizeof(wl_event_msg_t)); msg.event_type = hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE); wl_cfg80211_event(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, NULL); } @@ -1237,7 +1268,7 @@ wl_cfgp2p_listen_expired(unsigned long data) /* * Routine for cancelling the P2P LISTEN */ -s32 +static s32 wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev, bool notify) { @@ -1402,13 +1433,12 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); if (ret < 0) { - CFGP2P_ERR((" sending action frame is failed\n")); goto exit; } timeout = wait_event_interruptible_timeout(wl->netif_change_event, - (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || wl_get_p2p_status(wl, ACTION_TX_NOACK)), - msecs_to_jiffies(MAX_WAIT_TIME)); + (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || wl_get_p2p_status(wl, ACTION_TX_NOACK)), + msecs_to_jiffies(MAX_WAIT_TIME)); if (timeout > 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) { CFGP2P_INFO(("tx action frame operation is completed\n")); diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index 668198d31a2e..40d9e5463fe0 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -30,7 +30,11 @@ struct wl_priv; extern u32 wl_dbg_level; + +#ifdef WLWFDIE typedef struct wifi_p2p_ie wifi_wfd_ie_t; +#endif /* WLWFDIE */ + /* Enumeration of the usages of the BSSCFGs used by the P2P Library. Do not * confuse this with a bsscfg index. This value is an index into the * saved_ie[] array of structures which in turn contains a bsscfg index field. @@ -42,7 +46,7 @@ typedef enum { P2PAPI_BSSCFG_MAX } p2p_bsscfg_type_t; -#define IE_MAX_LEN 300 +#define IE_MAX_LEN 512 /* Structure to hold all saved P2P and WPS IEs for a BSSCFG */ struct p2p_saved_ie { u8 p2p_probe_req_ie[IE_MAX_LEN]; @@ -91,7 +95,8 @@ enum wl_cfgp2p_status { WLP2P_STATUS_LISTEN_EXPIRED, WLP2P_STATUS_ACTION_TX_COMPLETED, WLP2P_STATUS_ACTION_TX_NOACK, - WLP2P_STATUS_SCANNING + WLP2P_STATUS_SCANNING, + WLP2P_STATUS_GO_NEG_PHASE }; @@ -191,8 +196,10 @@ wl_cfgp2p_find_wpsie(u8 *parse, u32 len); extern wifi_p2p_ie_t * wl_cfgp2p_find_p2pie(u8 *parse, u32 len); +#ifdef WLWFDIE extern wifi_wfd_ie_t * wl_cfgp2p_find_wfdie(u8 *parse, u32 len); +#endif /* WLWFDIE */ extern s32 wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index 059929340354..6bb07650b27e 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -6341,6 +6341,7 @@ wl_iw_set_cscan( else { WL_ERROR(("%s Ignoring CSCAN : First Scan is not done yet %d\n", __FUNCTION__, g_first_counter_scans)); + res = -EBUSY; goto exit_proc; } } -- cgit v1.2.3 From 0fd9eb0bda72152b650adcd19d29d31ec7f6794e Mon Sep 17 00:00:00 2001 From: Prem Sasidharan Date: Mon, 13 Aug 2012 13:54:16 -0700 Subject: arm: tegra: E1506 Tristate, pull down LCD pins Tristate and pull down LCD pins D0-D23, LCD_PWR* and LCD_CS*_N pins for E1506 DSI panel. Reduced the power consumption on VDDIO_LCD to 0.37mW for PM269 with E1506 DSI panel. Bug 1007512 Bug 1015349 Signed-off-by: Prem Sasidharan Change-Id: Ic54d1ca71f5ff92742f70915b7b27104c0a508a6 Reviewed-on: http://git-master/r/123172 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Jon Mayo (cherry picked from commit a8047fabd0ae8fc767ce6f276d8bfb53fc838d05) Reviewed-on: http://git-master/r/123848 Tested-by: Jon Mayo --- arch/arm/mach-tegra/board-cardhu-pinmux.c | 75 +++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/arch/arm/mach-tegra/board-cardhu-pinmux.c b/arch/arm/mach-tegra/board-cardhu-pinmux.c index 09d7c8911f22..346dccfd715b 100644 --- a/arch/arm/mach-tegra/board-cardhu-pinmux.c +++ b/arch/arm/mach-tegra/board-cardhu-pinmux.c @@ -543,6 +543,38 @@ static __initdata struct tegra_pingroup_config unused_pins_lowpower[] = { }; static __initdata struct tegra_pingroup_config unused_pins_lowpower_e1506[] = { + DEFAULT_PINMUX(LCD_D0, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D1, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D2, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D3, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D4, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D5, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D6, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D7, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D8, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D9, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D10, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D11, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D12, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D13, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D14, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D15, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D16, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D17, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D18, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D19, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D20, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D21, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D22, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D23, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + + DEFAULT_PINMUX(LCD_DC0, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PWR0, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PWR1, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PWR2, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_CS0_N, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_CS1_N, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PCLK, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), DEFAULT_PINMUX(LCD_WR_N, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), DEFAULT_PINMUX(LCD_HSYNC, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), @@ -767,6 +799,47 @@ struct gpio_init_pin_info vddio_gmi_pins_pm269_e1506[] = { PIN_GPIO_LPM("GMI_CS2", TEGRA_GPIO_PK3, 1, 0), }; +static struct gpio_init_pin_info cardhu_unused_gpio_pins_e1506[] = { + PIN_GPIO_LPM("LCD_D0", TEGRA_GPIO_PE0, 0, 0), + PIN_GPIO_LPM("LCD_D1", TEGRA_GPIO_PE1, 0, 0), + PIN_GPIO_LPM("LCD_D2", TEGRA_GPIO_PE2, 0, 0), + PIN_GPIO_LPM("LCD_D3", TEGRA_GPIO_PE3, 0, 0), + PIN_GPIO_LPM("LCD_D4", TEGRA_GPIO_PE4, 0, 0), + PIN_GPIO_LPM("LCD_D5", TEGRA_GPIO_PE5, 0, 0), + PIN_GPIO_LPM("LCD_D6", TEGRA_GPIO_PE6, 0, 0), + PIN_GPIO_LPM("LCD_D7", TEGRA_GPIO_PE7, 0, 0), + PIN_GPIO_LPM("LCD_D8", TEGRA_GPIO_PF0, 0, 0), + PIN_GPIO_LPM("LCD_D9", TEGRA_GPIO_PF1, 0, 0), + PIN_GPIO_LPM("LCD_D10", TEGRA_GPIO_PF2, 0, 0), + PIN_GPIO_LPM("LCD_D11", TEGRA_GPIO_PF3, 0, 0), + PIN_GPIO_LPM("LCD_D12", TEGRA_GPIO_PF4, 0, 0), + PIN_GPIO_LPM("LCD_D13", TEGRA_GPIO_PF5, 0, 0), + PIN_GPIO_LPM("LCD_D14", TEGRA_GPIO_PF6, 0, 0), + PIN_GPIO_LPM("LCD_D15", TEGRA_GPIO_PF7, 0, 0), + PIN_GPIO_LPM("LCD_D16", TEGRA_GPIO_PM0, 0, 0), + PIN_GPIO_LPM("LCD_D17", TEGRA_GPIO_PM1, 0, 0), + PIN_GPIO_LPM("LCD_D18", TEGRA_GPIO_PM2, 0, 0), + PIN_GPIO_LPM("LCD_D19", TEGRA_GPIO_PM3, 0, 0), + PIN_GPIO_LPM("LCD_D20", TEGRA_GPIO_PM4, 0, 0), + PIN_GPIO_LPM("LCD_D21", TEGRA_GPIO_PM5, 0, 0), + PIN_GPIO_LPM("LCD_D22", TEGRA_GPIO_PM6, 0, 0), + PIN_GPIO_LPM("LCD_D23", TEGRA_GPIO_PM7, 0, 0), + + PIN_GPIO_LPM("LCD_DC0", TEGRA_GPIO_PN6, 0, 0), + PIN_GPIO_LPM("LCD_PWR0", TEGRA_GPIO_PB2, 0, 0), + PIN_GPIO_LPM("LCD_PWR1", TEGRA_GPIO_PC1, 0, 0), + PIN_GPIO_LPM("LCD_PWR2", TEGRA_GPIO_PC6, 0, 0), + PIN_GPIO_LPM("LCD_CS0_N", TEGRA_GPIO_PN4, 0, 0), + PIN_GPIO_LPM("LCD_CS1_N", TEGRA_GPIO_PW0, 0, 0), + PIN_GPIO_LPM("LCD_PCLK", TEGRA_GPIO_PB3, 0, 0), + PIN_GPIO_LPM("LCD_WR_N", TEGRA_GPIO_PZ3, 0, 0), + PIN_GPIO_LPM("LCD_HSYNC", TEGRA_GPIO_PJ3, 0, 0), + PIN_GPIO_LPM("LCD_VSYNC", TEGRA_GPIO_PJ4, 0, 0), + PIN_GPIO_LPM("LCD_SCK", TEGRA_GPIO_PZ4, 0, 0), + PIN_GPIO_LPM("LCD_SDOUT", TEGRA_GPIO_PN5, 0, 0), + PIN_GPIO_LPM("LCD_SDIN", TEGRA_GPIO_PZ2, 0, 0), +}; + static void set_unused_pin_gpio(struct gpio_init_pin_info *lpm_pin_info, int list_count) { @@ -829,6 +902,8 @@ int __init cardhu_pins_state_init(void) if (display_board_info.board_id == BOARD_DISPLAY_E1506) { set_unused_pin_gpio(&vddio_gmi_pins_pm269_e1506[0], ARRAY_SIZE(vddio_gmi_pins_pm269_e1506)); + set_unused_pin_gpio(cardhu_unused_gpio_pins_e1506, + ARRAY_SIZE(cardhu_unused_gpio_pins_e1506)); } else if (display_board_info.board_id != BOARD_DISPLAY_PM313) { set_unused_pin_gpio(&vddio_gmi_pins_pm269_wo_pm313[0], ARRAY_SIZE(vddio_gmi_pins_pm269_wo_pm313)); -- cgit v1.2.3 From 50fa5e50b74a0534d7524fb6d7dcaa65b2e6e74c Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Thu, 16 Aug 2012 17:28:51 +0530 Subject: video: tegra: dc: fix boot issue with HDMI Set default mode for probe and resume to enable initialization of dc.1 Skipping this initialization results in hard system hang. bug 1030415 Change-Id: Icd8fe08a7803490117ed20caf0185f5cd4fb0d0b Signed-off-by: Deepak Nibade Reviewed-on: http://git-master/r/124001 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Jon Mayo Tested-by: Jon Mayo --- drivers/video/tegra/dc/dc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index da7f2910bb25..c33858ab4588 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -1814,8 +1814,8 @@ static int tegra_dc_probe(struct nvhost_device *ndev, mutex_lock(&dc->lock); if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED) { - dc->enabled = _tegra_dc_enable(dc); _tegra_dc_set_default_videomode(dc); + dc->enabled = _tegra_dc_enable(dc); } mutex_unlock(&dc->lock); @@ -1965,8 +1965,8 @@ static int tegra_dc_resume(struct nvhost_device *ndev) dc->suspended = false; if (dc->enabled) { - _tegra_dc_enable(dc); _tegra_dc_set_default_videomode(dc); + _tegra_dc_enable(dc); } if (dc->out && dc->out->hotplug_init) -- cgit v1.2.3 From ecee12f7352e9db89554db9bddc0d3b0392290b9 Mon Sep 17 00:00:00 2001 From: Hyung Taek Ryoo Date: Fri, 10 Aug 2012 11:48:56 -0700 Subject: security: tf_driver: integrate latest TL release Tegra 3 version: TF_TEGRA3_AB01.15.36932 1)Fix an issue in GIC controller 2)Add a task profiler option into the Trusted Foundations 3)Fixes the RCU stalls Bug 1030417 Reviewed-on: http://git-master/r/122808 Change-Id: I9fc15c69da94d5a2c56fc8582ccb1db0cf8936b4 Signed-off-by: Hyung Taek Ryoo Reviewed-on: http://git-master/r/123773 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: James Zhao Reviewed-by: Pradeep Thiruchelvam --- security/tf_driver/s_version.h | 2 +- security/tf_driver/tf_protocol.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/security/tf_driver/s_version.h b/security/tf_driver/s_version.h index 81d030a75835..2f52e75ac8a3 100644 --- a/security/tf_driver/s_version.h +++ b/security/tf_driver/s_version.h @@ -38,7 +38,7 @@ /* * This version number must be updated for each new release */ -#define S_VERSION_MAIN "01.14" +#define S_VERSION_MAIN "01.15" /* * If this is a patch or engineering version use the following diff --git a/security/tf_driver/tf_protocol.h b/security/tf_driver/tf_protocol.h index b264f04c4454..e39842bd6e16 100644 --- a/security/tf_driver/tf_protocol.h +++ b/security/tf_driver/tf_protocol.h @@ -659,7 +659,7 @@ struct tf_l1_shared_buffer { #ifdef CONFIG_TF_ZEBRA u8 rpc_trace_buffer[140]; u8 rpc_cus_buffer[180]; - #elif CONFIG_SECURE_TRACES + #elif defined(CONFIG_SECURE_TRACES) u32 traces_status; u8 traces_buffer[140]; u8 reserved3[176]; -- cgit v1.2.3 From 7900270d2d4ecf6c28e5ff8da348c8fb2a915f79 Mon Sep 17 00:00:00 2001 From: Steve Lin Date: Mon, 30 Jul 2012 17:34:00 -0700 Subject: arm: tegra: baseband: Fix sysfs node permissions Restricting the modem sysfs node permissions to owner only. Bug 1025901 Change-Id: I85095c06b6f5329403b66389a5f27383464f2c64 Signed-off-by: Steve Lin (cherry picked from commit 21bbdcd602f8de21ab09de64cf15fee20643c8ea) Reviewed-on: http://git-master/r/124131 Reviewed-by: Automatic_Commit_Validation_User Tested-by: Peter Zu --- arch/arm/mach-tegra/tegra_usb_modem_power.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-tegra/tegra_usb_modem_power.c b/arch/arm/mach-tegra/tegra_usb_modem_power.c index bb9495a329a6..63e4b177bfad 100644 --- a/arch/arm/mach-tegra/tegra_usb_modem_power.c +++ b/arch/arm/mach-tegra/tegra_usb_modem_power.c @@ -400,7 +400,8 @@ static ssize_t load_unload_usb_host(struct device *dev, return count; } -static DEVICE_ATTR(load_host, 0666, show_usb_host, load_unload_usb_host); +static DEVICE_ATTR(load_host, S_IRUSR | S_IWUSR, show_usb_host, + load_unload_usb_host); static int mdm_init(struct tegra_usb_modem *modem, struct platform_device *pdev) { -- cgit v1.2.3 From 5aa71345ae7028eacb69973fdedabd78fe21ba11 Mon Sep 17 00:00:00 2001 From: BH Hsieh Date: Mon, 13 Aug 2012 15:33:07 +0800 Subject: PM: Need to wake_up_all when suspend fail In rpm_suspend, when suspend fail, before going to reschedule another autosuspend, wake_up_all is required to avoid remote wakeup issues. Bug 1026169 Bug 1027598 Bug 1032565 Change-Id: Ieaf9282dae59b2cb343bf01aa2ba837a8cdc39c7 Signed-off-by: BH Hsieh Reviewed-on: http://git-master/r/122978 (cherry picked from commit 856f955552e8dbdf3b4a25c3eb648bcd5193cacf) Reviewed-on: http://git-master/r/124535 Reviewed-by: Neil Patel Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Tested-by: Neil Patel Reviewed-by: Steve Lin --- drivers/base/power/runtime.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 3f141ea9283d..37489733cb9d 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -406,8 +406,10 @@ static int rpm_suspend(struct device *dev, int rpmflags) * reschedule another autosuspend. */ if ((rpmflags & RPM_AUTO) && - pm_runtime_autosuspend_expiration(dev) != 0) + pm_runtime_autosuspend_expiration(dev) != 0) { + wake_up_all(&dev->power.wait_queue); goto repeat; + } } else { pm_runtime_cancel_pending(dev); } -- cgit v1.2.3 From 33d592157f162df970b7ac7204df0eec604818a0 Mon Sep 17 00:00:00 2001 From: Karthik Ramakrishnan Date: Mon, 13 Aug 2012 19:09:16 -0700 Subject: arm: tegra: Set Core to 0.95V in LP1 When the device prepares for LP1, the Core voltage is set to the highest value(1.2V for Enterprise and Kai, and 1.3V for AP37 and Cardhu). This is to set for some of the driver suspend along the sequence need a higher emc frequency and thus a higher Core voltage. Since the sequence of drivers suspend depends on the sequence of their registration in the table, which in turn is platform-dependent, there is no right place in the LP1 entry path where the Core voltage can be set to a lower voltage. Hence, the Core voltage remains high in LP1 resulting in higher power. Thus, the only safe location where the Core voltage can be lowered is once all the drivers are suspended and the DRAM is set in self-refresh, at the final point just before the system is suspended in the IRAM code. This location at the assembly code ensures that no other module will be running and thus that nothing will require a higher core voltage. The Core is set to the lowest possible value since nothing requires it. It is then restored to the highest voltage as soon as the LP1 resume code is started so that all drivers are resumed safely. At the execution point in IRAM during LP1 suspend path, even the I2C clocks are gated. They must be reset first and then the I2C transaction is performed. An I2C transaction involves 4 bytes of data, to send the slave address, the Core voltage register address and 2 bytes of data which has the value to set the voltage(the second byte is not required for this transaction). Once these registers are set, the I2C transaction is performed by setting the I2C transaction register to 0xA02. After sending the I2C transaction, we wait for about 250us to check the status of the transaction and if not updated, wait for more time to check again. If after 2ms and the transaction fails to register, the transaction is aborted and the device is allowed to enter at high voltage. Since the failure rate of I2C transaction is very low at this point in execution where there will be no conflicts in the bus, it is okay to have Core high for some of the LP1 cycles. However, it is unacceptable for the I2C transaction to fail on the way from LP1 resume since the device cannot come up with a lower Core voltage. In this case, the transaction is retried again and again till it is successful. There is no way but to keep trying as the device would fail to resume with Core at 0.95V. Each platform(or each PMU) has different values for the I2C transaction ie. slave address, Core voltage register and the value to set the voltage. For the device in IRAM, it cannot access anything in SDRAM memory, these values needs to be pushed to IRAM memory before the device starts execution in IRAM. This is done during initialization of suspend code when it picks values from the board files and copies it to IRAM part of code, before the whole memory is copied to IRAM. This new feature is controlled by a KConfig variable TEGRA_LP1_950 which should be enabled once the board file of the device is updated with the right values. The device hangs when it does not have the right values for the I2C transaction. With this change in Core, LP1 power is reduced by 12mW in Enterprise, 20mW in AP37 and about 24mW in Kai. Bug 1035684 Change-Id: I4318c66fd70ab227ef0786d6a13286e020e4541d Signed-off-by: Karthik Ramakrishnan Reviewed-on: http://git-master/r/124135 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Dan Willemsen --- arch/arm/mach-tegra/Kconfig | 7 ++ arch/arm/mach-tegra/pm.c | 15 +++++ arch/arm/mach-tegra/pm.h | 8 +++ arch/arm/mach-tegra/sleep-t3.S | 150 ++++++++++++++++++++++++++++++++++++++++- arch/arm/mach-tegra/sleep.h | 40 +++++++++++ 5 files changed, 219 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index b69f0dc6e24d..da6d33998a4d 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -563,4 +563,11 @@ config TEGRA_SKIN_THROTTLE help Enable throttling to control the temperature of the skin/case of the device. + +config TEGRA_LP1_950 + bool "LP1 low core voltage" + default n + depends on ARCH_TEGRA_3x_SOC + help + Enable support for LP1 Core voltage to set to lowest endif diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index d251e57626aa..2cdfdfe6f43d 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -1186,6 +1186,21 @@ out: plat->suspend_mode = TEGRA_SUSPEND_LP2; } +#ifdef CONFIG_TEGRA_LP1_950 + if (pdata->lp1_lowvolt_support) { + u32 lp1_core_lowvolt, lp1_core_highvolt; + memcpy(tegra_lp1_register_pmuslave_addr(), &pdata->pmuslave_addr, 4); + memcpy(tegra_lp1_register_i2c_base_addr(), &pdata->i2c_base_addr, 4); + + lp1_core_lowvolt = 0; + lp1_core_lowvolt = (pdata->lp1_core_volt_low << 8) | pdata->core_reg_addr; + memcpy(tegra_lp1_register_core_lowvolt(), &lp1_core_lowvolt, 4); + + lp1_core_highvolt = 0; + lp1_core_highvolt = (pdata->lp1_core_volt_high << 8) | pdata->core_reg_addr; + memcpy(tegra_lp1_register_core_highvolt(), &lp1_core_highvolt, 4); + } +#endif /* !!!FIXME!!! THIS IS TEGRA2 ONLY */ /* Initialize scratch registers used for CPU LP2 synchronization */ writel(0, pmc + PMC_SCRATCH37); diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h index b78e9b1abc00..5ea2b7f843a2 100644 --- a/arch/arm/mach-tegra/pm.h +++ b/arch/arm/mach-tegra/pm.h @@ -65,6 +65,14 @@ struct tegra_suspend_platform_data { /* lp_state = 0 for LP0 state, 1 for LP1 state, 2 for LP2 state */ void (*board_resume)(int lp_state, enum resume_stage stg); unsigned int cpu_resume_boost; /* CPU frequency resume boost in kHz */ +#ifdef CONFIG_TEGRA_LP1_950 + bool lp1_lowvolt_support; + unsigned int i2c_base_addr; + unsigned int pmuslave_addr; + unsigned int core_reg_addr; + unsigned int lp1_core_volt_low; + unsigned int lp1_core_volt_high; +#endif }; /* clears io dpd settings before kernel code */ diff --git a/arch/arm/mach-tegra/sleep-t3.S b/arch/arm/mach-tegra/sleep-t3.S index 23e96c605b96..4ee73d581a08 100644 --- a/arch/arm/mach-tegra/sleep-t3.S +++ b/arch/arm/mach-tegra/sleep-t3.S @@ -95,6 +95,16 @@ #define PMC_PLLM_WB0_OVERRIDE 0x1dc #define CLK_RESET_CLK_SOURCE_MSELECT 0x3b4 +#define CLK_RESET_CLK_ENB_H_SET 0x328 +#define CLK_RESET_CLK_ENB_H_CLR 0x32c +#define CLK_RESET_CLK_RST_DEV_H_SET 0x308 +#define CLK_RESET_CLK_RST_DEV_H_CLR 0x30c + +#define I2C_CNFG 0x0 +#define I2C_ADDR0 0x4 +#define I2C_DATA1 0xc +#define I2C_DATA2 0x10 +#define I2C_STATUS 0x1c #define MSELECT_CLKM (0x3 << 30) @@ -348,6 +358,66 @@ ENTRY(tegra3_lp1_reset) mov32 r4, ((1<<28) | (8)) @ burst policy is PLLX str r4, [r0, #CLK_RESET_CCLK_BURST] +#ifdef CONFIG_TEGRA_LP1_950 +lp1_voltset: + /* Restore the Core voltage to high on LP1 resume */ + /* Reset(Enable/Disable) the DVC-I2C Controller*/ + mov r1, #(1 << 15) + str r1, [r0, #CLK_RESET_CLK_RST_DEV_H_SET] + + /* Wait for 2us */ + mov32 r7, TEGRA_TMRUS_BASE + wait_for_us r1, r7, r9 + add r1, r1, #2 + wait_until r1, r7, r9 + + mov r1, #(1 << 15) + str r1, [r0, #CLK_RESET_CLK_RST_DEV_H_CLR] + + /* Enable the DVC-I2C Controller */ + mov r1, #(1 << 15) + str r1, [r0, #CLK_RESET_CLK_ENB_H_SET] + + + /* Same I2C transaction protocol as suspend */ + ldr r1, lp1_register_pmuslave_addr + cmp r1, #0 + beq lp1_voltskip_resume + + ldr r4, lp1_register_i2c_base_addr + str r1, [r4, #I2C_ADDR0] + + mov32 r1, 0x2 + str r1, [r4, #I2C_CNFG] + + ldr r1, lp1_register_core_highvolt + str r1, [r4, #I2C_DATA1] + + mov32 r1, 0 + str r1, [r4, #I2C_DATA2] + + mov32 r1, 0xA02 + str r1, [r4, #I2C_CNFG] + + wait_for_us r1, r7, r9 + mov32 r3, 0x7D0 /* Wait for 2ms and try transaction again */ + add r0, r1, r3 +loop_i2c_status_resume: + add r1, r1, #0xFA /* Check status every 250us */ + wait_until r1, r7, r9 + cmp r0, r1 + beq lp1_voltset + + ldr r3, [r4, #I2C_STATUS] + cmp r3, #0 + bne loop_i2c_status_resume + +lp1_voltskip_resume: + /* Disable the DVC-I2C Controller */ + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_ENB_H_CLR] +#endif + #if defined (CONFIG_CACHE_L2X0) /* power up L2 */ ldr r0, [r2, #PMC_PWRGATE_STATUS] @@ -492,6 +562,21 @@ tegra3_sdram_pad_address: tegra3_sdram_pad_size: .word tegra3_sdram_pad_address - tegra3_sdram_pad_save +#ifdef CONFIG_TEGRA_LP1_950 + .globl lp1_register_pmuslave_addr + .globl lp1_register_i2c_base_addr + .globl lp1_register_core_lowvolt + .globl lp1_register_core_highvolt +lp1_register_pmuslave_addr: + .word 0 +lp1_register_i2c_base_addr: + .word 0 +lp1_register_core_lowvolt: + .word 0 +lp1_register_core_highvolt: + .word 0 +#endif + /* * tegra3_tear_down_core * @@ -526,9 +611,72 @@ tegra3_cpu_clk32k: str r0, [r4, #PMC_PLLM_WB0_OVERRIDE] mov pc, lr +lp1_clocks_prepare: + /* Prepare to set the Core to the lowest voltage if supported. + * Start by setting the I2C clocks to make the I2C transfer */ +#ifdef CONFIG_TEGRA_LP1_950 + /* Set up the PWR I2C GPIOs with the right masks*/ + + /* Reset(Set/Clr) the DVC-I2C Controller*/ + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_RST_DEV_H_SET] + + /* Wait for 2us */ + wait_for_us r1, r7, r9 + mov32 r0, 0x7D0 + add r1, r1, r0 + wait_until r1, r7, r9 + + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_RST_DEV_H_CLR] + + /* Enable the DVC-I2C Controller */ + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_ENB_H_SET] + + /* I2C transfer protocol: + * 4 packets: Slaveaddr + WriteConfigure + Data1 + Data2 */ + ldr r0, lp1_register_pmuslave_addr + cmp r0, #0 + beq lp1_volt_skip + ldr r1, lp1_register_i2c_base_addr + str r0, [r1, #I2C_ADDR0] + + mov32 r0, 0x2 + str r0, [r1, #I2C_CNFG] + + ldr r0, lp1_register_core_lowvolt + str r0, [r1, #I2C_DATA1] + + mov32 r0, 0 + str r0, [r1, #I2C_DATA2] + + /* Send I2C transaction */ + mov32 r0, 0xA02 + str r0, [r1, #I2C_CNFG] + + /* Check the transaction status before proceeding */ + wait_for_us r2, r7, r9 + mov32 r3, 0x7D0 /* Wait for 2ms for I2C transaction */ + add r3, r2, r3 +loop_i2c_status_suspend: + add r2, r2, #0xFA /* Check status every 250us */ + cmp r3, r2 + beq lp1_volt_skip /* Waited for 2ms, I2C transaction didn't take place */ + wait_until r2, r7, r9 + + ldr r0, [r1, #I2C_STATUS] + cmp r0, #0 + bne loop_i2c_status_suspend +lp1_volt_skip: + + /* Disable the DVC-I2C Controller */ + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_ENB_H_CLR] + +#endif /* start by jumping to clkm to safely disable PLLs, then jump * to clks */ -lp1_clocks_prepare: mov r0, #(1 << 28) str r0, [r5, #CLK_RESET_SCLK_BURST] str r0, [r5, #CLK_RESET_CCLK_BURST] diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h index c57399985ecd..48b2bb8cfdb2 100644 --- a/arch/arm/mach-tegra/sleep.h +++ b/arch/arm/mach-tegra/sleep.h @@ -223,6 +223,10 @@ void tegra2_sleep_wfi(unsigned long v2p); #else extern unsigned int tegra3_iram_start; extern unsigned int tegra3_iram_end; +extern unsigned int lp1_register_pmuslave_addr; +extern unsigned int lp1_register_i2c_base_addr; +extern unsigned int lp1_register_core_lowvolt; +extern unsigned int lp1_register_core_highvolt; void tegra3_sleep_core(unsigned long v2p); void tegra3_sleep_cpu_secondary(unsigned long v2p); void tegra3_hotplug_shutdown(void); @@ -245,5 +249,41 @@ static inline void *tegra_iram_end(void) return &tegra3_iram_end; #endif } + +static inline void *tegra_lp1_register_pmuslave_addr(void) +{ +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + return NULL; +#else + return &lp1_register_pmuslave_addr; +#endif +} + +static inline void *tegra_lp1_register_i2c_base_addr(void) +{ +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + return NULL; +#else + return &lp1_register_i2c_base_addr; +#endif +} + +static inline void *tegra_lp1_register_core_lowvolt(void) +{ +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + return NULL; +#else + return &lp1_register_core_lowvolt; +#endif +} + +static inline void *tegra_lp1_register_core_highvolt(void) +{ +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + return NULL; +#else + return &lp1_register_core_highvolt; +#endif +} #endif #endif -- cgit v1.2.3 From 002e60d4ed08ef4eb3d117e47db7fb40322a278c Mon Sep 17 00:00:00 2001 From: Karthik Ramakrishnan Date: Fri, 10 Aug 2012 17:24:20 -0700 Subject: arm: tegra: Board files settings for LP1 0.95V CoreV Set the register values for each of the board files to keep the Core voltage to 0.95V in LP1. This change is only for those platforms where LP1 is supported. Enterprise and Kai are the main platforms for this change. There is no support for Cardhu for LP1 and so is left blank and the feature will be skipped for Cardhu platforms, except for AP37. AP37 with a PM269 board needs this change and so Cardhu board file is updated with the values specific to AP37. This change is part of the feature to set VCore to 0.95V Refer to http://git-master/r/124135 for more details Bug 1035684 Change-Id: I6d1d984b0e7968b441cebbc37705c25647a4a85a Signed-off-by: Karthik Ramakrishnan Reviewed-on: http://git-master/r/124136 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Dan Willemsen --- arch/arm/mach-tegra/board-cardhu-power.c | 21 +++++++++++++++++++++ arch/arm/mach-tegra/board-enterprise-power.c | 8 ++++++++ arch/arm/mach-tegra/board-kai-power.c | 8 ++++++++ 3 files changed, 37 insertions(+) diff --git a/arch/arm/mach-tegra/board-cardhu-power.c b/arch/arm/mach-tegra/board-cardhu-power.c index 4f96c5cc5d05..e76cbc458914 100644 --- a/arch/arm/mach-tegra/board-cardhu-power.c +++ b/arch/arm/mach-tegra/board-cardhu-power.c @@ -1134,15 +1134,25 @@ static struct tegra_suspend_platform_data cardhu_suspend_data = { .cpu_lp2_min_residency = 2000, .board_suspend = cardhu_board_suspend, .board_resume = cardhu_board_resume, +#ifdef CONFIG_TEGRA_LP1_950 + .lp1_lowvolt_support = false, + .i2c_base_addr = 0, + .pmuslave_addr = 0, + .core_reg_addr = 0, + .lp1_core_volt_low = 0, + .lp1_core_volt_high = 0, +#endif }; int __init cardhu_suspend_init(void) { struct board_info board_info; struct board_info pmu_board_info; + struct board_info display_board_info; tegra_get_board_info(&board_info); tegra_get_pmu_board_info(&pmu_board_info); + tegra_get_display_board_info(&display_board_info); /* For PMU Fab A03, A04 and A05 make core_pwr_req to high */ if ((pmu_board_info.fab == BOARD_FAB_A03) || @@ -1170,6 +1180,17 @@ int __init cardhu_suspend_init(void) tegra_disable_wake_source(TEGRA_WAKE_USB1_VBUS); break; case BOARD_PM269: +#ifdef CONFIG_TEGRA_LP1_950 + /* AP37 board supports the LP1_950mV feature */ + if (is_display_board_dsi(display_board_info.board_id)) { + cardhu_suspend_data.lp1_lowvolt_support = true; + cardhu_suspend_data.i2c_base_addr = TEGRA_I2C5_BASE; + cardhu_suspend_data.pmuslave_addr = 0xC0; + cardhu_suspend_data.core_reg_addr = 0x03; + cardhu_suspend_data.lp1_core_volt_low = 0x2D; + cardhu_suspend_data.lp1_core_volt_high = 0x50; + } +#endif case BOARD_PM305: case BOARD_PM311: break; diff --git a/arch/arm/mach-tegra/board-enterprise-power.c b/arch/arm/mach-tegra/board-enterprise-power.c index 37d4576feb96..ad5e486b84de 100644 --- a/arch/arm/mach-tegra/board-enterprise-power.c +++ b/arch/arm/mach-tegra/board-enterprise-power.c @@ -791,6 +791,14 @@ static struct tegra_suspend_platform_data enterprise_suspend_data = { .sysclkreq_high = true, .board_suspend = enterprise_board_suspend, .board_resume = enterprise_board_resume, +#ifdef CONFIG_TEGRA_LP1_950 + .lp1_lowvolt_support = true, + .i2c_base_addr = TEGRA_I2C5_BASE, + .pmuslave_addr = 0x24, + .core_reg_addr = 0x5B, + .lp1_core_volt_low = 0x1D, + .lp1_core_volt_high = 0x33, +#endif }; static void enterprise_init_deep_sleep_mode(void) diff --git a/arch/arm/mach-tegra/board-kai-power.c b/arch/arm/mach-tegra/board-kai-power.c index 6c66f1d2bbe9..027d97458dd3 100644 --- a/arch/arm/mach-tegra/board-kai-power.c +++ b/arch/arm/mach-tegra/board-kai-power.c @@ -614,6 +614,14 @@ static struct tegra_suspend_platform_data kai_suspend_data = { .cpu_lp2_min_residency = 2000, .board_suspend = kai_board_suspend, .board_resume = kai_board_resume, +#ifdef CONFIG_TEGRA_LP1_950 + .lp1_lowvolt_support = true, + .i2c_base_addr = TEGRA_I2C5_BASE, + .pmuslave_addr = 0x78, + .core_reg_addr = 0x17, + .lp1_core_volt_low = 0x0C, + .lp1_core_volt_high = 0x20, +#endif }; int __init kai_suspend_init(void) -- cgit v1.2.3 From 6a7acfda96621c36c6f6d4e3bebf3fd3b2f6c04f Mon Sep 17 00:00:00 2001 From: Karthik Ramakrishnan Date: Fri, 10 Aug 2012 17:33:20 -0700 Subject: arm: tegra: Enable LP1_950 config Enable LP1 Core voltage settings to 950mV The feature is added in the below change. Refer to http://git-master/r/#change,124135 for more details. Bug 1035684 Change-Id: I922efff17797f4666fd6ed069a8523c164445842 Signed-off-by: Karthik Ramakrishnan Reviewed-on: http://git-master/r/124137 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Dan Willemsen --- arch/arm/configs/tegra3_android_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/tegra3_android_defconfig b/arch/arm/configs/tegra3_android_defconfig index 0eb50c7eb645..1a47741b40ce 100644 --- a/arch/arm/configs/tegra3_android_defconfig +++ b/arch/arm/configs/tegra3_android_defconfig @@ -40,6 +40,7 @@ CONFIG_TEGRA_USB_MODEM_POWER=y CONFIG_TEGRA_BB_XMM_POWER=y CONFIG_TEGRA_BB_XMM_POWER2=m CONFIG_TEGRA_PLLM_RESTRICTED=y +CONFIG_TEGRA_LP1_950=y CONFIG_ARM_ERRATA_742230=y CONFIG_ARM_ERRATA_743622=y CONFIG_ARM_ERRATA_751472=y -- cgit v1.2.3 From 1c21c5a7abb7e97d93b871e40f103ed658a7317c Mon Sep 17 00:00:00 2001 From: Krishna Yarlagadda Date: Tue, 14 Aug 2012 21:36:59 +0530 Subject: ARM: tegra: usb: handle device connect in lp0 When a otg cable is connected along with device during lp0 system will wakeup but might not complete device enumeration before going back to lp0. In this case we have to handle pmc disable. Bug 1024456 Reviewed-on: http://git-master/r/123383 (cherry picked from commit 6399f339601cee0f39e48011265d0e324e7dd99e) Change-Id: Ib401c27a0d6729c906f5d3e1450548f21ff638f7 Signed-off-by: Krishna Yarlagadda Reviewed-on: http://git-master/r/124317 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Venkat Moganty --- arch/arm/mach-tegra/tegra3_usb_phy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-tegra/tegra3_usb_phy.c b/arch/arm/mach-tegra/tegra3_usb_phy.c index af9eaab782c7..b02e9b646284 100644 --- a/arch/arm/mach-tegra/tegra3_usb_phy.c +++ b/arch/arm/mach-tegra/tegra3_usb_phy.c @@ -1657,11 +1657,11 @@ static void utmi_phy_restore_start(struct tegra_usb_phy *phy) if (UTMIP_WALK_PTR_VAL(inst) & val) { phy->remote_wakeup = true; } else if(!phy->remote_wakeup) { - if (!((UTMIP_USBON_VAL(phy->inst) | - UTMIP_USBOP_VAL(phy->inst)) & val)) { - utmip_phy_disable_pmc_bus_ctrl(phy); - } + val = readl(pmc_base + PMC_SLEEP_CFG); + if (val & UTMIP_MASTER_ENABLE(inst)) + utmip_phy_disable_pmc_bus_ctrl(phy); } + utmi_phy_enable_obs_bus(phy); } -- cgit v1.2.3 From 2d3e074eb3afc0ddcdff72e732e8500e1c80b334 Mon Sep 17 00:00:00 2001 From: Charlie Huang Date: Fri, 10 Aug 2012 16:26:34 -0700 Subject: ARM: tegra: cardhu: adjust ov2710 power sequence To fix an instability issue, the power sequence is updated to match the specification for this device. bug 1031318 Change-Id: I77c16e883ce6a5a37dace9372a016b0cbc71012b Signed-off-by: Charlie Huang Reviewed-on: http://git-master/r/122867 (cherry picked from commit e2862b9cd75bb9f608db0c33bef47f3952df5f26) Reviewed-on: http://git-master/r/124443 Reviewed-by: Sang-Hun Lee Tested-by: Sang-Hun Lee Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Dan Willemsen Reviewed-by: Manish Tuteja --- arch/arm/mach-tegra/board-cardhu-sensors.c | 45 ++++++++++++++++-------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu-sensors.c b/arch/arm/mach-tegra/board-cardhu-sensors.c index bb6a2ae5774d..7e9774f290eb 100644 --- a/arch/arm/mach-tegra/board-cardhu-sensors.c +++ b/arch/arm/mach-tegra/board-cardhu-sensors.c @@ -340,7 +340,7 @@ static int cardhu_right_ov5650_power_off(void) gpio_direction_output(CAMERA_CSI_MUX_SEL_GPIO, 0); /* Boards E1198 and E1291 are of Cardhu personality - * and donot have TCA6416 exp for camera */ + * and do not have TCA6416 for camera */ if ((board_info.board_id == BOARD_E1198) || (board_info.board_id == BOARD_E1291)) { gpio_direction_output(CAM1_POWER_DWN_GPIO, 1); @@ -387,16 +387,21 @@ static int cardhu_ov2710_power_on(void) /* CSI-B and front sensor are muxed on cardhu */ gpio_direction_output(CAMERA_CSI_MUX_SEL_GPIO, 1); + /* Enable VDD_1V8_Cam3 */ + if (cardhu_1v8_cam3 == NULL) { + cardhu_1v8_cam3 = regulator_get(NULL, "vdd_1v8_cam3"); + if (WARN_ON(IS_ERR(cardhu_1v8_cam3))) { + pr_err("%s: couldn't get regulator vdd_1v8_cam3: %ld\n", + __func__, PTR_ERR(cardhu_1v8_cam3)); + goto reg_alloc_fail; + } + } + regulator_enable(cardhu_1v8_cam3); + /* Boards E1198 and E1291 are of Cardhu personality - * and donot have TCA6416 exp for camera */ + * and do not have TCA6416 for camera */ if ((board_info.board_id == BOARD_E1198) || (board_info.board_id == BOARD_E1291)) { - - gpio_direction_output(CAM1_POWER_DWN_GPIO, 0); - gpio_direction_output(CAM2_POWER_DWN_GPIO, 0); - gpio_direction_output(CAM3_POWER_DWN_GPIO, 0); - mdelay(10); - if (cardhu_vdd_cam3 == NULL) { cardhu_vdd_cam3 = regulator_get(NULL, "vdd_cam3"); if (WARN_ON(IS_ERR(cardhu_vdd_cam3))) { @@ -406,19 +411,17 @@ static int cardhu_ov2710_power_on(void) } } regulator_enable(cardhu_vdd_cam3); - } - /* Enable VDD_1V8_Cam3 */ - if (cardhu_1v8_cam3 == NULL) { - cardhu_1v8_cam3 = regulator_get(NULL, "vdd_1v8_cam3"); - if (WARN_ON(IS_ERR(cardhu_1v8_cam3))) { - pr_err("%s: couldn't get regulator vdd_1v8_cam3: %ld\n", - __func__, PTR_ERR(cardhu_1v8_cam3)); - goto reg_alloc_fail; - } + mdelay(5); + + gpio_direction_output(CAM1_POWER_DWN_GPIO, 0); + gpio_direction_output(CAM2_POWER_DWN_GPIO, 0); + gpio_direction_output(CAM3_POWER_DWN_GPIO, 0); + mdelay(10); + } - regulator_enable(cardhu_1v8_cam3); - mdelay(5); + + mdelay(20); return 0; @@ -447,12 +450,12 @@ static int cardhu_ov2710_power_off(void) gpio_direction_output(CAM1_POWER_DWN_GPIO, 1); gpio_direction_output(CAM2_POWER_DWN_GPIO, 1); gpio_direction_output(CAM3_POWER_DWN_GPIO, 1); + if (cardhu_vdd_cam3) + regulator_disable(cardhu_vdd_cam3); } if (cardhu_1v8_cam3) regulator_disable(cardhu_1v8_cam3); - if (cardhu_vdd_cam3) - regulator_disable(cardhu_vdd_cam3); return 0; } -- cgit v1.2.3 From d2b1e1ddb2e65482eb15698b925471daf573a7ba Mon Sep 17 00:00:00 2001 From: Sang-Hun Lee Date: Fri, 17 Aug 2012 16:54:05 -0700 Subject: ARM: tegra: kai: adjust ov2710 power sequence Update the power sequence to match the specification Bug 1031318 Change-Id: If77777bf23fda32fa9698f53691b99b50cb35bde Signed-off-by: Sang-Hun Lee Reviewed-on: http://git-master/r/124496 Reviewed-by: Charlie Huang Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Dan Willemsen --- arch/arm/mach-tegra/board-kai-sensors.c | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-tegra/board-kai-sensors.c b/arch/arm/mach-tegra/board-kai-sensors.c index 29d1bea2e8a7..048c39c9759f 100644 --- a/arch/arm/mach-tegra/board-kai-sensors.c +++ b/arch/arm/mach-tegra/board-kai-sensors.c @@ -179,8 +179,15 @@ static int kai_camera_init(void) static int kai_ov2710_power_on(void) { - gpio_direction_output(CAM2_POWER_DWN_GPIO, 0); - mdelay(10); + if (kai_1v8_cam3 == NULL) { + kai_1v8_cam3 = regulator_get(NULL, "vdd_1v8_cam3"); + if (WARN_ON(IS_ERR(kai_1v8_cam3))) { + pr_err("%s: couldn't get regulator vdd_1v8_cam3: %d\n", + __func__, (int)PTR_ERR(kai_1v8_cam3)); + goto reg_get_vdd_1v8_cam3_fail; + } + } + regulator_enable(kai_1v8_cam3); if (kai_vdd_cam3 == NULL) { kai_vdd_cam3 = regulator_get(NULL, "vdd_cam3"); @@ -191,43 +198,36 @@ static int kai_ov2710_power_on(void) } } regulator_enable(kai_vdd_cam3); - - if (kai_1v8_cam3 == NULL) { - kai_1v8_cam3 = regulator_get(NULL, "vdd_1v8_cam3"); - if (WARN_ON(IS_ERR(kai_1v8_cam3))) { - pr_err("%s: couldn't get regulator vdd_1v8_cam3: %d\n", - __func__, (int)PTR_ERR(kai_1v8_cam3)); - goto reg_get_vdd_1v8_cam3_fail; - } - } - regulator_enable(kai_1v8_cam3); mdelay(5); + gpio_direction_output(CAM2_POWER_DWN_GPIO, 0); + mdelay(10); + gpio_direction_output(CAM2_RST_GPIO, 1); mdelay(10); return 0; -reg_get_vdd_1v8_cam3_fail: - kai_1v8_cam3 = NULL; - regulator_put(kai_vdd_cam3); - reg_get_vdd_cam3_fail: kai_vdd_cam3 = NULL; + regulator_put(kai_1v8_cam3); + +reg_get_vdd_1v8_cam3_fail: + kai_1v8_cam3 = NULL; return -ENODEV; } static int kai_ov2710_power_off(void) { - gpio_direction_output(CAM2_POWER_DWN_GPIO, 1); - gpio_direction_output(CAM2_RST_GPIO, 0); - if (kai_1v8_cam3) - regulator_disable(kai_1v8_cam3); + gpio_direction_output(CAM2_POWER_DWN_GPIO, 1); + if (kai_vdd_cam3) regulator_disable(kai_vdd_cam3); + if (kai_1v8_cam3) + regulator_disable(kai_1v8_cam3); return 0; } -- cgit v1.2.3 From 1b17974177148f058e6d09d5dec20dc1dc59f018 Mon Sep 17 00:00:00 2001 From: Wen Yi Date: Tue, 21 Aug 2012 11:35:35 -0700 Subject: Revert "arm: tegra: la: hack latency allowance formula" This reverts commit 935adef53692ab73a02a7d09876756b30beb5206. The orginal patch is used to boost emc performance to fix display underflow. It doesn't achieve the goal but with side effect of higher power. Proper fix is required and the patch is reverted. Bug 996270 Signed-off-by: Wen Yi Change-Id: I6d7364b311e4de86ceed40ff438ee9549251e02e Reviewed-on: http://git-master/r/124975 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Yu-Huan Hsu Reviewed-by: Michael Frydrych --- arch/arm/mach-tegra/latency_allowance.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-tegra/latency_allowance.c b/arch/arm/mach-tegra/latency_allowance.c index 8d16d8d36661..e550cc142528 100644 --- a/arch/arm/mach-tegra/latency_allowance.c +++ b/arch/arm/mach-tegra/latency_allowance.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/latency_allowance.c * - * Copyright (C) 2011-2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (C) 2011 NVIDIA Corporation * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -100,9 +100,6 @@ printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__); \ } -/* Bug 995270 */ -#define HACK_LA_FIFO 1 - static struct dentry *latency_debug_dir; struct la_client_info { @@ -387,9 +384,7 @@ int tegra_set_latency_allowance(enum tegra_la_id id, int la_to_set; unsigned long reg_read; unsigned long reg_write; - unsigned int fifo_size_in_atoms; int bytes_per_atom = normal_atom_size; - const int fifo_scale = 4; /* 25% of the FIFO */ struct la_client_info *ci; VALIDATE_ID(id); @@ -399,19 +394,11 @@ int tegra_set_latency_allowance(enum tegra_la_id id, bytes_per_atom = fdc_atom_size; ci = &la_info[id]; - fifo_size_in_atoms = ci->fifo_size_in_atoms; - -#if HACK_LA_FIFO - /* pretend that our FIFO is only as deep as the lowest fullness - * we expect to see */ - if (id >= ID(DISPLAY_0A) && id <= ID(DISPLAY_HCB)) - fifo_size_in_atoms /= fifo_scale; -#endif if (bandwidth_in_mbps == 0) { la_to_set = MC_LA_MAX_VALUE; } else { - ideal_la = (fifo_size_in_atoms * bytes_per_atom * 1000) / + ideal_la = (ci->fifo_size_in_atoms * bytes_per_atom * 1000) / (bandwidth_in_mbps * ns_per_tick); la_to_set = ideal_la - (ci->expiration_in_ns/ns_per_tick) - 1; } @@ -422,6 +409,11 @@ int tegra_set_latency_allowance(enum tegra_la_id id, la_to_set = (la_to_set > MC_LA_MAX_VALUE) ? MC_LA_MAX_VALUE : la_to_set; scaling_info[id].actual_la_to_set = la_to_set; + /* until display can use latency allowance scaling, use a more + * aggressive LA setting. Bug 862709 */ + if (id >= ID(DISPLAY_0A) && id <= ID(DISPLAY_HCB)) + la_to_set /= 3; + spin_lock(&safety_lock); reg_read = readl(ci->reg_addr); reg_write = (reg_read & ~ci->mask) | -- cgit v1.2.3 From ea4da3a292039d772eba32b43048fe50e7f7377b Mon Sep 17 00:00:00 2001 From: Jon Mayo Date: Fri, 17 Aug 2012 14:12:17 -0700 Subject: Revert "video: tegra: dc: fix boot issue with HDMI" This reverts commit 50fa5e50b74a0534d7524fb6d7dcaa65b2e6e74c. Change-Id: I535127153082dae5ec701bbb876af002c9ebf5a3 Signed-off-by: Jon Mayo Reviewed-on: http://git-master/r/124449 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit --- drivers/video/tegra/dc/dc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index c33858ab4588..da7f2910bb25 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -1814,8 +1814,8 @@ static int tegra_dc_probe(struct nvhost_device *ndev, mutex_lock(&dc->lock); if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED) { - _tegra_dc_set_default_videomode(dc); dc->enabled = _tegra_dc_enable(dc); + _tegra_dc_set_default_videomode(dc); } mutex_unlock(&dc->lock); @@ -1965,8 +1965,8 @@ static int tegra_dc_resume(struct nvhost_device *ndev) dc->suspended = false; if (dc->enabled) { - _tegra_dc_set_default_videomode(dc); _tegra_dc_enable(dc); + _tegra_dc_set_default_videomode(dc); } if (dc->out && dc->out->hotplug_init) -- cgit v1.2.3 From ced6edaf188e05194fc08b39ac0a89d1b56e94a5 Mon Sep 17 00:00:00 2001 From: Jon Mayo Date: Tue, 17 Jul 2012 15:56:44 -0700 Subject: video: tegra: dc: power optimize DC and host1x clk Use threaded IRQ to support enabling clocks in interrupt handling. Use io_start and io_end to hold and release host1x clock. Disable IRQ after it is first requested to balance enable/disable. Use disable_irq_nosync() anywhere dc->lock is held to avoid deadlock. Change tegra_dc_update_windows() to always be balanced with tegra_dc_sync_windows(). Sync points (from host1x) are potentially lost if clock gated after update, generally this only affects applications that update at a slow frame rate. To balance update and sync calls, Colormap/LUT code now performans a sync_windows on a LUT change, this makes LUT changes slower and take effect immediately. Add a nosync version of tegra_dc_dsi_write_data to be used within dsi module. Bug 1031933 Bug 1002768 Bug 1036025 Bug 1013506 Bug 1025621 Bug 1028716 Bug 1029041 Bug 899059 Bug 887342 Bug 929609 Change-Id: I79454e265a96df66244275c2f3b0e4949f71bd02 Signed-off-by: Jon Mayo Reviewed-on: http://git-master/r/123813 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Kevin Huang (Eng-SW) GVS: Gerrit_Virtual_Submit --- drivers/video/tegra/dc/dc.c | 140 +++++++++++++++++++++++++++------------ drivers/video/tegra/dc/dc_priv.h | 15 +++-- drivers/video/tegra/dc/dsi.c | 44 +++++++----- drivers/video/tegra/dc/hdmi.c | 32 ++++----- drivers/video/tegra/dc/lut.c | 1 + drivers/video/tegra/dc/nvsd.c | 8 +++ drivers/video/tegra/dc/rgb.c | 4 ++ drivers/video/tegra/dc/window.c | 16 ++++- 8 files changed, 177 insertions(+), 83 deletions(-) diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index da7f2910bb25..14c86b16ba23 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -134,8 +134,8 @@ static void _dump_regs(struct tegra_dc *dc, void *data, char buff[256]; mutex_lock(&dc->lock); - tegra_dc_hold_dc_out(dc); tegra_dc_io_start(dc); + tegra_dc_hold_dc_out(dc); DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0); DUMP_REG(DC_CMD_DISPLAY_COMMAND); @@ -285,8 +285,8 @@ static void _dump_regs(struct tegra_dc *dc, void *data, DUMP_REG(DC_COM_PM1_DUTY_CYCLE); DUMP_REG(DC_DISP_SD_CONTROL); - tegra_dc_io_end(dc); tegra_dc_release_dc_out(dc); + tegra_dc_io_end(dc); mutex_unlock(&dc->lock); } @@ -503,11 +503,13 @@ int tegra_dc_get_stride(struct tegra_dc *dc, unsigned win) return 0; BUG_ON(win > DC_N_WINDOWS); mutex_lock(&dc->lock); + tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); tegra_dc_writel(dc, WINDOW_A_SELECT << win, DC_CMD_DISPLAY_WINDOW_HEADER); stride = tegra_dc_readl(dc, DC_WIN_LINE_STRIDE); tegra_dc_release_dc_out(dc); + tegra_dc_io_end(dc); mutex_unlock(&dc->lock); return GET_LINE_STRIDE(stride); } @@ -556,6 +558,7 @@ static void tegra_dc_set_scaling_filter(struct tegra_dc *dc) unsigned i; unsigned v0 = 128; unsigned v1 = 0; + /* linear horizontal and vertical filters */ for (i = 0; i < 16; i++) { tegra_dc_writel(dc, (v1 << 16) | (v0 << 8), @@ -568,9 +571,11 @@ static void tegra_dc_set_scaling_filter(struct tegra_dc *dc) } } -static inline void disable_dc_irq(unsigned int irq) +/* disable_irq() blocks until handler completes, calling this function while + * holding dc->lock can deadlock. */ +static inline void disable_dc_irq(const struct tegra_dc *dc) { - disable_irq(irq); + disable_irq(dc->irq); } u32 tegra_dc_get_syncpt_id(const struct tegra_dc *dc, int i) @@ -584,11 +589,13 @@ u32 tegra_dc_incr_syncpt_max(struct tegra_dc *dc, int i) u32 max; mutex_lock(&dc->lock); + tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); max = nvhost_syncpt_incr_max_ext(dc->ndev, dc->syncpt[i].id, ((dc->enabled) ? 1 : 0)); dc->syncpt[i].max = max; tegra_dc_release_dc_out(dc); + tegra_dc_io_end(dc); mutex_unlock(&dc->lock); return max; @@ -598,12 +605,14 @@ void tegra_dc_incr_syncpt_min(struct tegra_dc *dc, int i, u32 val) { mutex_lock(&dc->lock); if (dc->enabled) { + tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); while (dc->syncpt[i].min < val) { dc->syncpt[i].min++; nvhost_syncpt_cpu_incr_ext(dc->ndev, dc->syncpt[i].id); } tegra_dc_release_dc_out(dc); + tegra_dc_io_end(dc); } mutex_unlock(&dc->lock); } @@ -621,6 +630,7 @@ tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg) return; } + tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); ctrl = ((cfg->period << PM_PERIOD_SHIFT) | @@ -656,6 +666,7 @@ tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg) } tegra_dc_writel(dc, cmd_state, DC_CMD_STATE_ACCESS); tegra_dc_release_dc_out(dc); + tegra_dc_io_end(dc); mutex_unlock(&dc->lock); } EXPORT_SYMBOL(tegra_dc_config_pwm); @@ -804,8 +815,8 @@ void tegra_dc_enable_crc(struct tegra_dc *dc) u32 val; mutex_lock(&dc->lock); - tegra_dc_hold_dc_out(dc); tegra_dc_io_start(dc); + tegra_dc_hold_dc_out(dc); val = CRC_ALWAYS_ENABLE | CRC_INPUT_DATA_ACTIVE_DATA | CRC_ENABLE_ENABLE; @@ -813,19 +824,21 @@ void tegra_dc_enable_crc(struct tegra_dc *dc) tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL); tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); tegra_dc_release_dc_out(dc); + tegra_dc_io_end(dc); mutex_unlock(&dc->lock); } void tegra_dc_disable_crc(struct tegra_dc *dc) { mutex_lock(&dc->lock); + tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); tegra_dc_writel(dc, 0x0, DC_COM_CRC_CONTROL); tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL); tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); - tegra_dc_io_end(dc); tegra_dc_release_dc_out(dc); + tegra_dc_io_end(dc); mutex_unlock(&dc->lock); } @@ -843,9 +856,11 @@ u32 tegra_dc_read_checksum_latched(struct tegra_dc *dc) mdelay(TEGRA_CRC_LATCHED_DELAY); mutex_lock(&dc->lock); + tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); crc = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM_LATCHED); tegra_dc_release_dc_out(dc); + tegra_dc_io_end(dc); mutex_unlock(&dc->lock); crc_error: return crc; @@ -863,13 +878,13 @@ static bool tegra_dc_windows_are_dirty(struct tegra_dc *dc) return false; } -static inline void enable_dc_irq(unsigned int irq) +static inline void enable_dc_irq(const struct tegra_dc *dc) { #ifndef CONFIG_TEGRA_FPGA_PLATFORM - enable_irq(irq); + enable_irq(dc->irq); #else /* Always disable DC interrupts on FPGA. */ - disable_irq(irq); + disable_irq(dc->irq); #endif } @@ -885,6 +900,7 @@ static void tegra_dc_vblank(struct work_struct *work) return; } + tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); /* use the new frame's bandwidth setting instead of max(current, new), * skip this if we're using tegra_dc_one_shot_worker() */ @@ -913,6 +929,7 @@ static void tegra_dc_vblank(struct work_struct *work) tegra_dc_mask_interrupt(dc, V_BLANK_INT); tegra_dc_release_dc_out(dc); + tegra_dc_io_end(dc); mutex_unlock(&dc->lock); /* Do the actual brightness update outside of the mutex */ @@ -935,8 +952,11 @@ static void tegra_dc_one_shot_worker(struct work_struct *work) /* memory client has gone idle */ tegra_dc_clear_bandwidth(dc); - if (dc->out_ops->idle) + if (dc->out_ops->idle) { + tegra_dc_io_start(dc); dc->out_ops->idle(dc); + tegra_dc_io_end(dc); + } mutex_unlock(&dc->lock); } @@ -946,13 +966,13 @@ static void tegra_dc_one_shot_worker(struct work_struct *work) static u64 tegra_dc_underflow_count(struct tegra_dc *dc, unsigned reg) { unsigned count = tegra_dc_readl(dc, reg); + tegra_dc_writel(dc, 0, reg); return ((count & 0x80000000) == 0) ? count : 10000000000ll; } static void tegra_dc_underflow_handler(struct tegra_dc *dc) { - u32 val; int i; dc->stats.underflows++; @@ -1015,8 +1035,7 @@ static void tegra_dc_underflow_handler(struct tegra_dc *dc) /* Clear the underflow mask now that we've checked it. */ tegra_dc_writel(dc, dc->underflow_mask, DC_CMD_INT_STATUS); dc->underflow_mask = 0; - val = tegra_dc_readl(dc, DC_CMD_INT_MASK); - tegra_dc_writel(dc, val | ALL_UF_INT, DC_CMD_INT_MASK); + tegra_dc_unmask_interrupt(dc, ALL_UF_INT); print_underflow_info(dc); } @@ -1062,12 +1081,19 @@ static irqreturn_t tegra_dc_irq(int irq, void *ptr) unsigned long underflow_mask; u32 val; + mutex_lock(&dc->lock); + clk_enable(dc->clk); + tegra_dc_io_start(dc); + tegra_dc_hold_dc_out(dc); + if (!nvhost_module_powered_ext(nvhost_get_parent(dc->ndev))) { WARN(1, "IRQ when DC not powered!\n"); - tegra_dc_io_start(dc); status = tegra_dc_readl(dc, DC_CMD_INT_STATUS); tegra_dc_writel(dc, status, DC_CMD_INT_STATUS); + tegra_dc_release_dc_out(dc); tegra_dc_io_end(dc); + clk_disable(dc->clk); + mutex_unlock(&dc->lock); return IRQ_HANDLED; } @@ -1097,6 +1123,11 @@ static irqreturn_t tegra_dc_irq(int irq, void *ptr) else tegra_dc_continuous_irq(dc, status); + tegra_dc_release_dc_out(dc); + tegra_dc_io_end(dc); + clk_disable(dc->clk); + mutex_unlock(&dc->lock); + return IRQ_HANDLED; #else /* CONFIG_TEGRA_FPGA_PLATFORM */ return IRQ_NONE; @@ -1215,6 +1246,7 @@ static int tegra_dc_init(struct tegra_dc *dc) { int i; + tegra_dc_io_start(dc); tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL); if (dc->ndev->id == 0) { tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0A, @@ -1277,14 +1309,19 @@ static int tegra_dc_init(struct tegra_dc *dc) print_mode_info(dc, dc->mode); - if (dc->mode.pclk) - if (tegra_dc_program_mode(dc, &dc->mode)) + if (dc->mode.pclk) { + if (tegra_dc_program_mode(dc, &dc->mode)) { + tegra_dc_io_end(dc); return -EINVAL; + } + } /* Initialize SD AFTER the modeset. nvsd_init handles the sd_settings = NULL case. */ nvsd_init(dc, dc->out->sd_settings); + tegra_dc_io_end(dc); + return 0; } @@ -1297,20 +1334,22 @@ static bool _tegra_dc_controller_enable(struct tegra_dc *dc) tegra_dc_setup_clk(dc, dc->clk); tegra_dc_clk_enable(dc); + tegra_dc_io_start(dc); /* do not accept interrupts during initialization */ tegra_dc_writel(dc, 0, DC_CMD_INT_MASK); - enable_dc_irq(dc->irq); + enable_dc_irq(dc); failed_init = tegra_dc_init(dc); if (failed_init) { tegra_dc_writel(dc, 0, DC_CMD_INT_MASK); - disable_irq(dc->irq); + disable_irq_nosync(dc->irq); tegra_dc_clear_bandwidth(dc); tegra_dc_clk_disable(dc); if (dc->out && dc->out->disable) dc->out->disable(); + tegra_dc_io_end(dc); return false; } @@ -1330,6 +1369,7 @@ static bool _tegra_dc_controller_enable(struct tegra_dc *dc) if (dc->out->postpoweron) dc->out->postpoweron(); + tegra_dc_io_end(dc); return true; } @@ -1346,10 +1386,10 @@ static bool _tegra_dc_controller_reset_enable(struct tegra_dc *dc) if (dc->ndev->id == 0 && tegra_dcs[1] != NULL) { mutex_lock(&tegra_dcs[1]->lock); - disable_irq(tegra_dcs[1]->irq); + disable_irq_nosync(tegra_dcs[1]->irq); } else if (dc->ndev->id == 1 && tegra_dcs[0] != NULL) { mutex_lock(&tegra_dcs[0]->lock); - disable_irq(tegra_dcs[0]->irq); + disable_irq_nosync(tegra_dcs[0]->irq); } msleep(5); @@ -1361,14 +1401,14 @@ static bool _tegra_dc_controller_reset_enable(struct tegra_dc *dc) #endif if (dc->ndev->id == 0 && tegra_dcs[1] != NULL) { - enable_dc_irq(tegra_dcs[1]->irq); + enable_dc_irq(tegra_dcs[1]); mutex_unlock(&tegra_dcs[1]->lock); } else if (dc->ndev->id == 1 && tegra_dcs[0] != NULL) { - enable_dc_irq(tegra_dcs[0]->irq); + enable_dc_irq(tegra_dcs[0]); mutex_unlock(&tegra_dcs[0]->lock); } - enable_dc_irq(dc->irq); + enable_dc_irq(dc); if (tegra_dc_init(dc)) { dev_err(&dc->ndev->dev, "cannot initialize\n"); @@ -1426,16 +1466,16 @@ static int _tegra_dc_set_default_videomode(struct tegra_dc *dc) static bool _tegra_dc_enable(struct tegra_dc *dc) { + if (dc->enabled) + return true; + if (dc->mode.pclk == 0) return false; if (!dc->out) return false; - tegra_dc_io_start(dc); - if (!_tegra_dc_controller_enable(dc)) { - tegra_dc_io_end(dc); return false; } return true; @@ -1456,6 +1496,8 @@ static void _tegra_dc_controller_disable(struct tegra_dc *dc) { unsigned i; + tegra_dc_hold_dc_out(dc); + if (dc->out && dc->out->prepoweroff) dc->out->prepoweroff(); @@ -1463,11 +1505,14 @@ static void _tegra_dc_controller_disable(struct tegra_dc *dc) dc->out_ops->disable(dc); tegra_dc_writel(dc, 0, DC_CMD_INT_MASK); - tegra_dc_writel(dc, 0, DC_CMD_INT_ENABLE); - disable_irq(dc->irq); + + disable_irq_nosync(dc->irq); tegra_dc_clear_bandwidth(dc); - tegra_dc_clk_disable(dc); + if (dc->out_ops->release) /* ugly hack */ + tegra_dc_release_dc_out(dc); + else + tegra_dc_clk_disable(dc); if (dc->out && dc->out->disable) dc->out->disable(); @@ -1548,13 +1593,10 @@ static void _tegra_dc_disable(struct tegra_dc *dc) cancel_delayed_work_sync(&dc->one_shot_work); } - tegra_dc_hold_dc_out(dc); - + tegra_dc_io_start(dc); _tegra_dc_controller_disable(dc); tegra_dc_io_end(dc); - tegra_dc_release_dc_out(dc); - if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) mutex_unlock(&dc->one_shot_lock); } @@ -1581,6 +1623,7 @@ void tegra_dc_disable(struct tegra_dc *dc) #endif mutex_unlock(&dc->lock); + synchronize_irq(dc->irq); print_mode_info(dc, dc->mode); } @@ -1646,12 +1689,14 @@ static void tegra_dc_underflow_worker(struct work_struct *work) to_delayed_work(work), struct tegra_dc, underflow_work); mutex_lock(&dc->lock); + tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); if (dc->enabled) { tegra_dc_underflow_handler(dc); } tegra_dc_release_dc_out(dc); + tegra_dc_io_end(dc); mutex_unlock(&dc->lock); } @@ -1812,20 +1857,21 @@ static int tegra_dc_probe(struct nvhost_device *ndev, dc->ext = NULL; } - mutex_lock(&dc->lock); - if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED) { - dc->enabled = _tegra_dc_enable(dc); - _tegra_dc_set_default_videomode(dc); - } - mutex_unlock(&dc->lock); - /* interrupt handler must be registered before tegra_fb_register() */ - if (request_irq(irq, tegra_dc_irq, 0, + if (request_threaded_irq(irq, NULL, tegra_dc_irq, IRQF_ONESHOT, dev_name(&ndev->dev), dc)) { dev_err(&ndev->dev, "request_irq %d failed\n", irq); ret = -EBUSY; goto err_put_emc_clk; } + disable_dc_irq(dc); + + mutex_lock(&dc->lock); + if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED) { + _tegra_dc_set_default_videomode(dc); + dc->enabled = _tegra_dc_enable(dc); + } + mutex_unlock(&dc->lock); tegra_dc_create_debugfs(dc); @@ -1849,9 +1895,11 @@ static int tegra_dc_probe(struct nvhost_device *ndev, dc->pdata->fb->yres = mode->v_active; } + tegra_dc_io_start(dc); dc->fb = tegra_fb_register(ndev, dc, dc->pdata->fb, fb_mem); if (IS_ERR_OR_NULL(dc->fb)) dc->fb = NULL; + tegra_dc_io_end(dc); } if (dc->out && dc->out->hotplug_init) @@ -1902,8 +1950,12 @@ static int tegra_dc_remove(struct nvhost_device *ndev) if (dc->ext) tegra_dc_ext_unregister(dc->ext); + mutex_lock(&dc->lock); if (dc->enabled) _tegra_dc_disable(dc); + dc->enabled = false; + mutex_unlock(&dc->lock); + synchronize_irq(dc->irq); /* wait for IRQ handlers to finish */ #ifdef CONFIG_SWITCH switch_dev_unregister(&dc->modeset_switch); @@ -1930,6 +1982,7 @@ static int tegra_dc_suspend(struct nvhost_device *ndev, pm_message_t state) tegra_dc_ext_disable(dc->ext); mutex_lock(&dc->lock); + tegra_dc_io_start(dc); if (dc->out_ops && dc->out_ops->suspend) dc->out_ops->suspend(dc); @@ -1949,7 +2002,9 @@ static int tegra_dc_suspend(struct nvhost_device *ndev, pm_message_t state) msleep(100); } + tegra_dc_io_end(dc); mutex_unlock(&dc->lock); + synchronize_irq(dc->irq); /* wait for IRQ handlers to finish */ return 0; } @@ -1965,8 +2020,9 @@ static int tegra_dc_resume(struct nvhost_device *ndev) dc->suspended = false; if (dc->enabled) { - _tegra_dc_enable(dc); + dc->enabled = false; _tegra_dc_set_default_videomode(dc); + dc->enabled = _tegra_dc_enable(dc); } if (dc->out && dc->out->hotplug_init) diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h index 759d64da7052..75211584157a 100644 --- a/drivers/video/tegra/dc/dc_priv.h +++ b/drivers/video/tegra/dc/dc_priv.h @@ -325,21 +325,26 @@ static inline bool tegra_dc_is_yuv_planar(int fmt) return false; } -static inline void tegra_dc_unmask_interrupt(struct tegra_dc *dc, u32 int_val) +static inline u32 tegra_dc_unmask_interrupt(struct tegra_dc *dc, u32 int_val) { u32 val; val = tegra_dc_readl(dc, DC_CMD_INT_MASK); - val |= int_val; - tegra_dc_writel(dc, val, DC_CMD_INT_MASK); + tegra_dc_writel(dc, val | int_val, DC_CMD_INT_MASK); + return val; } -static inline void tegra_dc_mask_interrupt(struct tegra_dc *dc, u32 int_val) +static inline u32 tegra_dc_mask_interrupt(struct tegra_dc *dc, u32 int_val) { u32 val; val = tegra_dc_readl(dc, DC_CMD_INT_MASK); - val &= ~int_val; + tegra_dc_writel(dc, val & ~int_val, DC_CMD_INT_MASK); + return val; +} + +static inline void tegra_dc_restore_interrupt(struct tegra_dc *dc, u32 val) +{ tegra_dc_writel(dc, val, DC_CMD_INT_MASK); } diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c index 4a9e507bcdb9..f60184bdd42c 100644 --- a/drivers/video/tegra/dc/dsi.c +++ b/drivers/video/tegra/dc/dsi.c @@ -1391,8 +1391,7 @@ static void tegra_dsi_stop_dc_stream_at_frame_end(struct tegra_dc *dc, INIT_COMPLETION(dc->frame_end_complete); /* unmask frame end interrupt */ - val = tegra_dc_readl(dc, DC_CMD_INT_MASK); - tegra_dc_writel(dc, val | FRAME_END_INT, DC_CMD_INT_MASK); + val = tegra_dc_unmask_interrupt(dc, FRAME_END_INT); tegra_dsi_stop_dc_stream(dc, dsi); @@ -1412,7 +1411,7 @@ static void tegra_dsi_stop_dc_stream_at_frame_end(struct tegra_dc *dc, tegra_dsi_soft_reset(dsi); /* reinstate interrupt mask */ - tegra_dc_writel(dc, val, DC_CMD_INT_MASK); + tegra_dc_restore_interrupt(dc, val); /* potentially a race? */ if (timeout == 0) dev_warn(&dc->ndev->dev, @@ -2142,15 +2141,13 @@ static void tegra_dc_dsi_idle(struct tegra_dc *dc) tegra_dsi_host_suspend(dc); } -int tegra_dsi_write_data(struct tegra_dc *dc, +static int tegra_dsi_write_data_nosync(struct tegra_dc *dc, struct tegra_dc_dsi_data *dsi, u8 *pdata, u8 data_id, u16 data_len) { int err = 0; struct dsi_status *init_status; - tegra_dc_io_start(dc); - init_status = tegra_dsi_prepare_host_transmission( dc, dsi, DSI_LP_OP_WRITE); if (IS_ERR_OR_NULL(init_status)) { @@ -2164,10 +2161,27 @@ fail: err = tegra_dsi_restore_state(dc, dsi, init_status); if (err < 0) dev_err(&dc->ndev->dev, "Failed to restore prev state\n"); + + return err; +} + +int tegra_dsi_write_data(struct tegra_dc *dc, + struct tegra_dc_dsi_data *dsi, + u8 *pdata, u8 data_id, u16 data_len) +{ + int err; + + tegra_dc_io_start(dc); + tegra_dc_dsi_hold_host(dc); + + err = tegra_dsi_write_data_nosync(dc, dsi, pdata, data_id, data_len); + + tegra_dc_dsi_release_host(dc); tegra_dc_io_end(dc); return err; } + EXPORT_SYMBOL(tegra_dsi_write_data); static int tegra_dsi_send_panel_cmd(struct tegra_dc *dc, @@ -2186,7 +2200,7 @@ static int tegra_dsi_send_panel_cmd(struct tegra_dc *dc, if (cur_cmd->cmd_type == TEGRA_DSI_DELAY_MS) mdelay(cur_cmd->sp_len_dly.delay_ms); else { - err = tegra_dsi_write_data(dc, dsi, + err = tegra_dsi_write_data_nosync(dc, dsi, cur_cmd->pdata, cur_cmd->data_id, cur_cmd->sp_len_dly.data_len); @@ -2311,9 +2325,8 @@ int tegra_dsi_start_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi, return -EINVAL; mutex_lock(&dsi->lock); - tegra_dc_dsi_hold_host(dc); - tegra_dc_io_start(dc); + tegra_dc_dsi_hold_host(dc); err = tegra_dsi_dcs_pkt_seq_ctrl_init(dsi, cmd); @@ -2334,8 +2347,8 @@ int tegra_dsi_start_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi, tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_CONTROL); fail: - tegra_dc_io_end(dc); tegra_dc_dsi_release_host(dc); + tegra_dc_io_end(dc); mutex_unlock(&dsi->lock); return err; @@ -2350,9 +2363,8 @@ void tegra_dsi_stop_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi) u32 cnt; mutex_lock(&dsi->lock); - tegra_dc_dsi_hold_host(dc); - tegra_dc_io_start(dc); + tegra_dc_dsi_hold_host(dc); tegra_dsi_writel(dsi, TEGRA_DSI_DISABLE, DSI_INIT_SEQ_CONTROL); @@ -2360,9 +2372,9 @@ void tegra_dsi_stop_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi) for (cnt = 0; cnt < 8; cnt++) tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_0 + cnt); + tegra_dc_dsi_release_host(dc); tegra_dc_io_end(dc); - tegra_dc_dsi_release_host(dc); mutex_unlock(&dsi->lock); } EXPORT_SYMBOL(tegra_dsi_stop_host_cmd_v_blank_dcs); @@ -2778,9 +2790,9 @@ static void tegra_dc_dsi_enable(struct tegra_dc *dc) u32 val; mutex_lock(&dsi->lock); + tegra_dc_io_start(dc); tegra_dc_dsi_hold_host(dc); - tegra_dc_io_start(dc); /* Stop DC stream before configuring DSI registers * to avoid visible glitches on panel during transition * from bootloader to kernel driver @@ -2893,8 +2905,8 @@ static void tegra_dc_dsi_enable(struct tegra_dc *dc) if (dsi->status.driven == DSI_DRIVEN_MODE_DC) tegra_dsi_start_dc_stream(dc, dsi); fail: - tegra_dc_io_end(dc); tegra_dc_dsi_release_host(dc); + tegra_dc_io_end(dc); mutex_unlock(&dsi->lock); } @@ -3377,8 +3389,8 @@ static void tegra_dc_dsi_disable(struct tegra_dc *dc) int err; struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc); - tegra_dc_io_start(dc); mutex_lock(&dsi->lock); + tegra_dc_io_start(dc); if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE) tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi); diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c index 55d9163d4faf..9f5968f0c587 100644 --- a/drivers/video/tegra/dc/hdmi.c +++ b/drivers/video/tegra/dc/hdmi.c @@ -1462,10 +1462,7 @@ static void tegra_dc_hdmi_detect_worker(struct work_struct *work) container_of(to_delayed_work(work), struct tegra_dc_hdmi_data, work); struct tegra_dc *dc = hdmi->dc; - tegra_dc_enable(dc); - msleep(5); if (!tegra_dc_hdmi_detect(dc)) { - tegra_dc_disable(dc); tegra_fb_update_monspecs(dc->fb, NULL, NULL); dc->connected = false; @@ -1623,21 +1620,11 @@ static int tegra_dc_hdmi_init(struct tegra_dc *dc) } #endif - /* TODO: support non-hotplug */ - if (request_irq(gpio_to_irq(dc->out->hotplug_gpio), tegra_dc_hdmi_irq, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - dev_name(&dc->ndev->dev), dc)) { - dev_err(&dc->ndev->dev, "hdmi: request_irq %d failed\n", - gpio_to_irq(dc->out->hotplug_gpio)); - err = -EBUSY; - goto err_put_clock; - } - hdmi->edid = tegra_edid_create(dc->out->dcc_bus); if (IS_ERR_OR_NULL(hdmi->edid)) { dev_err(&dc->ndev->dev, "hdmi: can't create edid\n"); err = PTR_ERR(hdmi->edid); - goto err_free_irq; + goto err_put_clock; } #ifdef CONFIG_TEGRA_NVHDCP @@ -1692,14 +1679,23 @@ static int tegra_dc_hdmi_init(struct tegra_dc *dc) tegra_dc_hdmi_debug_create(hdmi); + /* TODO: support non-hotplug */ + if (request_irq(gpio_to_irq(dc->out->hotplug_gpio), tegra_dc_hdmi_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + dev_name(&dc->ndev->dev), dc)) { + dev_err(&dc->ndev->dev, "hdmi: request_irq %d failed\n", + gpio_to_irq(dc->out->hotplug_gpio)); + err = -EBUSY; + goto err_nvhdcp_destroy; + } + return 0; -#ifdef CONFIG_TEGRA_NVHDCP +err_nvhdcp_destroy: + if (hdmi->nvhdcp) + tegra_nvhdcp_destroy(hdmi->nvhdcp); err_edid_destroy: tegra_edid_destroy(hdmi->edid); -#endif -err_free_irq: - free_irq(gpio_to_irq(dc->out->hotplug_gpio), dc); err_put_clock: #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) if (!IS_ERR_OR_NULL(hdmi->hda2hdmi_clk)) diff --git a/drivers/video/tegra/dc/lut.c b/drivers/video/tegra/dc/lut.c index 7ce8fc6768a0..2dfecfcea458 100644 --- a/drivers/video/tegra/dc/lut.c +++ b/drivers/video/tegra/dc/lut.c @@ -109,6 +109,7 @@ static int tegra_dc_update_winlut(struct tegra_dc *dc, int win_idx, int fbovr) mutex_unlock(&dc->lock); tegra_dc_update_windows(&win, 1); + tegra_dc_sync_windows(&win, 1); return 0; } diff --git a/drivers/video/tegra/dc/nvsd.c b/drivers/video/tegra/dc/nvsd.c index 6e76ee0f1702..2f3343146ecc 100644 --- a/drivers/video/tegra/dc/nvsd.c +++ b/drivers/video/tegra/dc/nvsd.c @@ -174,7 +174,9 @@ static bool nvsd_phase_in_adjustments(struct tegra_dc *dc, /* Set manual k value */ man_k = SD_MAN_K_R(cur_k) | SD_MAN_K_G(cur_k) | SD_MAN_K_B(cur_k); + tegra_dc_io_start(dc); tegra_dc_writel(dc, man_k, DC_DISP_SD_MAN_K_VALUES); + tegra_dc_io_end(dc); /* Set manual brightness value */ atomic_set(sd_brightness, cur_sd_brightness); } @@ -271,6 +273,7 @@ static void nvsd_cmd_handler(struct tegra_dc_sd_settings *settings, val &= ~SD_BIN_WIDTH_MASK; val |= bw; } + tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL); nvsd_phase_in_luts(settings, dc); @@ -351,6 +354,7 @@ void nvsd_init(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings) u32 bw_idx = 0; /* TODO: check if HW says SD's available */ + tegra_dc_io_start(dc); /* If SD's not present or disabled, clear the register and return. */ if (!settings || settings->enable == 0) { /* clear the brightness val, too. */ @@ -362,6 +366,7 @@ void nvsd_init(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings) if (settings) settings->phase_settings_step = 0; tegra_dc_writel(dc, 0, DC_DISP_SD_CONTROL); + tegra_dc_io_end(dc); return; } @@ -487,6 +492,7 @@ void nvsd_init(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings) /* Finally, Write SD Control */ tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL); dev_dbg(&dc->ndev->dev, " SD_CONTROL: 0x%08x\n", val); + tegra_dc_io_end(dc); /* set the brightness pointer */ sd_brightness = settings->sd_brightness; @@ -810,9 +816,11 @@ static ssize_t nvsd_settings_store(struct kobject *kobj, return -ENODEV; } + tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); nvsd_init(dc, sd_settings); tegra_dc_release_dc_out(dc); + tegra_dc_io_end(dc); mutex_unlock(&dc->lock); diff --git a/drivers/video/tegra/dc/rgb.c b/drivers/video/tegra/dc/rgb.c index b4097d98a9ba..36dbbdf09a66 100644 --- a/drivers/video/tegra/dc/rgb.c +++ b/drivers/video/tegra/dc/rgb.c @@ -97,6 +97,7 @@ static void tegra_dc_rgb_enable(struct tegra_dc *dc) int i; u32 out_sel_pintable[ARRAY_SIZE(tegra_dc_rgb_enable_out_sel_pintable)]; + tegra_dc_io_start(dc); tegra_dc_writel(dc, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE, DC_CMD_DISPLAY_POWER_CONTROL); @@ -150,13 +151,16 @@ static void tegra_dc_rgb_enable(struct tegra_dc *dc) /* Inform DC register updated */ tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL); tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); + tegra_dc_io_end(dc); } static void tegra_dc_rgb_disable(struct tegra_dc *dc) { + tegra_dc_io_start(dc); tegra_dc_writel(dc, 0x00000000, DC_CMD_DISPLAY_POWER_CONTROL); tegra_dc_write_table(dc, tegra_dc_rgb_disable_pintable); + tegra_dc_io_end(dc); } struct tegra_dc_out_ops tegra_dc_rgb_ops = { diff --git a/drivers/video/tegra/dc/window.c b/drivers/video/tegra/dc/window.c index 0b4350d49418..48fef11b9978 100644 --- a/drivers/video/tegra/dc/window.c +++ b/drivers/video/tegra/dc/window.c @@ -31,11 +31,16 @@ static bool tegra_dc_windows_are_clean(struct tegra_dc_win *windows[], int n) { int i; + struct tegra_dc *dc = windows[0]->dc; + mutex_lock(&dc->lock); for (i = 0; i < n; i++) { - if (windows[i]->dirty) + if (windows[i]->dirty) { + mutex_unlock(&dc->lock); return false; + } } + mutex_unlock(&dc->lock); return true; } @@ -100,6 +105,7 @@ static void tegra_dc_set_blending(struct tegra_dc *dc, { unsigned long mask = BIT(DC_N_WINDOWS) - 1; + tegra_dc_io_start(dc); while (mask) { int idx = get_topmost_window(blend->z, &mask); @@ -116,6 +122,7 @@ static void tegra_dc_set_blending(struct tegra_dc *dc, tegra_dc_writel(dc, blend_3win(idx, mask, blend->flags), DC_WIN_BLEND_3WIN_XY); } + tegra_dc_io_end(dc); } /* does not support syncing windows on multiple dcs in one call */ @@ -141,6 +148,8 @@ int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n) trace_printk("%s:After wait_event_interruptible_timeout\n", windows[0]->dc->ndev->name); #endif + /* tegra_dc_io_start() done in update_windows */ + tegra_dc_io_end(windows[0]->dc); return ret; } EXPORT_SYMBOL(tegra_dc_sync_windows); @@ -192,7 +201,8 @@ static inline u32 compute_initial_dda(fixed20_12 in) return dfixed_frac(in); } -/* does not support updating windows on multiple dcs in one call */ +/* Does not support updating windows on multiple dcs in one call. + * Requires a matching sync_windows to avoid leaking ref-count on clocks. */ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n) { struct tegra_dc *dc; @@ -219,6 +229,7 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n) return -EFAULT; } + tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); if (no_vsync) @@ -424,6 +435,7 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n) trace_printk("%s:update_mask=%#lx\n", dc->ndev->name, update_mask); tegra_dc_release_dc_out(dc); + /* tegra_dc_io_end() is called in tegra_dc_sync_windows() */ mutex_unlock(&dc->lock); if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) mutex_unlock(&dc->one_shot_lock); -- cgit v1.2.3 From 4e11888615fe361083974c0a415ac27c53b02b3e Mon Sep 17 00:00:00 2001 From: Simone Willett Date: Thu, 23 Aug 2012 13:32:37 -0700 Subject: Revert "Revert "arm: tegra: la: hack latency allowance formula"" This reverts commit 6d7364b311e4de86ceed40ff438ee9549251e02e Change-Id: I5fd8e2ab5c3259f75cadf6260c59a1ca3ddc40d2 Reviewed-on: http://git-master/r/126976 Reviewed-by: Simone Willett Tested-by: Simone Willett --- arch/arm/mach-tegra/latency_allowance.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-tegra/latency_allowance.c b/arch/arm/mach-tegra/latency_allowance.c index e550cc142528..8d16d8d36661 100644 --- a/arch/arm/mach-tegra/latency_allowance.c +++ b/arch/arm/mach-tegra/latency_allowance.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/latency_allowance.c * - * Copyright (C) 2011 NVIDIA Corporation + * Copyright (C) 2011-2012, NVIDIA CORPORATION. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -100,6 +100,9 @@ printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__); \ } +/* Bug 995270 */ +#define HACK_LA_FIFO 1 + static struct dentry *latency_debug_dir; struct la_client_info { @@ -384,7 +387,9 @@ int tegra_set_latency_allowance(enum tegra_la_id id, int la_to_set; unsigned long reg_read; unsigned long reg_write; + unsigned int fifo_size_in_atoms; int bytes_per_atom = normal_atom_size; + const int fifo_scale = 4; /* 25% of the FIFO */ struct la_client_info *ci; VALIDATE_ID(id); @@ -394,11 +399,19 @@ int tegra_set_latency_allowance(enum tegra_la_id id, bytes_per_atom = fdc_atom_size; ci = &la_info[id]; + fifo_size_in_atoms = ci->fifo_size_in_atoms; + +#if HACK_LA_FIFO + /* pretend that our FIFO is only as deep as the lowest fullness + * we expect to see */ + if (id >= ID(DISPLAY_0A) && id <= ID(DISPLAY_HCB)) + fifo_size_in_atoms /= fifo_scale; +#endif if (bandwidth_in_mbps == 0) { la_to_set = MC_LA_MAX_VALUE; } else { - ideal_la = (ci->fifo_size_in_atoms * bytes_per_atom * 1000) / + ideal_la = (fifo_size_in_atoms * bytes_per_atom * 1000) / (bandwidth_in_mbps * ns_per_tick); la_to_set = ideal_la - (ci->expiration_in_ns/ns_per_tick) - 1; } @@ -409,11 +422,6 @@ int tegra_set_latency_allowance(enum tegra_la_id id, la_to_set = (la_to_set > MC_LA_MAX_VALUE) ? MC_LA_MAX_VALUE : la_to_set; scaling_info[id].actual_la_to_set = la_to_set; - /* until display can use latency allowance scaling, use a more - * aggressive LA setting. Bug 862709 */ - if (id >= ID(DISPLAY_0A) && id <= ID(DISPLAY_HCB)) - la_to_set /= 3; - spin_lock(&safety_lock); reg_read = readl(ci->reg_addr); reg_write = (reg_read & ~ci->mask) | -- cgit v1.2.3 From b34024a5f32cc51b463e767df66da30e53c460ef Mon Sep 17 00:00:00 2001 From: Matt Wagner Date: Wed, 22 Aug 2012 14:29:46 -0700 Subject: Revert "video: tegra: hdcp: Fix Locking Issue" This reverts commit 51f746421b73f8f378bd7908b35fd6c79687e239. This commit caused issues with Suspend/Resume Bug 1030468 Change-Id: I2bcf6c01e388d5ba795decd0d2da768fa541fa81 Signed-off-by: Matt Wagner Reviewed-on: http://git-master/r/125336 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Jon Mayo Reviewed-by: Bharat Nihalani --- drivers/video/tegra/dc/nvhdcp.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/video/tegra/dc/nvhdcp.c b/drivers/video/tegra/dc/nvhdcp.c index b509a6c78499..3566e2bd33b5 100644 --- a/drivers/video/tegra/dc/nvhdcp.c +++ b/drivers/video/tegra/dc/nvhdcp.c @@ -78,7 +78,6 @@ struct tegra_nvhdcp { struct tegra_dc_hdmi_data *hdmi; struct workqueue_struct *downstream_wq; struct mutex lock; - struct mutex state_lock; struct miscdevice miscdev; char name[12]; unsigned id; @@ -981,9 +980,7 @@ static void nvhdcp_downstream_worker(struct work_struct *work) nvhdcp_vdbg("CRYPT enabled\n"); - mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_LINK_VERIFY; - mutex_unlock(&nvhdcp->state_lock); nvhdcp_info("link verified!\n"); while (1) { @@ -1010,39 +1007,30 @@ failure: if(nvhdcp->fail_count > 5) { nvhdcp_err("nvhdcp failure - too many failures, giving up!\n"); } else { - if (!nvhdcp_is_plugged(nvhdcp)) { - nvhdcp_err("nvhdcp failure\n"); - goto lost_hdmi; - } nvhdcp_err("nvhdcp failure - renegotiating in 1 second\n"); + if (!nvhdcp_is_plugged(nvhdcp)) + goto lost_hdmi; queue_delayed_work(nvhdcp->downstream_wq, &nvhdcp->work, msecs_to_jiffies(1000)); } lost_hdmi: - mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_UNAUTHENTICATED; - mutex_unlock(&nvhdcp->state_lock); hdcp_ctrl_run(hdmi, 0); err: mutex_unlock(&nvhdcp->lock); return; disable: - mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_OFF; nvhdcp_set_plugged(nvhdcp, false); - mutex_unlock(&nvhdcp->state_lock); mutex_unlock(&nvhdcp->lock); return; } static int tegra_nvhdcp_on(struct tegra_nvhdcp *nvhdcp) { - mutex_lock(&nvhdcp->state_lock); - nvhdcp_set_plugged(nvhdcp, true); nvhdcp->state = STATE_UNAUTHENTICATED; - mutex_unlock(&nvhdcp->state_lock); if (nvhdcp_is_plugged(nvhdcp)) { nvhdcp->fail_count = 0; queue_delayed_work(nvhdcp->downstream_wq, &nvhdcp->work, @@ -1053,10 +1041,10 @@ static int tegra_nvhdcp_on(struct tegra_nvhdcp *nvhdcp) static int tegra_nvhdcp_off(struct tegra_nvhdcp *nvhdcp) { - mutex_lock(&nvhdcp->state_lock); + mutex_lock(&nvhdcp->lock); nvhdcp->state = STATE_OFF; nvhdcp_set_plugged(nvhdcp, false); - mutex_unlock(&nvhdcp->state_lock); + mutex_unlock(&nvhdcp->lock); wake_up_interruptible(&wq_worker); flush_workqueue(nvhdcp->downstream_wq); return 0; @@ -1067,6 +1055,7 @@ void tegra_nvhdcp_set_plug(struct tegra_nvhdcp *nvhdcp, bool hpd) nvhdcp_debug("hdmi hotplug detected (hpd = %d)\n", hpd); if (hpd) { + nvhdcp_set_plugged(nvhdcp, true); tegra_nvhdcp_on(nvhdcp); } else { tegra_nvhdcp_off(nvhdcp); @@ -1091,9 +1080,9 @@ int tegra_nvhdcp_set_policy(struct tegra_nvhdcp *nvhdcp, int pol) static int tegra_nvhdcp_renegotiate(struct tegra_nvhdcp *nvhdcp) { - mutex_lock(&nvhdcp->state_lock); + mutex_lock(&nvhdcp->lock); nvhdcp->state = STATE_RENEGOTIATE; - mutex_unlock(&nvhdcp->state_lock); + mutex_unlock(&nvhdcp->lock); tegra_nvhdcp_on(nvhdcp); return 0; } @@ -1212,7 +1201,6 @@ struct tegra_nvhdcp *tegra_nvhdcp_create(struct tegra_dc_hdmi_data *hdmi, snprintf(nvhdcp->name, sizeof(nvhdcp->name), "nvhdcp%u", id); nvhdcp->hdmi = hdmi; mutex_init(&nvhdcp->lock); - mutex_init(&nvhdcp->state_lock); strlcpy(nvhdcp->info.type, nvhdcp->name, sizeof(nvhdcp->info.type)); nvhdcp->bus = bus; @@ -1236,9 +1224,7 @@ struct tegra_nvhdcp *tegra_nvhdcp_create(struct tegra_dc_hdmi_data *hdmi, goto free_nvhdcp; } - mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_UNAUTHENTICATED; - mutex_unlock(&nvhdcp->state_lock); nvhdcp->downstream_wq = create_singlethread_workqueue(nvhdcp->name); INIT_DELAYED_WORK(&nvhdcp->work, nvhdcp_downstream_worker); -- cgit v1.2.3 From 6667859ccb945a51c93d3f282e31b9283334fa53 Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Mon, 13 Aug 2012 12:14:51 +0530 Subject: ARM: tegra: enterprise: set I2S as slave mode. Setting default I2S mode as slave. This will help in power optimization of around 4mW. Change-Id: Ic2d702c332283bd0f6c4f73615e8097fb3b16ef9 Signed-off-by: Ankit Gupta Reviewed-on: http://git-master/r/122943 (cherry picked from commit 14e3dc4ad30637bf2fd12cff78397b9f3d50198c) Reviewed-on: http://git-master/r/125181 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Chandrakanth Gorantla GVS: Gerrit_Virtual_Submit Reviewed-by: Bharat Nihalani --- arch/arm/mach-tegra/board-enterprise.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c index 2675f0f0c524..7f2cf39866db 100644 --- a/arch/arm/mach-tegra/board-enterprise.c +++ b/arch/arm/mach-tegra/board-enterprise.c @@ -514,7 +514,7 @@ static struct tegra_asoc_platform_data enterprise_audio_pdata = { /*defaults for Enterprise board*/ .i2s_param[HIFI_CODEC] = { .audio_port_id = 0, - .is_i2s_master = 1, + .is_i2s_master = 0, .i2s_mode = TEGRA_DAIFMT_I2S, .sample_size = 16, }, -- cgit v1.2.3 From 90ec2d7e47927723f8c088c178bb560828fac622 Mon Sep 17 00:00:00 2001 From: Kerwin Wan Date: Wed, 4 Jul 2012 16:20:24 +0800 Subject: arm: tegra: kai: update memory timings bug 947148 Change-Id: Icc9711e44375dee9346cbe2cb8af090286a244a2 Signed-off-by: Kerwin Wan Reviewed-on: http://git-master/r/126834 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Raymond Poudrier Reviewed-by: Bharat Nihalani Reviewed-by: Simone Willett Tested-by: Simone Willett --- arch/arm/mach-tegra/board-kai-memory.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-tegra/board-kai-memory.c b/arch/arm/mach-tegra/board-kai-memory.c index cf5daf6492eb..07d6405c7016 100644 --- a/arch/arm/mach-tegra/board-kai-memory.c +++ b/arch/arm/mach-tegra/board-kai-memory.c @@ -118,7 +118,7 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT_DURATION */ 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */ 0x00030003, /* MC_EMEM_ARB_CFG */ - 0xc0000008, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ 0x00000002, /* MC_EMEM_ARB_TIMING_RC */ @@ -238,7 +238,7 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ 0x00010003, /* MC_EMEM_ARB_CFG */ - 0xc000000a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ 0x00000002, /* MC_EMEM_ARB_TIMING_RC */ @@ -358,7 +358,7 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ 0x00000003, /* MC_EMEM_ARB_CFG */ - 0xc0000013, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0xc0000018, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ 0x00000003, /* MC_EMEM_ARB_TIMING_RC */ -- cgit v1.2.3 From bee7876186f664b3de0d828bda7d0d293a93ffb7 Mon Sep 17 00:00:00 2001 From: Peter Zu Date: Thu, 23 Aug 2012 12:13:01 -0700 Subject: Revert "video: tegra: dc: power optimize DC and host1x clk" This reverts commit ced6edaf188e05194fc08b39ac0a89d1b56e94a5. Change-Id: I0831dc5a623d8926e72f5dfef8e92b8e7dd81ea7 Signed-off-by: Peter Zu Reviewed-on: http://git-master/r/126958 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Wen Yi Reviewed-by: Jon Mayo GVS: Gerrit_Virtual_Submit --- drivers/video/tegra/dc/dc.c | 140 ++++++++++++--------------------------- drivers/video/tegra/dc/dc_priv.h | 15 ++--- drivers/video/tegra/dc/dsi.c | 44 +++++------- drivers/video/tegra/dc/hdmi.c | 32 +++++---- drivers/video/tegra/dc/lut.c | 1 - drivers/video/tegra/dc/nvsd.c | 8 --- drivers/video/tegra/dc/rgb.c | 4 -- drivers/video/tegra/dc/window.c | 16 +---- 8 files changed, 83 insertions(+), 177 deletions(-) diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index 14c86b16ba23..da7f2910bb25 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -134,8 +134,8 @@ static void _dump_regs(struct tegra_dc *dc, void *data, char buff[256]; mutex_lock(&dc->lock); - tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); + tegra_dc_io_start(dc); DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0); DUMP_REG(DC_CMD_DISPLAY_COMMAND); @@ -285,8 +285,8 @@ static void _dump_regs(struct tegra_dc *dc, void *data, DUMP_REG(DC_COM_PM1_DUTY_CYCLE); DUMP_REG(DC_DISP_SD_CONTROL); - tegra_dc_release_dc_out(dc); tegra_dc_io_end(dc); + tegra_dc_release_dc_out(dc); mutex_unlock(&dc->lock); } @@ -503,13 +503,11 @@ int tegra_dc_get_stride(struct tegra_dc *dc, unsigned win) return 0; BUG_ON(win > DC_N_WINDOWS); mutex_lock(&dc->lock); - tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); tegra_dc_writel(dc, WINDOW_A_SELECT << win, DC_CMD_DISPLAY_WINDOW_HEADER); stride = tegra_dc_readl(dc, DC_WIN_LINE_STRIDE); tegra_dc_release_dc_out(dc); - tegra_dc_io_end(dc); mutex_unlock(&dc->lock); return GET_LINE_STRIDE(stride); } @@ -558,7 +556,6 @@ static void tegra_dc_set_scaling_filter(struct tegra_dc *dc) unsigned i; unsigned v0 = 128; unsigned v1 = 0; - /* linear horizontal and vertical filters */ for (i = 0; i < 16; i++) { tegra_dc_writel(dc, (v1 << 16) | (v0 << 8), @@ -571,11 +568,9 @@ static void tegra_dc_set_scaling_filter(struct tegra_dc *dc) } } -/* disable_irq() blocks until handler completes, calling this function while - * holding dc->lock can deadlock. */ -static inline void disable_dc_irq(const struct tegra_dc *dc) +static inline void disable_dc_irq(unsigned int irq) { - disable_irq(dc->irq); + disable_irq(irq); } u32 tegra_dc_get_syncpt_id(const struct tegra_dc *dc, int i) @@ -589,13 +584,11 @@ u32 tegra_dc_incr_syncpt_max(struct tegra_dc *dc, int i) u32 max; mutex_lock(&dc->lock); - tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); max = nvhost_syncpt_incr_max_ext(dc->ndev, dc->syncpt[i].id, ((dc->enabled) ? 1 : 0)); dc->syncpt[i].max = max; tegra_dc_release_dc_out(dc); - tegra_dc_io_end(dc); mutex_unlock(&dc->lock); return max; @@ -605,14 +598,12 @@ void tegra_dc_incr_syncpt_min(struct tegra_dc *dc, int i, u32 val) { mutex_lock(&dc->lock); if (dc->enabled) { - tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); while (dc->syncpt[i].min < val) { dc->syncpt[i].min++; nvhost_syncpt_cpu_incr_ext(dc->ndev, dc->syncpt[i].id); } tegra_dc_release_dc_out(dc); - tegra_dc_io_end(dc); } mutex_unlock(&dc->lock); } @@ -630,7 +621,6 @@ tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg) return; } - tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); ctrl = ((cfg->period << PM_PERIOD_SHIFT) | @@ -666,7 +656,6 @@ tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg) } tegra_dc_writel(dc, cmd_state, DC_CMD_STATE_ACCESS); tegra_dc_release_dc_out(dc); - tegra_dc_io_end(dc); mutex_unlock(&dc->lock); } EXPORT_SYMBOL(tegra_dc_config_pwm); @@ -815,8 +804,8 @@ void tegra_dc_enable_crc(struct tegra_dc *dc) u32 val; mutex_lock(&dc->lock); - tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); + tegra_dc_io_start(dc); val = CRC_ALWAYS_ENABLE | CRC_INPUT_DATA_ACTIVE_DATA | CRC_ENABLE_ENABLE; @@ -824,21 +813,19 @@ void tegra_dc_enable_crc(struct tegra_dc *dc) tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL); tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); tegra_dc_release_dc_out(dc); - tegra_dc_io_end(dc); mutex_unlock(&dc->lock); } void tegra_dc_disable_crc(struct tegra_dc *dc) { mutex_lock(&dc->lock); - tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); tegra_dc_writel(dc, 0x0, DC_COM_CRC_CONTROL); tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL); tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); - tegra_dc_release_dc_out(dc); tegra_dc_io_end(dc); + tegra_dc_release_dc_out(dc); mutex_unlock(&dc->lock); } @@ -856,11 +843,9 @@ u32 tegra_dc_read_checksum_latched(struct tegra_dc *dc) mdelay(TEGRA_CRC_LATCHED_DELAY); mutex_lock(&dc->lock); - tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); crc = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM_LATCHED); tegra_dc_release_dc_out(dc); - tegra_dc_io_end(dc); mutex_unlock(&dc->lock); crc_error: return crc; @@ -878,13 +863,13 @@ static bool tegra_dc_windows_are_dirty(struct tegra_dc *dc) return false; } -static inline void enable_dc_irq(const struct tegra_dc *dc) +static inline void enable_dc_irq(unsigned int irq) { #ifndef CONFIG_TEGRA_FPGA_PLATFORM - enable_irq(dc->irq); + enable_irq(irq); #else /* Always disable DC interrupts on FPGA. */ - disable_irq(dc->irq); + disable_irq(irq); #endif } @@ -900,7 +885,6 @@ static void tegra_dc_vblank(struct work_struct *work) return; } - tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); /* use the new frame's bandwidth setting instead of max(current, new), * skip this if we're using tegra_dc_one_shot_worker() */ @@ -929,7 +913,6 @@ static void tegra_dc_vblank(struct work_struct *work) tegra_dc_mask_interrupt(dc, V_BLANK_INT); tegra_dc_release_dc_out(dc); - tegra_dc_io_end(dc); mutex_unlock(&dc->lock); /* Do the actual brightness update outside of the mutex */ @@ -952,11 +935,8 @@ static void tegra_dc_one_shot_worker(struct work_struct *work) /* memory client has gone idle */ tegra_dc_clear_bandwidth(dc); - if (dc->out_ops->idle) { - tegra_dc_io_start(dc); + if (dc->out_ops->idle) dc->out_ops->idle(dc); - tegra_dc_io_end(dc); - } mutex_unlock(&dc->lock); } @@ -966,13 +946,13 @@ static void tegra_dc_one_shot_worker(struct work_struct *work) static u64 tegra_dc_underflow_count(struct tegra_dc *dc, unsigned reg) { unsigned count = tegra_dc_readl(dc, reg); - tegra_dc_writel(dc, 0, reg); return ((count & 0x80000000) == 0) ? count : 10000000000ll; } static void tegra_dc_underflow_handler(struct tegra_dc *dc) { + u32 val; int i; dc->stats.underflows++; @@ -1035,7 +1015,8 @@ static void tegra_dc_underflow_handler(struct tegra_dc *dc) /* Clear the underflow mask now that we've checked it. */ tegra_dc_writel(dc, dc->underflow_mask, DC_CMD_INT_STATUS); dc->underflow_mask = 0; - tegra_dc_unmask_interrupt(dc, ALL_UF_INT); + val = tegra_dc_readl(dc, DC_CMD_INT_MASK); + tegra_dc_writel(dc, val | ALL_UF_INT, DC_CMD_INT_MASK); print_underflow_info(dc); } @@ -1081,19 +1062,12 @@ static irqreturn_t tegra_dc_irq(int irq, void *ptr) unsigned long underflow_mask; u32 val; - mutex_lock(&dc->lock); - clk_enable(dc->clk); - tegra_dc_io_start(dc); - tegra_dc_hold_dc_out(dc); - if (!nvhost_module_powered_ext(nvhost_get_parent(dc->ndev))) { WARN(1, "IRQ when DC not powered!\n"); + tegra_dc_io_start(dc); status = tegra_dc_readl(dc, DC_CMD_INT_STATUS); tegra_dc_writel(dc, status, DC_CMD_INT_STATUS); - tegra_dc_release_dc_out(dc); tegra_dc_io_end(dc); - clk_disable(dc->clk); - mutex_unlock(&dc->lock); return IRQ_HANDLED; } @@ -1123,11 +1097,6 @@ static irqreturn_t tegra_dc_irq(int irq, void *ptr) else tegra_dc_continuous_irq(dc, status); - tegra_dc_release_dc_out(dc); - tegra_dc_io_end(dc); - clk_disable(dc->clk); - mutex_unlock(&dc->lock); - return IRQ_HANDLED; #else /* CONFIG_TEGRA_FPGA_PLATFORM */ return IRQ_NONE; @@ -1246,7 +1215,6 @@ static int tegra_dc_init(struct tegra_dc *dc) { int i; - tegra_dc_io_start(dc); tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL); if (dc->ndev->id == 0) { tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0A, @@ -1309,19 +1277,14 @@ static int tegra_dc_init(struct tegra_dc *dc) print_mode_info(dc, dc->mode); - if (dc->mode.pclk) { - if (tegra_dc_program_mode(dc, &dc->mode)) { - tegra_dc_io_end(dc); + if (dc->mode.pclk) + if (tegra_dc_program_mode(dc, &dc->mode)) return -EINVAL; - } - } /* Initialize SD AFTER the modeset. nvsd_init handles the sd_settings = NULL case. */ nvsd_init(dc, dc->out->sd_settings); - tegra_dc_io_end(dc); - return 0; } @@ -1334,22 +1297,20 @@ static bool _tegra_dc_controller_enable(struct tegra_dc *dc) tegra_dc_setup_clk(dc, dc->clk); tegra_dc_clk_enable(dc); - tegra_dc_io_start(dc); /* do not accept interrupts during initialization */ tegra_dc_writel(dc, 0, DC_CMD_INT_MASK); - enable_dc_irq(dc); + enable_dc_irq(dc->irq); failed_init = tegra_dc_init(dc); if (failed_init) { tegra_dc_writel(dc, 0, DC_CMD_INT_MASK); - disable_irq_nosync(dc->irq); + disable_irq(dc->irq); tegra_dc_clear_bandwidth(dc); tegra_dc_clk_disable(dc); if (dc->out && dc->out->disable) dc->out->disable(); - tegra_dc_io_end(dc); return false; } @@ -1369,7 +1330,6 @@ static bool _tegra_dc_controller_enable(struct tegra_dc *dc) if (dc->out->postpoweron) dc->out->postpoweron(); - tegra_dc_io_end(dc); return true; } @@ -1386,10 +1346,10 @@ static bool _tegra_dc_controller_reset_enable(struct tegra_dc *dc) if (dc->ndev->id == 0 && tegra_dcs[1] != NULL) { mutex_lock(&tegra_dcs[1]->lock); - disable_irq_nosync(tegra_dcs[1]->irq); + disable_irq(tegra_dcs[1]->irq); } else if (dc->ndev->id == 1 && tegra_dcs[0] != NULL) { mutex_lock(&tegra_dcs[0]->lock); - disable_irq_nosync(tegra_dcs[0]->irq); + disable_irq(tegra_dcs[0]->irq); } msleep(5); @@ -1401,14 +1361,14 @@ static bool _tegra_dc_controller_reset_enable(struct tegra_dc *dc) #endif if (dc->ndev->id == 0 && tegra_dcs[1] != NULL) { - enable_dc_irq(tegra_dcs[1]); + enable_dc_irq(tegra_dcs[1]->irq); mutex_unlock(&tegra_dcs[1]->lock); } else if (dc->ndev->id == 1 && tegra_dcs[0] != NULL) { - enable_dc_irq(tegra_dcs[0]); + enable_dc_irq(tegra_dcs[0]->irq); mutex_unlock(&tegra_dcs[0]->lock); } - enable_dc_irq(dc); + enable_dc_irq(dc->irq); if (tegra_dc_init(dc)) { dev_err(&dc->ndev->dev, "cannot initialize\n"); @@ -1466,16 +1426,16 @@ static int _tegra_dc_set_default_videomode(struct tegra_dc *dc) static bool _tegra_dc_enable(struct tegra_dc *dc) { - if (dc->enabled) - return true; - if (dc->mode.pclk == 0) return false; if (!dc->out) return false; + tegra_dc_io_start(dc); + if (!_tegra_dc_controller_enable(dc)) { + tegra_dc_io_end(dc); return false; } return true; @@ -1496,8 +1456,6 @@ static void _tegra_dc_controller_disable(struct tegra_dc *dc) { unsigned i; - tegra_dc_hold_dc_out(dc); - if (dc->out && dc->out->prepoweroff) dc->out->prepoweroff(); @@ -1505,14 +1463,11 @@ static void _tegra_dc_controller_disable(struct tegra_dc *dc) dc->out_ops->disable(dc); tegra_dc_writel(dc, 0, DC_CMD_INT_MASK); - - disable_irq_nosync(dc->irq); + tegra_dc_writel(dc, 0, DC_CMD_INT_ENABLE); + disable_irq(dc->irq); tegra_dc_clear_bandwidth(dc); - if (dc->out_ops->release) /* ugly hack */ - tegra_dc_release_dc_out(dc); - else - tegra_dc_clk_disable(dc); + tegra_dc_clk_disable(dc); if (dc->out && dc->out->disable) dc->out->disable(); @@ -1593,10 +1548,13 @@ static void _tegra_dc_disable(struct tegra_dc *dc) cancel_delayed_work_sync(&dc->one_shot_work); } - tegra_dc_io_start(dc); + tegra_dc_hold_dc_out(dc); + _tegra_dc_controller_disable(dc); tegra_dc_io_end(dc); + tegra_dc_release_dc_out(dc); + if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) mutex_unlock(&dc->one_shot_lock); } @@ -1623,7 +1581,6 @@ void tegra_dc_disable(struct tegra_dc *dc) #endif mutex_unlock(&dc->lock); - synchronize_irq(dc->irq); print_mode_info(dc, dc->mode); } @@ -1689,14 +1646,12 @@ static void tegra_dc_underflow_worker(struct work_struct *work) to_delayed_work(work), struct tegra_dc, underflow_work); mutex_lock(&dc->lock); - tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); if (dc->enabled) { tegra_dc_underflow_handler(dc); } tegra_dc_release_dc_out(dc); - tegra_dc_io_end(dc); mutex_unlock(&dc->lock); } @@ -1857,21 +1812,20 @@ static int tegra_dc_probe(struct nvhost_device *ndev, dc->ext = NULL; } + mutex_lock(&dc->lock); + if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED) { + dc->enabled = _tegra_dc_enable(dc); + _tegra_dc_set_default_videomode(dc); + } + mutex_unlock(&dc->lock); + /* interrupt handler must be registered before tegra_fb_register() */ - if (request_threaded_irq(irq, NULL, tegra_dc_irq, IRQF_ONESHOT, + if (request_irq(irq, tegra_dc_irq, 0, dev_name(&ndev->dev), dc)) { dev_err(&ndev->dev, "request_irq %d failed\n", irq); ret = -EBUSY; goto err_put_emc_clk; } - disable_dc_irq(dc); - - mutex_lock(&dc->lock); - if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED) { - _tegra_dc_set_default_videomode(dc); - dc->enabled = _tegra_dc_enable(dc); - } - mutex_unlock(&dc->lock); tegra_dc_create_debugfs(dc); @@ -1895,11 +1849,9 @@ static int tegra_dc_probe(struct nvhost_device *ndev, dc->pdata->fb->yres = mode->v_active; } - tegra_dc_io_start(dc); dc->fb = tegra_fb_register(ndev, dc, dc->pdata->fb, fb_mem); if (IS_ERR_OR_NULL(dc->fb)) dc->fb = NULL; - tegra_dc_io_end(dc); } if (dc->out && dc->out->hotplug_init) @@ -1950,12 +1902,8 @@ static int tegra_dc_remove(struct nvhost_device *ndev) if (dc->ext) tegra_dc_ext_unregister(dc->ext); - mutex_lock(&dc->lock); if (dc->enabled) _tegra_dc_disable(dc); - dc->enabled = false; - mutex_unlock(&dc->lock); - synchronize_irq(dc->irq); /* wait for IRQ handlers to finish */ #ifdef CONFIG_SWITCH switch_dev_unregister(&dc->modeset_switch); @@ -1982,7 +1930,6 @@ static int tegra_dc_suspend(struct nvhost_device *ndev, pm_message_t state) tegra_dc_ext_disable(dc->ext); mutex_lock(&dc->lock); - tegra_dc_io_start(dc); if (dc->out_ops && dc->out_ops->suspend) dc->out_ops->suspend(dc); @@ -2002,9 +1949,7 @@ static int tegra_dc_suspend(struct nvhost_device *ndev, pm_message_t state) msleep(100); } - tegra_dc_io_end(dc); mutex_unlock(&dc->lock); - synchronize_irq(dc->irq); /* wait for IRQ handlers to finish */ return 0; } @@ -2020,9 +1965,8 @@ static int tegra_dc_resume(struct nvhost_device *ndev) dc->suspended = false; if (dc->enabled) { - dc->enabled = false; + _tegra_dc_enable(dc); _tegra_dc_set_default_videomode(dc); - dc->enabled = _tegra_dc_enable(dc); } if (dc->out && dc->out->hotplug_init) diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h index 75211584157a..759d64da7052 100644 --- a/drivers/video/tegra/dc/dc_priv.h +++ b/drivers/video/tegra/dc/dc_priv.h @@ -325,26 +325,21 @@ static inline bool tegra_dc_is_yuv_planar(int fmt) return false; } -static inline u32 tegra_dc_unmask_interrupt(struct tegra_dc *dc, u32 int_val) +static inline void tegra_dc_unmask_interrupt(struct tegra_dc *dc, u32 int_val) { u32 val; val = tegra_dc_readl(dc, DC_CMD_INT_MASK); - tegra_dc_writel(dc, val | int_val, DC_CMD_INT_MASK); - return val; + val |= int_val; + tegra_dc_writel(dc, val, DC_CMD_INT_MASK); } -static inline u32 tegra_dc_mask_interrupt(struct tegra_dc *dc, u32 int_val) +static inline void tegra_dc_mask_interrupt(struct tegra_dc *dc, u32 int_val) { u32 val; val = tegra_dc_readl(dc, DC_CMD_INT_MASK); - tegra_dc_writel(dc, val & ~int_val, DC_CMD_INT_MASK); - return val; -} - -static inline void tegra_dc_restore_interrupt(struct tegra_dc *dc, u32 val) -{ + val &= ~int_val; tegra_dc_writel(dc, val, DC_CMD_INT_MASK); } diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c index f60184bdd42c..4a9e507bcdb9 100644 --- a/drivers/video/tegra/dc/dsi.c +++ b/drivers/video/tegra/dc/dsi.c @@ -1391,7 +1391,8 @@ static void tegra_dsi_stop_dc_stream_at_frame_end(struct tegra_dc *dc, INIT_COMPLETION(dc->frame_end_complete); /* unmask frame end interrupt */ - val = tegra_dc_unmask_interrupt(dc, FRAME_END_INT); + val = tegra_dc_readl(dc, DC_CMD_INT_MASK); + tegra_dc_writel(dc, val | FRAME_END_INT, DC_CMD_INT_MASK); tegra_dsi_stop_dc_stream(dc, dsi); @@ -1411,7 +1412,7 @@ static void tegra_dsi_stop_dc_stream_at_frame_end(struct tegra_dc *dc, tegra_dsi_soft_reset(dsi); /* reinstate interrupt mask */ - tegra_dc_restore_interrupt(dc, val); /* potentially a race? */ + tegra_dc_writel(dc, val, DC_CMD_INT_MASK); if (timeout == 0) dev_warn(&dc->ndev->dev, @@ -2141,13 +2142,15 @@ static void tegra_dc_dsi_idle(struct tegra_dc *dc) tegra_dsi_host_suspend(dc); } -static int tegra_dsi_write_data_nosync(struct tegra_dc *dc, +int tegra_dsi_write_data(struct tegra_dc *dc, struct tegra_dc_dsi_data *dsi, u8 *pdata, u8 data_id, u16 data_len) { int err = 0; struct dsi_status *init_status; + tegra_dc_io_start(dc); + init_status = tegra_dsi_prepare_host_transmission( dc, dsi, DSI_LP_OP_WRITE); if (IS_ERR_OR_NULL(init_status)) { @@ -2161,27 +2164,10 @@ fail: err = tegra_dsi_restore_state(dc, dsi, init_status); if (err < 0) dev_err(&dc->ndev->dev, "Failed to restore prev state\n"); - - return err; -} - -int tegra_dsi_write_data(struct tegra_dc *dc, - struct tegra_dc_dsi_data *dsi, - u8 *pdata, u8 data_id, u16 data_len) -{ - int err; - - tegra_dc_io_start(dc); - tegra_dc_dsi_hold_host(dc); - - err = tegra_dsi_write_data_nosync(dc, dsi, pdata, data_id, data_len); - - tegra_dc_dsi_release_host(dc); tegra_dc_io_end(dc); return err; } - EXPORT_SYMBOL(tegra_dsi_write_data); static int tegra_dsi_send_panel_cmd(struct tegra_dc *dc, @@ -2200,7 +2186,7 @@ static int tegra_dsi_send_panel_cmd(struct tegra_dc *dc, if (cur_cmd->cmd_type == TEGRA_DSI_DELAY_MS) mdelay(cur_cmd->sp_len_dly.delay_ms); else { - err = tegra_dsi_write_data_nosync(dc, dsi, + err = tegra_dsi_write_data(dc, dsi, cur_cmd->pdata, cur_cmd->data_id, cur_cmd->sp_len_dly.data_len); @@ -2325,9 +2311,10 @@ int tegra_dsi_start_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi, return -EINVAL; mutex_lock(&dsi->lock); - tegra_dc_io_start(dc); tegra_dc_dsi_hold_host(dc); + tegra_dc_io_start(dc); + err = tegra_dsi_dcs_pkt_seq_ctrl_init(dsi, cmd); if (err < 0) { @@ -2347,8 +2334,8 @@ int tegra_dsi_start_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi, tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_CONTROL); fail: - tegra_dc_dsi_release_host(dc); tegra_dc_io_end(dc); + tegra_dc_dsi_release_host(dc); mutex_unlock(&dsi->lock); return err; @@ -2363,18 +2350,19 @@ void tegra_dsi_stop_host_cmd_v_blank_dcs(struct tegra_dc_dsi_data * dsi) u32 cnt; mutex_lock(&dsi->lock); - tegra_dc_io_start(dc); tegra_dc_dsi_hold_host(dc); + tegra_dc_io_start(dc); + tegra_dsi_writel(dsi, TEGRA_DSI_DISABLE, DSI_INIT_SEQ_CONTROL); /* clear seq data registers */ for (cnt = 0; cnt < 8; cnt++) tegra_dsi_writel(dsi, 0, DSI_INIT_SEQ_DATA_0 + cnt); - tegra_dc_dsi_release_host(dc); tegra_dc_io_end(dc); + tegra_dc_dsi_release_host(dc); mutex_unlock(&dsi->lock); } EXPORT_SYMBOL(tegra_dsi_stop_host_cmd_v_blank_dcs); @@ -2790,9 +2778,9 @@ static void tegra_dc_dsi_enable(struct tegra_dc *dc) u32 val; mutex_lock(&dsi->lock); - tegra_dc_io_start(dc); tegra_dc_dsi_hold_host(dc); + tegra_dc_io_start(dc); /* Stop DC stream before configuring DSI registers * to avoid visible glitches on panel during transition * from bootloader to kernel driver @@ -2905,8 +2893,8 @@ static void tegra_dc_dsi_enable(struct tegra_dc *dc) if (dsi->status.driven == DSI_DRIVEN_MODE_DC) tegra_dsi_start_dc_stream(dc, dsi); fail: - tegra_dc_dsi_release_host(dc); tegra_dc_io_end(dc); + tegra_dc_dsi_release_host(dc); mutex_unlock(&dsi->lock); } @@ -3389,8 +3377,8 @@ static void tegra_dc_dsi_disable(struct tegra_dc *dc) int err; struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc); - mutex_lock(&dsi->lock); tegra_dc_io_start(dc); + mutex_lock(&dsi->lock); if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE) tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi); diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c index 9f5968f0c587..55d9163d4faf 100644 --- a/drivers/video/tegra/dc/hdmi.c +++ b/drivers/video/tegra/dc/hdmi.c @@ -1462,7 +1462,10 @@ static void tegra_dc_hdmi_detect_worker(struct work_struct *work) container_of(to_delayed_work(work), struct tegra_dc_hdmi_data, work); struct tegra_dc *dc = hdmi->dc; + tegra_dc_enable(dc); + msleep(5); if (!tegra_dc_hdmi_detect(dc)) { + tegra_dc_disable(dc); tegra_fb_update_monspecs(dc->fb, NULL, NULL); dc->connected = false; @@ -1620,11 +1623,21 @@ static int tegra_dc_hdmi_init(struct tegra_dc *dc) } #endif + /* TODO: support non-hotplug */ + if (request_irq(gpio_to_irq(dc->out->hotplug_gpio), tegra_dc_hdmi_irq, + IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + dev_name(&dc->ndev->dev), dc)) { + dev_err(&dc->ndev->dev, "hdmi: request_irq %d failed\n", + gpio_to_irq(dc->out->hotplug_gpio)); + err = -EBUSY; + goto err_put_clock; + } + hdmi->edid = tegra_edid_create(dc->out->dcc_bus); if (IS_ERR_OR_NULL(hdmi->edid)) { dev_err(&dc->ndev->dev, "hdmi: can't create edid\n"); err = PTR_ERR(hdmi->edid); - goto err_put_clock; + goto err_free_irq; } #ifdef CONFIG_TEGRA_NVHDCP @@ -1679,23 +1692,14 @@ static int tegra_dc_hdmi_init(struct tegra_dc *dc) tegra_dc_hdmi_debug_create(hdmi); - /* TODO: support non-hotplug */ - if (request_irq(gpio_to_irq(dc->out->hotplug_gpio), tegra_dc_hdmi_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - dev_name(&dc->ndev->dev), dc)) { - dev_err(&dc->ndev->dev, "hdmi: request_irq %d failed\n", - gpio_to_irq(dc->out->hotplug_gpio)); - err = -EBUSY; - goto err_nvhdcp_destroy; - } - return 0; -err_nvhdcp_destroy: - if (hdmi->nvhdcp) - tegra_nvhdcp_destroy(hdmi->nvhdcp); +#ifdef CONFIG_TEGRA_NVHDCP err_edid_destroy: tegra_edid_destroy(hdmi->edid); +#endif +err_free_irq: + free_irq(gpio_to_irq(dc->out->hotplug_gpio), dc); err_put_clock: #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) if (!IS_ERR_OR_NULL(hdmi->hda2hdmi_clk)) diff --git a/drivers/video/tegra/dc/lut.c b/drivers/video/tegra/dc/lut.c index 2dfecfcea458..7ce8fc6768a0 100644 --- a/drivers/video/tegra/dc/lut.c +++ b/drivers/video/tegra/dc/lut.c @@ -109,7 +109,6 @@ static int tegra_dc_update_winlut(struct tegra_dc *dc, int win_idx, int fbovr) mutex_unlock(&dc->lock); tegra_dc_update_windows(&win, 1); - tegra_dc_sync_windows(&win, 1); return 0; } diff --git a/drivers/video/tegra/dc/nvsd.c b/drivers/video/tegra/dc/nvsd.c index 2f3343146ecc..6e76ee0f1702 100644 --- a/drivers/video/tegra/dc/nvsd.c +++ b/drivers/video/tegra/dc/nvsd.c @@ -174,9 +174,7 @@ static bool nvsd_phase_in_adjustments(struct tegra_dc *dc, /* Set manual k value */ man_k = SD_MAN_K_R(cur_k) | SD_MAN_K_G(cur_k) | SD_MAN_K_B(cur_k); - tegra_dc_io_start(dc); tegra_dc_writel(dc, man_k, DC_DISP_SD_MAN_K_VALUES); - tegra_dc_io_end(dc); /* Set manual brightness value */ atomic_set(sd_brightness, cur_sd_brightness); } @@ -273,7 +271,6 @@ static void nvsd_cmd_handler(struct tegra_dc_sd_settings *settings, val &= ~SD_BIN_WIDTH_MASK; val |= bw; } - tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL); nvsd_phase_in_luts(settings, dc); @@ -354,7 +351,6 @@ void nvsd_init(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings) u32 bw_idx = 0; /* TODO: check if HW says SD's available */ - tegra_dc_io_start(dc); /* If SD's not present or disabled, clear the register and return. */ if (!settings || settings->enable == 0) { /* clear the brightness val, too. */ @@ -366,7 +362,6 @@ void nvsd_init(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings) if (settings) settings->phase_settings_step = 0; tegra_dc_writel(dc, 0, DC_DISP_SD_CONTROL); - tegra_dc_io_end(dc); return; } @@ -492,7 +487,6 @@ void nvsd_init(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings) /* Finally, Write SD Control */ tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL); dev_dbg(&dc->ndev->dev, " SD_CONTROL: 0x%08x\n", val); - tegra_dc_io_end(dc); /* set the brightness pointer */ sd_brightness = settings->sd_brightness; @@ -816,11 +810,9 @@ static ssize_t nvsd_settings_store(struct kobject *kobj, return -ENODEV; } - tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); nvsd_init(dc, sd_settings); tegra_dc_release_dc_out(dc); - tegra_dc_io_end(dc); mutex_unlock(&dc->lock); diff --git a/drivers/video/tegra/dc/rgb.c b/drivers/video/tegra/dc/rgb.c index 36dbbdf09a66..b4097d98a9ba 100644 --- a/drivers/video/tegra/dc/rgb.c +++ b/drivers/video/tegra/dc/rgb.c @@ -97,7 +97,6 @@ static void tegra_dc_rgb_enable(struct tegra_dc *dc) int i; u32 out_sel_pintable[ARRAY_SIZE(tegra_dc_rgb_enable_out_sel_pintable)]; - tegra_dc_io_start(dc); tegra_dc_writel(dc, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE, DC_CMD_DISPLAY_POWER_CONTROL); @@ -151,16 +150,13 @@ static void tegra_dc_rgb_enable(struct tegra_dc *dc) /* Inform DC register updated */ tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL); tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); - tegra_dc_io_end(dc); } static void tegra_dc_rgb_disable(struct tegra_dc *dc) { - tegra_dc_io_start(dc); tegra_dc_writel(dc, 0x00000000, DC_CMD_DISPLAY_POWER_CONTROL); tegra_dc_write_table(dc, tegra_dc_rgb_disable_pintable); - tegra_dc_io_end(dc); } struct tegra_dc_out_ops tegra_dc_rgb_ops = { diff --git a/drivers/video/tegra/dc/window.c b/drivers/video/tegra/dc/window.c index 48fef11b9978..0b4350d49418 100644 --- a/drivers/video/tegra/dc/window.c +++ b/drivers/video/tegra/dc/window.c @@ -31,16 +31,11 @@ static bool tegra_dc_windows_are_clean(struct tegra_dc_win *windows[], int n) { int i; - struct tegra_dc *dc = windows[0]->dc; - mutex_lock(&dc->lock); for (i = 0; i < n; i++) { - if (windows[i]->dirty) { - mutex_unlock(&dc->lock); + if (windows[i]->dirty) return false; - } } - mutex_unlock(&dc->lock); return true; } @@ -105,7 +100,6 @@ static void tegra_dc_set_blending(struct tegra_dc *dc, { unsigned long mask = BIT(DC_N_WINDOWS) - 1; - tegra_dc_io_start(dc); while (mask) { int idx = get_topmost_window(blend->z, &mask); @@ -122,7 +116,6 @@ static void tegra_dc_set_blending(struct tegra_dc *dc, tegra_dc_writel(dc, blend_3win(idx, mask, blend->flags), DC_WIN_BLEND_3WIN_XY); } - tegra_dc_io_end(dc); } /* does not support syncing windows on multiple dcs in one call */ @@ -148,8 +141,6 @@ int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n) trace_printk("%s:After wait_event_interruptible_timeout\n", windows[0]->dc->ndev->name); #endif - /* tegra_dc_io_start() done in update_windows */ - tegra_dc_io_end(windows[0]->dc); return ret; } EXPORT_SYMBOL(tegra_dc_sync_windows); @@ -201,8 +192,7 @@ static inline u32 compute_initial_dda(fixed20_12 in) return dfixed_frac(in); } -/* Does not support updating windows on multiple dcs in one call. - * Requires a matching sync_windows to avoid leaking ref-count on clocks. */ +/* does not support updating windows on multiple dcs in one call */ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n) { struct tegra_dc *dc; @@ -229,7 +219,6 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n) return -EFAULT; } - tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); if (no_vsync) @@ -435,7 +424,6 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n) trace_printk("%s:update_mask=%#lx\n", dc->ndev->name, update_mask); tegra_dc_release_dc_out(dc); - /* tegra_dc_io_end() is called in tegra_dc_sync_windows() */ mutex_unlock(&dc->lock); if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) mutex_unlock(&dc->one_shot_lock); -- cgit v1.2.3 From 762959f6abfa9a8497113f6b3393a0bbeb1315fe Mon Sep 17 00:00:00 2001 From: Steve Lin Date: Wed, 22 Aug 2012 14:55:34 -0700 Subject: net/usbnet: avoid recursive locking in usbnet_stop() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit |kernel BUG at kernel/rtmutex.c:724! |[] (rt_spin_lock_slowlock+0x108/0x2bc) from [] (defer_bh+0x1c/0xb4) |[] (defer_bh+0x1c/0xb4) from [] (rx_complete+0x14c/0x194) |[] (rx_complete+0x14c/0x194) from [] (usb_hcd_giveback_urb+0xa0/0xf0) |[] (usb_hcd_giveback_urb+0xa0/0xf0) from [] (musb_giveback+0x34/0x40) |[] (musb_giveback+0x34/0x40) from [] (musb_advance_schedule+0xb4/0x1c0) |[] (musb_advance_schedule+0xb4/0x1c0) from [] (musb_cleanup_urb.isra.9+0x80/0x8c) |[] (musb_cleanup_urb.isra.9+0x80/0x8c) from [] (musb_urb_dequeue+0xec/0x108) |[] (musb_urb_dequeue+0xec/0x108) from [] (unlink1+0xbc/0xcc) |[] (unlink1+0xbc/0xcc) from [] (usb_hcd_unlink_urb+0x54/0xa8) |[] (usb_hcd_unlink_urb+0x54/0xa8) from [] (unlink_urbs.isra.17+0x2c/0x58) |[] (unlink_urbs.isra.17+0x2c/0x58) from [] (usbnet_terminate_urbs+0x94/0x10c) |[] (usbnet_terminate_urbs+0x94/0x10c) from [] (usbnet_stop+0x100/0x15c) |[] (usbnet_stop+0x100/0x15c) from [] (__dev_close_many+0x94/0xc8) defer_bh() takes the lock which is hold during unlink_urbs(). The safe walk suggest that the skb will be removed from the list and this is done by defer_bh() so it seems to be okay to drop the lock here. Reported-by: Aníbal Almeida Pinto Signed-off-by: Sebastian Andrzej Siewior Acked-by: Oliver Neukum Signed-off-by: David S. Miller (cherry picked from commit 4231d47e6fe69f061f96c98c30eaf9fb4c14b96d) --------------------------------------------------------------------- net/usbnet: reserve headroom on rx skbs network drivers should reserve some headroom on incoming skbs so that we dont need expensive reallocations, eg forwarding packets in tunnels. This NET_SKB_PAD padding is done in various helpers, like __netdev_alloc_skb_ip_align() in this patch, combining NET_SKB_PAD and NET_IP_ALIGN magic. Signed-off-by: Eric Dumazet Cc: Oliver Neukum Cc: Greg Kroah-Hartman Acked-by: Oliver Neukum Signed-off-by: David S. Miller (cherry picked from commit 7bdd402706cf26bfef9050dfee3f229b7f33ee4f) --------------------------------------------------------------------- usbnet: use netif_tx_wake_queue instead of netif_start_queue If host is going to autosuspend function with two interfaces and if IP packet has arrived in-between of two usbnet_suspend() callbacks, i.e usbnet_resume() is called in-between, tx data flow is stopped. When autosuspend timer expires and device is put to autosuspend again, tx queue is waked up and data can be sent again. This behavior might be repeated several times in a row. Tested on Intel/ARM. Reviewed-by: Sjur Brændeland Tested-by: Dmitry Tarnyagin Signed-off-by: Alexey Orishko Acked-by: Oliver Neukum Signed-off-by: David S. Miller (cherry picked from commit 1aa9bc5b2f4cf8c48944fb9a607bf1dd674e2c10) --------------------------------------------------------------------- usbnet: increase URB reference count before usb_unlink_urb Commit 4231d47e6fe69f061f96c98c30eaf9fb4c14b96d(net/usbnet: avoid recursive locking in usbnet_stop()) fixes the recursive locking problem by releasing the skb queue lock, but it makes usb_unlink_urb racing with defer_bh, and the URB to being unlinked may be freed before or during calling usb_unlink_urb, so use-after-free problem may be triggerd inside usb_unlink_urb. The patch fixes the use-after-free problem by increasing URB reference count with skb queue lock held before calling usb_unlink_urb, so the URB won't be freed until return from usb_unlink_urb. Reported-by: Dave Jones Signed-off-by: Ming Lei Acked-by: Greg Kroah-Hartman Signed-off-by: David S. Miller (cherry picked from commit 0956a8c20b23d429e79ff86d4325583fc06f9eb4) --------------------------------------------------------------------- usbnet: don't clear urb->dev in tx_complete URB unlinking is always racing with its completion and tx_complete may be called before or during running usb_unlink_urb, so tx_complete must not clear urb->dev since it will be used in unlink path, otherwise invalid memory accesses or usb device leak may be caused inside usb_unlink_urb. Signed-off-by: Ming Lei Acked-by: Greg Kroah-Hartman Signed-off-by: David S. Miller (cherry picked from commit 5d5440a835710d09f0ef18da5000541ec98b537a) --------------------------------------------------------------------- usbnet: consider device busy at each recieved packet usbnet should centrally handle busy reporting in the rx path so subdrivers need not worry. This hurts use cases which do rx only or predominantly. Signed-off-by: Oliver Neukum Signed-off-by: David S. Miller (cherry picked from commit 8a78335442cea429afb2b964318b6e257448ea00) --------------------------------------------------------------------- usbnet: fix leak of transfer buffer of dev->interrupt The transfer buffer of dev->interrupt is allocated in .probe path, but not freed in .disconnet path, so mark the interrupt URB as URB_FREE_BUFFER to free the buffer when the URB is destroyed. Signed-off-by: Ming Lei Acked-by: Oliver Neukum Signed-off-by: David S. Miller (cherry picked from commit 267a83e8e00dc5a878b24c39883643c20a8b1482) Bug 1036768 Change-Id: I5d6620c8ff4e6cef52c3f467fb2196658c4d47b1 Signed-off-by: Steve Lin Reviewed-on: http://git-master/r/125338 (cherry picked from commit 81c24e718939bc0a2d774ba6790febf57b4da4a5) Reviewed-on: http://git-master/r/127021 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit --- drivers/net/usb/usbnet.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 82965e20e076..a379613d0b58 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -210,6 +210,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf) } else { usb_fill_int_urb(dev->interrupt, dev->udev, pipe, buf, maxp, intr_complete, dev, period); + dev->interrupt->transfer_flags |= URB_FREE_BUFFER; dev_dbg(&intf->dev, "status ep%din, %d bytes period %d\n", usb_pipeendpoint(pipe), maxp, period); @@ -324,13 +325,13 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) unsigned long lockflags; size_t size = dev->rx_urb_size; - if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) { + skb = __netdev_alloc_skb_ip_align(dev->net, size, flags); + if (!skb) { netif_dbg(dev, rx_err, dev->net, "no rx skb\n"); usbnet_defer_kevent (dev, EVENT_RX_MEMORY); usb_free_urb (urb); return -ENOMEM; } - skb_reserve (skb, NET_IP_ALIGN); entry = (struct skb_data *) skb->cb; entry->urb = urb; @@ -489,6 +490,7 @@ block: if (netif_running (dev->net) && !test_bit (EVENT_RX_HALT, &dev->flags)) { rx_submit (dev, urb, GFP_ATOMIC); + usb_mark_last_busy(dev->udev); return; } usb_free_urb (urb); @@ -585,6 +587,15 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q) entry = (struct skb_data *) skb->cb; urb = entry->urb; + /* + * Get reference count of the URB to avoid it to be + * freed during usb_unlink_urb, which may trigger + * use-after-free problem inside usb_unlink_urb since + * usb_unlink_urb is always racing with .complete + * handler(include defer_bh). + */ + usb_get_urb(urb); + spin_unlock_irqrestore(&q->lock, flags); // during some PM-driven resume scenarios, // these (async) unlinks complete immediately retval = usb_unlink_urb (urb); @@ -592,6 +603,8 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q) netdev_dbg(dev->net, "unlink urb err, %d\n", retval); else count++; + usb_put_urb(urb); + spin_lock_irqsave(&q->lock, flags); } spin_unlock_irqrestore (&q->lock, flags); return count; @@ -1022,7 +1035,6 @@ static void tx_complete (struct urb *urb) } usb_autopm_put_interface_async(dev->intf); - urb->dev = NULL; entry->state = tx_done; defer_bh(dev, skb, &dev->txq); } @@ -1531,7 +1543,7 @@ int usbnet_resume (struct usb_interface *intf) if (test_bit(EVENT_DEV_OPEN, &dev->flags)) { if (!(dev->txq.qlen >= TX_QLEN(dev))) - netif_start_queue(dev->net); + netif_tx_wake_all_queues(dev->net); tasklet_schedule (&dev->bh); } } -- cgit v1.2.3 From 4f6001cbe99cf3176e108de0d7974a906fb6ac12 Mon Sep 17 00:00:00 2001 From: Ilan Aelion Date: Fri, 24 Aug 2012 14:26:52 +0530 Subject: ARM: tegra: profile: export app profile support Bug 1034948 Change-Id: I779abb26d65640f5138abe9c46652b749127c694 Signed-off-by: Ilan Aelion Reviewed-on: http://git-master/r/127064 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bharat Nihalani Tested-by: Bharat Nihalani --- arch/arm/mach-tegra/tegra3_speedo.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-tegra/tegra3_speedo.c b/arch/arm/mach-tegra/tegra3_speedo.c index 2889f656f47a..54180a67a620 100644 --- a/arch/arm/mach-tegra/tegra3_speedo.c +++ b/arch/arm/mach-tegra/tegra3_speedo.c @@ -136,6 +136,12 @@ static int package_id; */ static int enable_app_profiles; +int app_profiles_enabled(void) +{ + return enable_app_profiles; +} +EXPORT_SYMBOL(app_profiles_enabled); + static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp) { u32 reg; -- cgit v1.2.3 From a12c71d219c72eaf1ac45dc9ddd177656863022f Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Fri, 24 Aug 2012 11:10:21 +0530 Subject: Revert "Revert "video: tegra: dc: fix boot issue with HDMI"" This reverts commit ea4da3a292039d772eba32b43048fe50e7f7377b. Bug 1037683 Bug 1030415 Change-Id: Ibf77384ee62bb34e6fa34a1670ea3f0803dcd25e Signed-off-by: Deepak Nibade Reviewed-on: http://git-master/r/127084 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bharat Nihalani Tested-by: Bharat Nihalani --- drivers/video/tegra/dc/dc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index da7f2910bb25..c33858ab4588 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -1814,8 +1814,8 @@ static int tegra_dc_probe(struct nvhost_device *ndev, mutex_lock(&dc->lock); if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED) { - dc->enabled = _tegra_dc_enable(dc); _tegra_dc_set_default_videomode(dc); + dc->enabled = _tegra_dc_enable(dc); } mutex_unlock(&dc->lock); @@ -1965,8 +1965,8 @@ static int tegra_dc_resume(struct nvhost_device *ndev) dc->suspended = false; if (dc->enabled) { - _tegra_dc_enable(dc); _tegra_dc_set_default_videomode(dc); + _tegra_dc_enable(dc); } if (dc->out && dc->out->hotplug_init) -- cgit v1.2.3 From a3e56e8b914790e059ef0c44de3a4b4287c40f11 Mon Sep 17 00:00:00 2001 From: Ilan Aelion Date: Fri, 24 Aug 2012 14:39:38 +0530 Subject: video: tegra: host: WAR: fallback 3dfs on ap37 Disabling throughput-hint based scaling on ap37 Bug 1034948 Change-Id: I60570e1a6b95a2f27918959dfd8d3449b286627c Signed-off-by: Ilan Aelion Reviewed-on: http://git-master/r/127129 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bharat Nihalani Tested-by: Bharat Nihalani --- drivers/video/tegra/host/gr3d/scale3d.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/video/tegra/host/gr3d/scale3d.c b/drivers/video/tegra/host/gr3d/scale3d.c index fc30c2259ad4..dbbc355751ed 100644 --- a/drivers/video/tegra/host/gr3d/scale3d.c +++ b/drivers/video/tegra/host/gr3d/scale3d.c @@ -639,6 +639,12 @@ static ssize_t enable_3d_scaling_store(struct device *dev, static DEVICE_ATTR(enable_3d_scaling, S_IRUGO | S_IWUSR, enable_3d_scaling_show, enable_3d_scaling_store); +/* + * WAR: disable use_throughput_hint on ap37 + * this is defined in arch/arm/mach-tegra/tegra3_speedo.c + */ +int app_profiles_enabled(void); + void nvhost_scale3d_init(struct nvhost_device *d) { if (!scale3d.init) { @@ -750,6 +756,8 @@ void nvhost_scale3d_init(struct nvhost_device *d) scale3d.p_verbosity = 0; scale3d.p_adjust = 1; scale3d.p_use_throughput_hint = 1; + /* app profiles only enabled on ap37 */ + scale3d.p_use_throughput_hint = !app_profiles_enabled(); scale3d.p_throughput_lo_limit = 95; scale3d.p_throughput_hi_limit = 100; scale3d.p_scale_step = 60000000; -- cgit v1.2.3 From 92f2d2099e3411dfa1966e8ead58dc5654f3124c Mon Sep 17 00:00:00 2001 From: Nikesh Oswal Date: Tue, 28 Aug 2012 19:51:04 +0530 Subject: enterprise pinmux: set the pinmux for audio ports Bug: 1039342 Change-Id: Ic1f0e9fa8c8d9e69b7fb9cd35d2cbbf578c579e5 Signed-off-by: Nikesh Oswal Reviewed-on: http://git-master/r/127868 Reviewed-by: Ravindra Lokhande Reviewed-by: Scott Peterson --- arch/arm/mach-tegra/board-enterprise-pinmux.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-tegra/board-enterprise-pinmux.c b/arch/arm/mach-tegra/board-enterprise-pinmux.c index 1a19dbf95f4a..960346824167 100644 --- a/arch/arm/mach-tegra/board-enterprise-pinmux.c +++ b/arch/arm/mach-tegra/board-enterprise-pinmux.c @@ -258,8 +258,8 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_a03[] = { DEFAULT_PINMUX(ULPI_STP, ULPI, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(DAP3_DIN, I2S2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(GPIO_PV3, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), DEFAULT_PINMUX(LCD_PWR1, DISPLAYA, NORMAL, TRISTATE, OUTPUT), DEFAULT_PINMUX(LCD_PWR2, DISPLAYA, NORMAL, TRISTATE, INPUT), @@ -307,10 +307,10 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_a03[] = { DEFAULT_PINMUX(GPIO_PU4, PWM1, PULL_DOWN, TRISTATE, OUTPUT), DEFAULT_PINMUX(GPIO_PU5, PWM2, NORMAL, TRISTATE, INPUT), DEFAULT_PINMUX(GPIO_PU6, PWM3, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(DAP4_FS, I2S3, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(DAP4_DIN, I2S3, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(DAP4_DOUT, I2S3, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(DAP4_SCLK, I2S3, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP4_FS, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DIN, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DOUT, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_SCLK, I2S3, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(GMI_A16, UARTD, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(GMI_A17, UARTD, NORMAL, TRISTATE, INPUT), DEFAULT_PINMUX(GMI_A18, UARTD, NORMAL, TRISTATE, INPUT), @@ -326,14 +326,14 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_a03[] = { DEFAULT_PINMUX(KB_COL3, KBC, PULL_DOWN, TRISTATE, OUTPUT), DEFAULT_PINMUX(GPIO_PV0, RSVD, PULL_UP, TRISTATE, INPUT), DEFAULT_PINMUX(DAP1_FS, I2S0, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP1_DIN, I2S0, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(DAP1_DOUT, I2S0, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP1_DIN, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DOUT, I2S0, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(DAP1_SCLK, I2S0, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(SPDIF_IN, SPDIF, NORMAL, TRISTATE, INPUT), DEFAULT_PINMUX(DAP2_FS, I2S1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_DIN, I2S1, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(DAP2_DOUT, I2S1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP2_DIN, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DOUT, I2S1, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(DAP2_SCLK, I2S1, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(SPI1_MOSI, SPI1, PULL_DOWN, TRISTATE, OUTPUT), DEFAULT_PINMUX(SPI1_SCK, SPI1, PULL_DOWN, TRISTATE, OUTPUT), -- cgit v1.2.3