mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 05:34:13 +08:00
For the 3.12 merge window we have one new driver for the DA9063 PMIC
from Dialog Semiconductor. Besides that driver we also have: - Device tree support for the s2mps11 driver - More devm_* conversion for the pm8921, max89xx, menelaus, tps65010, wl1273 and pcf50633-adc drivers. - A conversion to threaded IRQ and IRQ domain for the twl6030 driver. - A fairly big update for the rtsx driver: Better power saving support, better vendor settings handling, and a few fixes. - Support for a couple more boards (COMe-bHL6 and COMe-cTH6) for the Kontron driver. - A conversion to the dev_get_platdata() API for all MFD drivers. - A removal of non-DT (legacy) support for the twl6040 driver. - A few fixes and additions (Mic detect level) to the wm5110 register tables. - Regmap support for the davinci_voicecodec driver. - The usual bunch of minor cleanups and janitorial fixes. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJSKFnjAAoJEIqAPN1PVmxKU9AP/RAmSYux6c+cd7P7roXL+/lA qNKy8Op31J51N/n918o7zwbskmRIJJsbd+I6ClBlYdCUB+B8/Oj41uD4F+q35b/H F5Xm2XRPQAGHx37m5adJMrK/OR3zCTwhPjleJYOJWIFjDP/nDNJIPwTYb13Rqurh V39icmRtnNR0uDOmv3eELyV4FnWQTpA858dxuhSi+5jbbHFhCcYShEmE9109eexl RNuyF8d0KPGvnKhK+H1/k4ZYG2XAFFOZfZz9MB+l651nidqDvwJph0Zdj3w1r112 8OR5i7B3vw268nmyjOOUtYqL2vOaUW4lavmLTQiSdQWd1BHv9hEmD0RRR5bSrLeH 6DwCTh0+xWH08ogbMwi4dwZyRhjxMPMpkxeNz51TpRnXKDSZmBgrjovKNJpP8pW6 m7RsgUC9AiEQf/Ac0PBMrU8ABKeJnt3K3ZZp4YN7/H6rAMOhXjLqFD8JLoFvx08z itKKSzVaIA3pzxpnkWWiTsr+bChaSOrHHy1biWa4ve5pvrFc9ivPz1DhL3PTmXpp haeeylFG01r5NJIHeJewRsmUJk67aEyeAnnoLwqCRycWjdDmcCBC5bgDBkRRonoS 93tgKVzL9q/NwvT5Uatw3uYqTN0jOuH0t39gAzu9uwnWvivcZK5EBYh789YQL+on zih4qUICM08yWRDNNDgF =a7dU -----END PGP SIGNATURE----- Merge tag 'mfd-3.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next Pull MFD (multi-function device) updates from Samuel Ortiz: "For the 3.12 merge window we have one new driver for the DA9063 PMIC from Dialog Semiconductor. Besides that driver we also have: - Device tree support for the s2mps11 driver - More devm_* conversion for the pm8921, max89xx, menelaus, tps65010, wl1273 and pcf50633-adc drivers. - A conversion to threaded IRQ and IRQ domain for the twl6030 driver. - A fairly big update for the rtsx driver: Better power saving support, better vendor settings handling, and a few fixes. - Support for a couple more boards (COMe-bHL6 and COMe-cTH6) for the Kontron driver. - A conversion to the dev_get_platdata() API for all MFD drivers. - A removal of non-DT (legacy) support for the twl6040 driver. - A few fixes and additions (Mic detect level) to the wm5110 register tables. - Regmap support for the davinci_voicecodec driver. - The usual bunch of minor cleanups and janitorial fixes" * tag 'mfd-3.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next: (81 commits) mfd: ucb1x00-core: Rewrite ucb1x00_add_dev() mfd: ab8500-debugfs: Apply a check for -ENOMEM after allocating memory for event name mfd: ab8500-debugfs: Apply a check for -ENOMEM after allocating memory for sysfs mfd: timberdale: Use module_pci_driver mfd: timberdale: Remove redundant break mfd: timberdale: Staticize local variables mfd: ab8500-debugfs: Staticize local variables mfd: db8500-prcmu: Staticize clk_mgt mfd: db8500-prcmu: Use ANSI function declaration mfd: omap-usb-host: Staticize usbhs_driver_name mfd: 88pm805: Fix potential NULL pdata dereference mfd: 88pm800: Fix potential NULL pdata dereference mfd: twl6040: Use regmap for register cache mfd: davinci_voicecodec: Provide a regmap for register I/O mfd: davinci_voicecodec: Remove unused read and write functions mmc: memstick: rtsx: Modify copyright comments mmc: rtsx: Clear SD_CLK toggle enable bit if switching voltage fail mfd: mmc: rtsx: Change default tx phase mfd: pcf50633-adc: Use devm_*() functions mfd: rtsx: Copyright modifications ...
This commit is contained in:
commit
8de4651abe
@ -5,6 +5,7 @@ twl6035 (palmas)
|
||||
twl6037 (palmas)
|
||||
tps65913 (palmas)
|
||||
tps65914 (palmas)
|
||||
tps659038
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be from the list
|
||||
@ -14,6 +15,7 @@ Required properties:
|
||||
ti,tps65913
|
||||
ti,tps65914
|
||||
ti,tps80036
|
||||
ti,tps659038
|
||||
and also the generic series names
|
||||
ti,palmas
|
||||
- interrupt-controller : palmas has its own internal IRQs
|
||||
|
109
Documentation/devicetree/bindings/mfd/s2mps11.txt
Normal file
109
Documentation/devicetree/bindings/mfd/s2mps11.txt
Normal file
@ -0,0 +1,109 @@
|
||||
|
||||
* Samsung S2MPS11 Voltage and Current Regulator
|
||||
|
||||
The Samsung S2MP211 is a multi-function device which includes voltage and
|
||||
current regulators, RTC, charger controller and other sub-blocks. It is
|
||||
interfaced to the host controller using a I2C interface. Each sub-block is
|
||||
addressed by the host system using different I2C slave address.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "samsung,s2mps11-pmic".
|
||||
- reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
|
||||
|
||||
Optional properties:
|
||||
- interrupt-parent: Specifies the phandle of the interrupt controller to which
|
||||
the interrupts from s2mps11 are delivered to.
|
||||
- interrupts: Interrupt specifiers for interrupt sources.
|
||||
|
||||
Optional nodes:
|
||||
- clocks: s2mps11 provides three(AP/CP/BT) buffered 32.768 KHz outputs, so to
|
||||
register these as clocks with common clock framework instantiate a sub-node
|
||||
named "clocks". It uses the common clock binding documented in :
|
||||
[Documentation/devicetree/bindings/clock/clock-bindings.txt]
|
||||
- #clock-cells: should be 1.
|
||||
|
||||
- The following is the list of clocks generated by the controller. Each clock
|
||||
is assigned an identifier and client nodes use this identifier to specify
|
||||
the clock which they consume.
|
||||
Clock ID
|
||||
----------------------
|
||||
32KhzAP 0
|
||||
32KhzCP 1
|
||||
32KhzBT 2
|
||||
|
||||
- regulators: The regulators of s2mps11 that have to be instantiated should be
|
||||
included in a sub-node named 'regulators'. Regulator nodes included in this
|
||||
sub-node should be of the format as listed below.
|
||||
|
||||
regulator_name {
|
||||
[standard regulator constraints....];
|
||||
};
|
||||
|
||||
regulator-ramp-delay for BUCKs = [6250/12500/25000(default)/50000] uV/us
|
||||
|
||||
BUCK[2/3/4/6] supports disabling ramp delay on hardware, so explictly
|
||||
regulator-ramp-delay = <0> can be used for them to disable ramp delay.
|
||||
In absence of regulator-ramp-delay property, default ramp delay will be used.
|
||||
|
||||
NOTE: Some BUCKs share the ramp rate setting i.e. same ramp value will be set
|
||||
for a particular group of BUCKs. So provide same regulator-ramp-delay<value>.
|
||||
Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6],
|
||||
BUCK[3, 4], and BUCK[7, 8, 10]
|
||||
|
||||
The regulator constraints inside the regulator nodes use the standard regulator
|
||||
bindings which are documented elsewhere.
|
||||
|
||||
The following are the names of the regulators that the s2mps11 pmic block
|
||||
supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
|
||||
as per the datasheet of s2mps11.
|
||||
|
||||
- LDOn
|
||||
- valid values for n are 1 to 28
|
||||
- Example: LDO0, LD01, LDO28
|
||||
- BUCKn
|
||||
- valid values for n are 1 to 9.
|
||||
- Example: BUCK1, BUCK2, BUCK9
|
||||
|
||||
Example:
|
||||
|
||||
s2mps11_pmic@66 {
|
||||
compatible = "samsung,s2mps11-pmic";
|
||||
reg = <0x66>;
|
||||
|
||||
s2m_osc: clocks{
|
||||
#clock-cells = 1;
|
||||
clock-output-names = "xx", "yy", "zz";
|
||||
};
|
||||
|
||||
regulators {
|
||||
ldo1_reg: LDO1 {
|
||||
regulator-name = "VDD_ABB_3.3V";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
ldo2_reg: LDO2 {
|
||||
regulator-name = "VDD_ALIVE_1.1V";
|
||||
regulator-min-microvolt = <1100000>;
|
||||
regulator-max-microvolt = <1100000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
buck1_reg: BUCK1 {
|
||||
regulator-name = "vdd_mif";
|
||||
regulator-min-microvolt = <950000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
buck2_reg: BUCK2 {
|
||||
regulator-name = "vdd_arm";
|
||||
regulator-min-microvolt = <950000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-ramp-delay = <50000>;
|
||||
};
|
||||
};
|
||||
};
|
@ -36,6 +36,9 @@ Optional nodes:
|
||||
ti,smps-range - OTP has the wrong range set for the hardware so override
|
||||
0 - low range, 1 - high range.
|
||||
|
||||
- ti,system-power-controller: Telling whether or not this pmic is controlling
|
||||
the system power.
|
||||
|
||||
Example:
|
||||
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
@ -48,6 +51,8 @@ pmic {
|
||||
|
||||
ti,ldo6-vibrator;
|
||||
|
||||
ti,system-power-controller;
|
||||
|
||||
regulators {
|
||||
smps12_reg : smps12 {
|
||||
regulator-name = "smps12";
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Realtek PCI-Express Memstick Card Interface driver
|
||||
*
|
||||
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
|
||||
* Copyright(c) 2009-2013 Realtek Semiconductor Corp. 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 the
|
||||
@ -17,7 +17,6 @@
|
||||
*
|
||||
* Author:
|
||||
* Wei WANG <wei_wang@realsil.com.cn>
|
||||
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -333,9 +333,11 @@ static int device_rtc_init(struct pm80x_chip *chip,
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (pdata) {
|
||||
rtc_devs[0].platform_data = pdata->rtc;
|
||||
rtc_devs[0].pdata_size =
|
||||
pdata->rtc ? sizeof(struct pm80x_rtc_pdata) : 0;
|
||||
}
|
||||
ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
|
||||
ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
|
||||
if (ret) {
|
||||
@ -541,7 +543,7 @@ static int pm800_probe(struct i2c_client *client,
|
||||
{
|
||||
int ret = 0;
|
||||
struct pm80x_chip *chip;
|
||||
struct pm80x_platform_data *pdata = client->dev.platform_data;
|
||||
struct pm80x_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct pm80x_subchip *subchip;
|
||||
|
||||
ret = pm80x_init(client);
|
||||
@ -578,7 +580,7 @@ static int pm800_probe(struct i2c_client *client,
|
||||
goto err_device_init;
|
||||
}
|
||||
|
||||
if (pdata->plat_config)
|
||||
if (pdata && pdata->plat_config)
|
||||
pdata->plat_config(chip, pdata);
|
||||
|
||||
return 0;
|
||||
|
@ -227,7 +227,7 @@ static int pm805_probe(struct i2c_client *client,
|
||||
{
|
||||
int ret = 0;
|
||||
struct pm80x_chip *chip;
|
||||
struct pm80x_platform_data *pdata = client->dev.platform_data;
|
||||
struct pm80x_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
|
||||
ret = pm80x_init(client);
|
||||
if (ret) {
|
||||
@ -243,7 +243,7 @@ static int pm805_probe(struct i2c_client *client,
|
||||
goto err_805_init;
|
||||
}
|
||||
|
||||
if (pdata->plat_config)
|
||||
if (pdata && pdata->plat_config)
|
||||
pdata->plat_config(chip, pdata);
|
||||
|
||||
err_805_init:
|
||||
|
@ -1130,7 +1130,7 @@ static int pm860x_dt_init(struct device_node *np,
|
||||
static int pm860x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct pm860x_platform_data *pdata = client->dev.platform_data;
|
||||
struct pm860x_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct device_node *node = client->dev.of_node;
|
||||
struct pm860x_chip *chip;
|
||||
int ret;
|
||||
|
@ -139,6 +139,18 @@ config MFD_DA9055
|
||||
This driver can be built as a module. If built as a module it will be
|
||||
called "da9055"
|
||||
|
||||
config MFD_DA9063
|
||||
bool "Dialog Semiconductor DA9063 PMIC Support"
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
depends on I2C=y && GENERIC_HARDIRQS
|
||||
help
|
||||
Say yes here for support for the Dialog Semiconductor DA9063 PMIC.
|
||||
This includes the I2C driver and core APIs.
|
||||
Additional drivers must be enabled in order to use the functionality
|
||||
of the device.
|
||||
|
||||
config MFD_MC13783
|
||||
tristate
|
||||
|
||||
@ -1070,7 +1082,7 @@ config MFD_WM5110
|
||||
Support for Wolfson Microelectronics WM5110 low power audio SoC
|
||||
|
||||
config MFD_WM8997
|
||||
bool "Support Wolfson Microelectronics WM8997"
|
||||
bool "Wolfson Microelectronics WM8997"
|
||||
depends on MFD_ARIZONA
|
||||
help
|
||||
Support for Wolfson Microelectronics WM8997 low power audio SoC
|
||||
|
@ -107,6 +107,9 @@ obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o
|
||||
da9055-objs := da9055-core.o da9055-i2c.o
|
||||
obj-$(CONFIG_MFD_DA9055) += da9055.o
|
||||
|
||||
da9063-objs := da9063-core.o da9063-irq.o da9063-i2c.o
|
||||
obj-$(CONFIG_MFD_DA9063) += da9063.o
|
||||
|
||||
obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o
|
||||
obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o
|
||||
obj-$(CONFIG_MFD_MAX8907) += max8907.o
|
||||
|
@ -363,7 +363,7 @@ static inline void aat2870_uninit_debugfs(struct aat2870_data *aat2870)
|
||||
static int aat2870_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct aat2870_platform_data *pdata = client->dev.platform_data;
|
||||
struct aat2870_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct aat2870_data *aat2870;
|
||||
int i, j;
|
||||
int ret = 0;
|
||||
|
@ -854,7 +854,7 @@ static int ab3100_probe(struct i2c_client *client,
|
||||
{
|
||||
struct ab3100 *ab3100;
|
||||
struct ab3100_platform_data *ab3100_plf_data =
|
||||
client->dev.platform_data;
|
||||
dev_get_platdata(&client->dev);
|
||||
int err;
|
||||
int i;
|
||||
|
||||
|
@ -159,7 +159,7 @@ static struct hwreg_cfg hwreg_cfg = {
|
||||
|
||||
static struct ab8500_prcmu_ranges *debug_ranges;
|
||||
|
||||
struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = {
|
||||
static struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = {
|
||||
[0x0] = {
|
||||
.num_ranges = 0,
|
||||
.range = NULL,
|
||||
@ -488,7 +488,7 @@ struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = {
|
||||
},
|
||||
};
|
||||
|
||||
struct ab8500_prcmu_ranges ab8505_debug_ranges[AB8500_NUM_BANKS] = {
|
||||
static struct ab8500_prcmu_ranges ab8505_debug_ranges[AB8500_NUM_BANKS] = {
|
||||
[0x0] = {
|
||||
.num_ranges = 0,
|
||||
.range = NULL,
|
||||
@ -847,7 +847,7 @@ struct ab8500_prcmu_ranges ab8505_debug_ranges[AB8500_NUM_BANKS] = {
|
||||
},
|
||||
};
|
||||
|
||||
struct ab8500_prcmu_ranges ab8540_debug_ranges[AB8500_NUM_BANKS] = {
|
||||
static struct ab8500_prcmu_ranges ab8540_debug_ranges[AB8500_NUM_BANKS] = {
|
||||
[AB8500_M_FSM_RANK] = {
|
||||
.num_ranges = 1,
|
||||
.range = (struct ab8500_reg_range[]) {
|
||||
@ -1377,7 +1377,7 @@ void ab8500_dump_all_banks(struct device *dev)
|
||||
|
||||
/* Space for 500 registers. */
|
||||
#define DUMP_MAX_REGS 700
|
||||
struct ab8500_register_dump
|
||||
static struct ab8500_register_dump
|
||||
{
|
||||
u8 bank;
|
||||
u8 reg;
|
||||
@ -2800,7 +2800,13 @@ static ssize_t ab8500_subscribe_write(struct file *file,
|
||||
*/
|
||||
dev_attr[irq_index] = kmalloc(sizeof(struct device_attribute),
|
||||
GFP_KERNEL);
|
||||
if (!dev_attr[irq_index])
|
||||
return -ENOMEM;
|
||||
|
||||
event_name[irq_index] = kmalloc(count, GFP_KERNEL);
|
||||
if (!event_name[irq_index])
|
||||
return -ENOMEM;
|
||||
|
||||
sprintf(event_name[irq_index], "%lu", user_val);
|
||||
dev_attr[irq_index]->show = show_irq;
|
||||
dev_attr[irq_index]->store = NULL;
|
||||
|
@ -867,6 +867,7 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
|
||||
gpadc->cal_data[ADC_INPUT_VBAT].offset);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int ab8500_gpadc_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
|
||||
@ -885,7 +886,9 @@ static int ab8500_gpadc_runtime_resume(struct device *dev)
|
||||
dev_err(dev, "Failed to enable vtvout LDO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int ab8500_gpadc_suspend(struct device *dev)
|
||||
{
|
||||
struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
|
||||
@ -913,6 +916,7 @@ static int ab8500_gpadc_resume(struct device *dev)
|
||||
mutex_unlock(&gpadc->ab8500_gpadc_lock);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ab8500_gpadc_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -207,7 +207,7 @@ static int adp5520_remove_subdevs(struct adp5520_chip *chip)
|
||||
static int adp5520_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct adp5520_platform_data *pdata = client->dev.platform_data;
|
||||
struct adp5520_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct platform_device *pdev;
|
||||
struct adp5520_chip *chip;
|
||||
int ret;
|
||||
|
@ -438,9 +438,9 @@ static int arizona_runtime_suspend(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
regulator_disable(arizona->dcvdd);
|
||||
regcache_cache_only(arizona->regmap, true);
|
||||
regcache_mark_dirty(arizona->regmap);
|
||||
regulator_disable(arizona->dcvdd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ static int as3711_i2c_probe(struct i2c_client *client,
|
||||
int ret;
|
||||
|
||||
if (!client->dev.of_node) {
|
||||
pdata = client->dev.platform_data;
|
||||
pdata = dev_get_platdata(&client->dev);
|
||||
if (!pdata)
|
||||
dev_dbg(&client->dev, "Platform data not found\n");
|
||||
} else {
|
||||
|
@ -952,7 +952,7 @@ static void asic3_mfd_remove(struct platform_device *pdev)
|
||||
/* Core */
|
||||
static int __init asic3_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct asic3_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct asic3_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct asic3 *asic;
|
||||
struct resource *mem;
|
||||
unsigned long clksel;
|
||||
|
@ -494,7 +494,7 @@ failed:
|
||||
static int da903x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct da903x_platform_data *pdata = client->dev.platform_data;
|
||||
struct da903x_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct da903x_chip *chip;
|
||||
unsigned int tmp;
|
||||
int ret;
|
||||
|
@ -534,7 +534,7 @@ EXPORT_SYMBOL_GPL(da9052_regmap_config);
|
||||
|
||||
int da9052_device_init(struct da9052 *da9052, u8 chip_id)
|
||||
{
|
||||
struct da9052_pdata *pdata = da9052->dev->platform_data;
|
||||
struct da9052_pdata *pdata = dev_get_platdata(da9052->dev);
|
||||
int ret;
|
||||
|
||||
mutex_init(&da9052->auxadc_lock);
|
||||
|
@ -379,8 +379,9 @@ static struct regmap_irq_chip da9055_regmap_irq_chip = {
|
||||
|
||||
int da9055_device_init(struct da9055 *da9055)
|
||||
{
|
||||
struct da9055_pdata *pdata = da9055->dev->platform_data;
|
||||
struct da9055_pdata *pdata = dev_get_platdata(da9055->dev);
|
||||
int ret;
|
||||
uint8_t clear_events[3] = {0xFF, 0xFF, 0xFF};
|
||||
|
||||
if (pdata && pdata->init != NULL)
|
||||
pdata->init(da9055);
|
||||
@ -390,6 +391,10 @@ int da9055_device_init(struct da9055 *da9055)
|
||||
else
|
||||
da9055->irq_base = pdata->irq_base;
|
||||
|
||||
ret = da9055_group_write(da9055, DA9055_REG_EVENT_A, 3, clear_events);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regmap_add_irq_chip(da9055->regmap, da9055->chip_irq,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
da9055->irq_base, &da9055_regmap_irq_chip,
|
||||
|
@ -54,7 +54,7 @@ static int da9055_i2c_remove(struct i2c_client *i2c)
|
||||
}
|
||||
|
||||
static struct i2c_device_id da9055_i2c_id[] = {
|
||||
{"da9055-pmic", 0},
|
||||
{"da9055", 0},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
185
drivers/mfd/da9063-core.c
Normal file
185
drivers/mfd/da9063-core.c
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* da9063-core.c: Device access for Dialog DA9063 modules
|
||||
*
|
||||
* Copyright 2012 Dialog Semiconductors Ltd.
|
||||
* Copyright 2013 Philipp Zabel, Pengutronix
|
||||
*
|
||||
* Author: Krystian Garbaciak <krystian.garbaciak@diasemi.com>,
|
||||
* Michal Hajduk <michal.hajduk@diasemi.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <linux/mfd/da9063/core.h>
|
||||
#include <linux/mfd/da9063/pdata.h>
|
||||
#include <linux/mfd/da9063/registers.h>
|
||||
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
|
||||
static struct resource da9063_regulators_resources[] = {
|
||||
{
|
||||
.name = "LDO_LIM",
|
||||
.start = DA9063_IRQ_LDO_LIM,
|
||||
.end = DA9063_IRQ_LDO_LIM,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource da9063_rtc_resources[] = {
|
||||
{
|
||||
.name = "ALARM",
|
||||
.start = DA9063_IRQ_ALARM,
|
||||
.end = DA9063_IRQ_ALARM,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "TICK",
|
||||
.start = DA9063_IRQ_TICK,
|
||||
.end = DA9063_IRQ_TICK,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static struct resource da9063_onkey_resources[] = {
|
||||
{
|
||||
.start = DA9063_IRQ_ONKEY,
|
||||
.end = DA9063_IRQ_ONKEY,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource da9063_hwmon_resources[] = {
|
||||
{
|
||||
.start = DA9063_IRQ_ADC_RDY,
|
||||
.end = DA9063_IRQ_ADC_RDY,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
static struct mfd_cell da9063_devs[] = {
|
||||
{
|
||||
.name = DA9063_DRVNAME_REGULATORS,
|
||||
.num_resources = ARRAY_SIZE(da9063_regulators_resources),
|
||||
.resources = da9063_regulators_resources,
|
||||
},
|
||||
{
|
||||
.name = DA9063_DRVNAME_LEDS,
|
||||
},
|
||||
{
|
||||
.name = DA9063_DRVNAME_WATCHDOG,
|
||||
},
|
||||
{
|
||||
.name = DA9063_DRVNAME_HWMON,
|
||||
.num_resources = ARRAY_SIZE(da9063_hwmon_resources),
|
||||
.resources = da9063_hwmon_resources,
|
||||
},
|
||||
{
|
||||
.name = DA9063_DRVNAME_ONKEY,
|
||||
.num_resources = ARRAY_SIZE(da9063_onkey_resources),
|
||||
.resources = da9063_onkey_resources,
|
||||
},
|
||||
{
|
||||
.name = DA9063_DRVNAME_RTC,
|
||||
.num_resources = ARRAY_SIZE(da9063_rtc_resources),
|
||||
.resources = da9063_rtc_resources,
|
||||
},
|
||||
{
|
||||
.name = DA9063_DRVNAME_VIBRATION,
|
||||
},
|
||||
};
|
||||
|
||||
int da9063_device_init(struct da9063 *da9063, unsigned int irq)
|
||||
{
|
||||
struct da9063_pdata *pdata = da9063->dev->platform_data;
|
||||
int model, revision;
|
||||
int ret;
|
||||
|
||||
if (pdata) {
|
||||
da9063->flags = pdata->flags;
|
||||
da9063->irq_base = pdata->irq_base;
|
||||
} else {
|
||||
da9063->flags = 0;
|
||||
da9063->irq_base = 0;
|
||||
}
|
||||
da9063->chip_irq = irq;
|
||||
|
||||
if (pdata && pdata->init != NULL) {
|
||||
ret = pdata->init(da9063);
|
||||
if (ret != 0) {
|
||||
dev_err(da9063->dev,
|
||||
"Platform initialization failed.\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_ID, &model);
|
||||
if (ret < 0) {
|
||||
dev_err(da9063->dev, "Cannot read chip model id.\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (model != PMIC_DA9063) {
|
||||
dev_err(da9063->dev, "Invalid chip model id: 0x%02x\n", model);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = regmap_read(da9063->regmap, DA9063_REG_CHIP_VARIANT, &revision);
|
||||
if (ret < 0) {
|
||||
dev_err(da9063->dev, "Cannot read chip revision id.\n");
|
||||
return -EIO;
|
||||
}
|
||||
revision >>= DA9063_CHIP_VARIANT_SHIFT;
|
||||
if (revision != 3) {
|
||||
dev_err(da9063->dev, "Unknown chip revision: %d\n", revision);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
da9063->model = model;
|
||||
da9063->revision = revision;
|
||||
|
||||
dev_info(da9063->dev,
|
||||
"Device detected (model-ID: 0x%02X rev-ID: 0x%02X)\n",
|
||||
model, revision);
|
||||
|
||||
ret = da9063_irq_init(da9063);
|
||||
if (ret) {
|
||||
dev_err(da9063->dev, "Cannot initialize interrupts.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mfd_add_devices(da9063->dev, -1, da9063_devs,
|
||||
ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base,
|
||||
NULL);
|
||||
if (ret)
|
||||
dev_err(da9063->dev, "Cannot add MFD cells\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void da9063_device_exit(struct da9063 *da9063)
|
||||
{
|
||||
mfd_remove_devices(da9063->dev);
|
||||
da9063_irq_exit(da9063);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("PMIC driver for Dialog DA9063");
|
||||
MODULE_AUTHOR("Krystian Garbaciak <krystian.garbaciak@diasemi.com>, Michal Hajduk <michal.hajduk@diasemi.com>");
|
||||
MODULE_LICENSE("GPL");
|
182
drivers/mfd/da9063-i2c.c
Normal file
182
drivers/mfd/da9063-i2c.c
Normal file
@ -0,0 +1,182 @@
|
||||
/* da9063-i2c.c: Interrupt support for Dialog DA9063
|
||||
*
|
||||
* Copyright 2012 Dialog Semiconductor Ltd.
|
||||
* Copyright 2013 Philipp Zabel, Pengutronix
|
||||
*
|
||||
* Author: Krystian Garbaciak <krystian.garbaciak@diasemi.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/da9063/core.h>
|
||||
#include <linux/mfd/da9063/pdata.h>
|
||||
#include <linux/mfd/da9063/registers.h>
|
||||
|
||||
static const struct regmap_range da9063_readable_ranges[] = {
|
||||
{
|
||||
.range_min = DA9063_REG_PAGE_CON,
|
||||
.range_max = DA9063_REG_SECOND_D,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ,
|
||||
.range_max = DA9063_REG_ID_32_31,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ_A,
|
||||
.range_max = DA9063_REG_AUTO3_LOW,
|
||||
}, {
|
||||
.range_min = DA9063_REG_T_OFFSET,
|
||||
.range_max = DA9063_REG_GP_ID_19,
|
||||
}, {
|
||||
.range_min = DA9063_REG_CHIP_ID,
|
||||
.range_max = DA9063_REG_CHIP_VARIANT,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063_writeable_ranges[] = {
|
||||
{
|
||||
.range_min = DA9063_REG_PAGE_CON,
|
||||
.range_max = DA9063_REG_PAGE_CON,
|
||||
}, {
|
||||
.range_min = DA9063_REG_FAULT_LOG,
|
||||
.range_max = DA9063_REG_VSYS_MON,
|
||||
}, {
|
||||
.range_min = DA9063_REG_COUNT_S,
|
||||
.range_max = DA9063_REG_ALARM_Y,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ,
|
||||
.range_max = DA9063_REG_ID_32_31,
|
||||
}, {
|
||||
.range_min = DA9063_REG_SEQ_A,
|
||||
.range_max = DA9063_REG_AUTO3_LOW,
|
||||
}, {
|
||||
.range_min = DA9063_REG_CONFIG_I,
|
||||
.range_max = DA9063_REG_MON_REG_4,
|
||||
}, {
|
||||
.range_min = DA9063_REG_GP_ID_0,
|
||||
.range_max = DA9063_REG_GP_ID_19,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_range da9063_volatile_ranges[] = {
|
||||
{
|
||||
.range_min = DA9063_REG_STATUS_A,
|
||||
.range_max = DA9063_REG_EVENT_D,
|
||||
}, {
|
||||
.range_min = DA9063_REG_CONTROL_F,
|
||||
.range_max = DA9063_REG_CONTROL_F,
|
||||
}, {
|
||||
.range_min = DA9063_REG_ADC_MAN,
|
||||
.range_max = DA9063_REG_ADC_MAN,
|
||||
}, {
|
||||
.range_min = DA9063_REG_ADC_RES_L,
|
||||
.range_max = DA9063_REG_SECOND_D,
|
||||
}, {
|
||||
.range_min = DA9063_REG_MON_REG_5,
|
||||
.range_max = DA9063_REG_MON_REG_6,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_access_table da9063_readable_table = {
|
||||
.yes_ranges = da9063_readable_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(da9063_readable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table da9063_writeable_table = {
|
||||
.yes_ranges = da9063_writeable_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(da9063_writeable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table da9063_volatile_table = {
|
||||
.yes_ranges = da9063_volatile_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(da9063_volatile_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_range_cfg da9063_range_cfg[] = {
|
||||
{
|
||||
.range_min = DA9063_REG_PAGE_CON,
|
||||
.range_max = DA9063_REG_CHIP_VARIANT,
|
||||
.selector_reg = DA9063_REG_PAGE_CON,
|
||||
.selector_mask = 1 << DA9063_I2C_PAGE_SEL_SHIFT,
|
||||
.selector_shift = DA9063_I2C_PAGE_SEL_SHIFT,
|
||||
.window_start = 0,
|
||||
.window_len = 256,
|
||||
}
|
||||
};
|
||||
|
||||
static struct regmap_config da9063_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.ranges = da9063_range_cfg,
|
||||
.num_ranges = ARRAY_SIZE(da9063_range_cfg),
|
||||
.max_register = DA9063_REG_CHIP_VARIANT,
|
||||
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
|
||||
.rd_table = &da9063_readable_table,
|
||||
.wr_table = &da9063_writeable_table,
|
||||
.volatile_table = &da9063_volatile_table,
|
||||
};
|
||||
|
||||
static int da9063_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct da9063 *da9063;
|
||||
int ret;
|
||||
|
||||
da9063 = devm_kzalloc(&i2c->dev, sizeof(struct da9063), GFP_KERNEL);
|
||||
if (da9063 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, da9063);
|
||||
da9063->dev = &i2c->dev;
|
||||
da9063->chip_irq = i2c->irq;
|
||||
|
||||
da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);
|
||||
if (IS_ERR(da9063->regmap)) {
|
||||
ret = PTR_ERR(da9063->regmap);
|
||||
dev_err(da9063->dev, "Failed to allocate register map: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return da9063_device_init(da9063, i2c->irq);
|
||||
}
|
||||
|
||||
static int da9063_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct da9063 *da9063 = i2c_get_clientdata(i2c);
|
||||
|
||||
da9063_device_exit(da9063);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id da9063_i2c_id[] = {
|
||||
{"da9063", PMIC_DA9063},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, da9063_i2c_id);
|
||||
|
||||
static struct i2c_driver da9063_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "da9063",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = da9063_i2c_probe,
|
||||
.remove = da9063_i2c_remove,
|
||||
.id_table = da9063_i2c_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(da9063_i2c_driver);
|
193
drivers/mfd/da9063-irq.c
Normal file
193
drivers/mfd/da9063-irq.c
Normal file
@ -0,0 +1,193 @@
|
||||
/* da9063-irq.c: Interrupts support for Dialog DA9063
|
||||
*
|
||||
* Copyright 2012 Dialog Semiconductor Ltd.
|
||||
* Copyright 2013 Philipp Zabel, Pengutronix
|
||||
*
|
||||
* Author: Michal Hajduk <michal.hajduk@diasemi.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/da9063/core.h>
|
||||
#include <linux/mfd/da9063/pdata.h>
|
||||
|
||||
#define DA9063_REG_EVENT_A_OFFSET 0
|
||||
#define DA9063_REG_EVENT_B_OFFSET 1
|
||||
#define DA9063_REG_EVENT_C_OFFSET 2
|
||||
#define DA9063_REG_EVENT_D_OFFSET 3
|
||||
#define EVENTS_BUF_LEN 4
|
||||
|
||||
static const u8 mask_events_buf[] = { [0 ... (EVENTS_BUF_LEN - 1)] = ~0 };
|
||||
|
||||
struct da9063_irq_data {
|
||||
u16 reg;
|
||||
u8 mask;
|
||||
};
|
||||
|
||||
static struct regmap_irq da9063_irqs[] = {
|
||||
/* DA9063 event A register */
|
||||
[DA9063_IRQ_ONKEY] = {
|
||||
.reg_offset = DA9063_REG_EVENT_A_OFFSET,
|
||||
.mask = DA9063_M_ONKEY,
|
||||
},
|
||||
[DA9063_IRQ_ALARM] = {
|
||||
.reg_offset = DA9063_REG_EVENT_A_OFFSET,
|
||||
.mask = DA9063_M_ALARM,
|
||||
},
|
||||
[DA9063_IRQ_TICK] = {
|
||||
.reg_offset = DA9063_REG_EVENT_A_OFFSET,
|
||||
.mask = DA9063_M_TICK,
|
||||
},
|
||||
[DA9063_IRQ_ADC_RDY] = {
|
||||
.reg_offset = DA9063_REG_EVENT_A_OFFSET,
|
||||
.mask = DA9063_M_ADC_RDY,
|
||||
},
|
||||
[DA9063_IRQ_SEQ_RDY] = {
|
||||
.reg_offset = DA9063_REG_EVENT_A_OFFSET,
|
||||
.mask = DA9063_M_SEQ_RDY,
|
||||
},
|
||||
/* DA9063 event B register */
|
||||
[DA9063_IRQ_WAKE] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_WAKE,
|
||||
},
|
||||
[DA9063_IRQ_TEMP] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_TEMP,
|
||||
},
|
||||
[DA9063_IRQ_COMP_1V2] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_COMP_1V2,
|
||||
},
|
||||
[DA9063_IRQ_LDO_LIM] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_LDO_LIM,
|
||||
},
|
||||
[DA9063_IRQ_REG_UVOV] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_UVOV,
|
||||
},
|
||||
[DA9063_IRQ_VDD_MON] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_VDD_MON,
|
||||
},
|
||||
[DA9063_IRQ_WARN] = {
|
||||
.reg_offset = DA9063_REG_EVENT_B_OFFSET,
|
||||
.mask = DA9063_M_VDD_WARN,
|
||||
},
|
||||
/* DA9063 event C register */
|
||||
[DA9063_IRQ_GPI0] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI0,
|
||||
},
|
||||
[DA9063_IRQ_GPI1] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI1,
|
||||
},
|
||||
[DA9063_IRQ_GPI2] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI2,
|
||||
},
|
||||
[DA9063_IRQ_GPI3] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI3,
|
||||
},
|
||||
[DA9063_IRQ_GPI4] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI4,
|
||||
},
|
||||
[DA9063_IRQ_GPI5] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI5,
|
||||
},
|
||||
[DA9063_IRQ_GPI6] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI6,
|
||||
},
|
||||
[DA9063_IRQ_GPI7] = {
|
||||
.reg_offset = DA9063_REG_EVENT_C_OFFSET,
|
||||
.mask = DA9063_M_GPI7,
|
||||
},
|
||||
/* DA9063 event D register */
|
||||
[DA9063_IRQ_GPI8] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI8,
|
||||
},
|
||||
[DA9063_IRQ_GPI9] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI9,
|
||||
},
|
||||
[DA9063_IRQ_GPI10] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI10,
|
||||
},
|
||||
[DA9063_IRQ_GPI11] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI11,
|
||||
},
|
||||
[DA9063_IRQ_GPI12] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI12,
|
||||
},
|
||||
[DA9063_IRQ_GPI13] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI13,
|
||||
},
|
||||
[DA9063_IRQ_GPI14] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI14,
|
||||
},
|
||||
[DA9063_IRQ_GPI15] = {
|
||||
.reg_offset = DA9063_REG_EVENT_D_OFFSET,
|
||||
.mask = DA9063_M_GPI15,
|
||||
},
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip da9063_irq_chip = {
|
||||
.name = "da9063-irq",
|
||||
.irqs = da9063_irqs,
|
||||
.num_irqs = DA9063_NUM_IRQ,
|
||||
|
||||
.num_regs = 4,
|
||||
.status_base = DA9063_REG_EVENT_A,
|
||||
.mask_base = DA9063_REG_IRQ_MASK_A,
|
||||
.ack_base = DA9063_REG_EVENT_A,
|
||||
.init_ack_masked = true,
|
||||
};
|
||||
|
||||
int da9063_irq_init(struct da9063 *da9063)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!da9063->chip_irq) {
|
||||
dev_err(da9063->dev, "No IRQ configured\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_add_irq_chip(da9063->regmap, da9063->chip_irq,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
|
||||
da9063->irq_base, &da9063_irq_chip,
|
||||
&da9063->regmap_irq);
|
||||
if (ret) {
|
||||
dev_err(da9063->dev, "Failed to reguest IRQ %d: %d\n",
|
||||
da9063->chip_irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void da9063_irq_exit(struct da9063 *da9063)
|
||||
{
|
||||
regmap_del_irq_chip(da9063->chip_irq, da9063->regmap_irq);
|
||||
}
|
@ -27,21 +27,16 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <sound/pcm.h>
|
||||
|
||||
#include <linux/mfd/davinci_voicecodec.h>
|
||||
|
||||
u32 davinci_vc_read(struct davinci_vc *davinci_vc, int reg)
|
||||
{
|
||||
return __raw_readl(davinci_vc->base + reg);
|
||||
}
|
||||
|
||||
void davinci_vc_write(struct davinci_vc *davinci_vc,
|
||||
int reg, u32 val)
|
||||
{
|
||||
__raw_writel(val, davinci_vc->base + reg);
|
||||
}
|
||||
static struct regmap_config davinci_vc_regmap = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
};
|
||||
|
||||
static int __init davinci_vc_probe(struct platform_device *pdev)
|
||||
{
|
||||
@ -74,6 +69,14 @@ static int __init davinci_vc_probe(struct platform_device *pdev)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
davinci_vc->regmap = devm_regmap_init_mmio(&pdev->dev,
|
||||
davinci_vc->base,
|
||||
&davinci_vc_regmap);
|
||||
if (IS_ERR(davinci_vc->regmap)) {
|
||||
ret = PTR_ERR(davinci_vc->regmap);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "no DMA resource\n");
|
||||
|
@ -465,7 +465,7 @@ static DEFINE_SPINLOCK(clk_mgt_lock);
|
||||
|
||||
#define CLK_MGT_ENTRY(_name, _branch, _clk38div)[PRCMU_##_name] = \
|
||||
{ (PRCM_##_name##_MGT), 0 , _branch, _clk38div}
|
||||
struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
|
||||
static struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
|
||||
CLK_MGT_ENTRY(SGACLK, PLL_DIV, false),
|
||||
CLK_MGT_ENTRY(UARTCLK, PLL_FIX, true),
|
||||
CLK_MGT_ENTRY(MSP02CLK, PLL_FIX, true),
|
||||
@ -2319,7 +2319,7 @@ unlock_and_return:
|
||||
/**
|
||||
* prcmu_ac_sleep_req - called when ARM no longer needs to talk to modem
|
||||
*/
|
||||
void prcmu_ac_sleep_req()
|
||||
void prcmu_ac_sleep_req(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
|
@ -315,8 +315,8 @@ static int add_children(struct i2c_client *client)
|
||||
}
|
||||
|
||||
/* MMC/SD inputs -- right after the last config input */
|
||||
if (client->dev.platform_data) {
|
||||
void (*mmcsd_setup)(unsigned) = client->dev.platform_data;
|
||||
if (dev_get_platdata(&client->dev)) {
|
||||
void (*mmcsd_setup)(unsigned) = dev_get_platdata(&client->dev);
|
||||
|
||||
mmcsd_setup(dm355evm_msp_gpio.base + 8 + 5);
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ static void pcap_msr_work(struct work_struct *work)
|
||||
static void pcap_isr_work(struct work_struct *work)
|
||||
{
|
||||
struct pcap_chip *pcap = container_of(work, struct pcap_chip, isr_work);
|
||||
struct pcap_platform_data *pdata = pcap->spi->dev.platform_data;
|
||||
struct pcap_platform_data *pdata = dev_get_platdata(&pcap->spi->dev);
|
||||
u32 msr, isr, int_sel, service;
|
||||
int irq;
|
||||
|
||||
@ -394,7 +394,7 @@ static int pcap_add_subdev(struct pcap_chip *pcap,
|
||||
static int ezx_pcap_remove(struct spi_device *spi)
|
||||
{
|
||||
struct pcap_chip *pcap = spi_get_drvdata(spi);
|
||||
struct pcap_platform_data *pdata = spi->dev.platform_data;
|
||||
struct pcap_platform_data *pdata = dev_get_platdata(&spi->dev);
|
||||
int i, adc_irq;
|
||||
|
||||
/* remove all registered subdevs */
|
||||
@ -420,7 +420,7 @@ static int ezx_pcap_remove(struct spi_device *spi)
|
||||
|
||||
static int ezx_pcap_probe(struct spi_device *spi)
|
||||
{
|
||||
struct pcap_platform_data *pdata = spi->dev.platform_data;
|
||||
struct pcap_platform_data *pdata = dev_get_platdata(&spi->dev);
|
||||
struct pcap_chip *pcap;
|
||||
int i, adc_irq;
|
||||
int ret = -ENODEV;
|
||||
|
@ -261,7 +261,7 @@ static void egpio_write_cache(struct egpio_info *ei)
|
||||
|
||||
static int __init egpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct htc_egpio_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct htc_egpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct resource *res;
|
||||
struct egpio_info *ei;
|
||||
struct gpio_chip *chip;
|
||||
|
@ -340,7 +340,7 @@ static int htcpld_setup_chip_irq(
|
||||
int ret = 0;
|
||||
|
||||
/* Get the platform and driver data */
|
||||
pdata = dev->platform_data;
|
||||
pdata = dev_get_platdata(dev);
|
||||
htcpld = platform_get_drvdata(pdev);
|
||||
chip = &htcpld->chip[chip_index];
|
||||
plat_chip_data = &pdata->chip[chip_index];
|
||||
@ -375,7 +375,7 @@ static int htcpld_register_chip_i2c(
|
||||
struct i2c_board_info info;
|
||||
|
||||
/* Get the platform and driver data */
|
||||
pdata = dev->platform_data;
|
||||
pdata = dev_get_platdata(dev);
|
||||
htcpld = platform_get_drvdata(pdev);
|
||||
chip = &htcpld->chip[chip_index];
|
||||
plat_chip_data = &pdata->chip[chip_index];
|
||||
@ -447,7 +447,7 @@ static int htcpld_register_chip_gpio(
|
||||
int ret = 0;
|
||||
|
||||
/* Get the platform and driver data */
|
||||
pdata = dev->platform_data;
|
||||
pdata = dev_get_platdata(dev);
|
||||
htcpld = platform_get_drvdata(pdev);
|
||||
chip = &htcpld->chip[chip_index];
|
||||
plat_chip_data = &pdata->chip[chip_index];
|
||||
@ -509,7 +509,7 @@ static int htcpld_setup_chips(struct platform_device *pdev)
|
||||
int i;
|
||||
|
||||
/* Get the platform and driver data */
|
||||
pdata = dev->platform_data;
|
||||
pdata = dev_get_platdata(dev);
|
||||
htcpld = platform_get_drvdata(pdev);
|
||||
|
||||
/* Setup each chip's output GPIOs */
|
||||
@ -574,7 +574,7 @@ static int htcpld_core_probe(struct platform_device *pdev)
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
pdata = dev->platform_data;
|
||||
pdata = dev_get_platdata(dev);
|
||||
if (!pdata) {
|
||||
dev_warn(dev, "Platform data not found for htcpld core!\n");
|
||||
return -ENXIO;
|
||||
|
@ -126,7 +126,7 @@ static struct mfd_cell ds1wm_cell __initdata = {
|
||||
|
||||
static int __init pasic3_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct pasic3_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct pasic3_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct device *dev = &pdev->dev;
|
||||
struct pasic3_data *asic;
|
||||
struct resource *r;
|
||||
|
@ -310,7 +310,7 @@ EXPORT_SYMBOL_GPL(intel_msic_irq_read);
|
||||
static int intel_msic_init_devices(struct intel_msic *msic)
|
||||
{
|
||||
struct platform_device *pdev = msic->pdev;
|
||||
struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct intel_msic_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
int ret, i;
|
||||
|
||||
if (pdata->gpio) {
|
||||
@ -372,7 +372,7 @@ static void intel_msic_remove_devices(struct intel_msic *msic)
|
||||
|
||||
static int intel_msic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct intel_msic_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct intel_msic *msic;
|
||||
struct resource *res;
|
||||
u8 id0, id1;
|
||||
|
@ -258,7 +258,7 @@ EXPORT_SYMBOL_GPL(kempld_write32);
|
||||
*/
|
||||
void kempld_get_mutex(struct kempld_device_data *pld)
|
||||
{
|
||||
struct kempld_platform_data *pdata = pld->dev->platform_data;
|
||||
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
|
||||
mutex_lock(&pld->lock);
|
||||
pdata->get_hardware_mutex(pld);
|
||||
@ -271,7 +271,7 @@ EXPORT_SYMBOL_GPL(kempld_get_mutex);
|
||||
*/
|
||||
void kempld_release_mutex(struct kempld_device_data *pld)
|
||||
{
|
||||
struct kempld_platform_data *pdata = pld->dev->platform_data;
|
||||
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
|
||||
pdata->release_hardware_mutex(pld);
|
||||
mutex_unlock(&pld->lock);
|
||||
@ -288,7 +288,7 @@ EXPORT_SYMBOL_GPL(kempld_release_mutex);
|
||||
*/
|
||||
static int kempld_get_info(struct kempld_device_data *pld)
|
||||
{
|
||||
struct kempld_platform_data *pdata = pld->dev->platform_data;
|
||||
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
|
||||
return pdata->get_info(pld);
|
||||
}
|
||||
@ -302,7 +302,7 @@ static int kempld_get_info(struct kempld_device_data *pld)
|
||||
*/
|
||||
static int kempld_register_cells(struct kempld_device_data *pld)
|
||||
{
|
||||
struct kempld_platform_data *pdata = pld->dev->platform_data;
|
||||
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
|
||||
return pdata->register_cells(pld);
|
||||
}
|
||||
@ -357,7 +357,7 @@ static int kempld_detect_device(struct kempld_device_data *pld)
|
||||
|
||||
static int kempld_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct kempld_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct kempld_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct device *dev = &pdev->dev;
|
||||
struct kempld_device_data *pld;
|
||||
struct resource *ioport;
|
||||
@ -394,7 +394,7 @@ static int kempld_probe(struct platform_device *pdev)
|
||||
static int kempld_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct kempld_device_data *pld = platform_get_drvdata(pdev);
|
||||
struct kempld_platform_data *pdata = pld->dev->platform_data;
|
||||
struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
|
||||
|
||||
mfd_remove_devices(&pdev->dev);
|
||||
pdata->release_hardware_mutex(pld);
|
||||
@ -412,6 +412,15 @@ static struct platform_driver kempld_driver = {
|
||||
};
|
||||
|
||||
static struct dmi_system_id __initdata kempld_dmi_table[] = {
|
||||
{
|
||||
.ident = "BHL6",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "COMe-bHL6"),
|
||||
},
|
||||
.driver_data = (void *)&kempld_platform_data_generic,
|
||||
.callback = kempld_create_platform_device,
|
||||
},
|
||||
{
|
||||
.ident = "CCR2",
|
||||
.matches = {
|
||||
@ -596,6 +605,15 @@ static struct dmi_system_id __initdata kempld_dmi_table[] = {
|
||||
.driver_data = (void *)&kempld_platform_data_generic,
|
||||
.callback = kempld_create_platform_device,
|
||||
},
|
||||
{
|
||||
.ident = "UTH6",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "COMe-cTH6"),
|
||||
},
|
||||
.driver_data = (void *)&kempld_platform_data_generic,
|
||||
.callback = kempld_create_platform_device,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(dmi, kempld_dmi_table);
|
||||
|
@ -384,7 +384,7 @@ static struct attribute_group lm3533_attribute_group = {
|
||||
|
||||
static int lm3533_device_als_init(struct lm3533 *lm3533)
|
||||
{
|
||||
struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
|
||||
struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
|
||||
int ret;
|
||||
|
||||
if (!pdata->als)
|
||||
@ -407,7 +407,7 @@ static int lm3533_device_als_init(struct lm3533 *lm3533)
|
||||
|
||||
static int lm3533_device_bl_init(struct lm3533 *lm3533)
|
||||
{
|
||||
struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
|
||||
struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
@ -436,7 +436,7 @@ static int lm3533_device_bl_init(struct lm3533 *lm3533)
|
||||
|
||||
static int lm3533_device_led_init(struct lm3533 *lm3533)
|
||||
{
|
||||
struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
|
||||
struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
@ -481,7 +481,7 @@ static int lm3533_device_setup(struct lm3533 *lm3533,
|
||||
|
||||
static int lm3533_device_init(struct lm3533 *lm3533)
|
||||
{
|
||||
struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
|
||||
struct lm3533_platform_data *pdata = dev_get_platdata(lm3533->dev);
|
||||
int ret;
|
||||
|
||||
dev_dbg(lm3533->dev, "%s\n", __func__);
|
||||
|
@ -173,7 +173,7 @@ static const struct regmap_config lp8788_regmap_config = {
|
||||
static int lp8788_probe(struct i2c_client *cl, const struct i2c_device_id *id)
|
||||
{
|
||||
struct lp8788 *lp;
|
||||
struct lp8788_platform_data *pdata = cl->dev.platform_data;
|
||||
struct lp8788_platform_data *pdata = dev_get_platdata(&cl->dev);
|
||||
int ret;
|
||||
|
||||
lp = devm_kzalloc(&cl->dev, sizeof(struct lp8788), GFP_KERNEL);
|
||||
|
@ -213,7 +213,7 @@ enum lpc_chipsets {
|
||||
LPC_COLETO, /* Coleto Creek */
|
||||
};
|
||||
|
||||
struct lpc_ich_info lpc_chipset_info[] = {
|
||||
static struct lpc_ich_info lpc_chipset_info[] = {
|
||||
[LPC_ICH] = {
|
||||
.name = "ICH",
|
||||
.iTCO_version = 1,
|
||||
|
@ -77,7 +77,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max77686_dev *max77686 = NULL;
|
||||
struct max77686_platform_data *pdata = i2c->dev.platform_data;
|
||||
struct max77686_platform_data *pdata = dev_get_platdata(&i2c->dev);
|
||||
unsigned int data;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -110,7 +110,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max77693_dev *max77693;
|
||||
struct max77693_platform_data *pdata = i2c->dev.platform_data;
|
||||
struct max77693_platform_data *pdata = dev_get_platdata(&i2c->dev);
|
||||
u8 reg_data;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -151,7 +151,7 @@ static int max8925_dt_init(struct device_node *np, struct device *dev,
|
||||
static int max8925_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max8925_platform_data *pdata = client->dev.platform_data;
|
||||
struct max8925_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
static struct max8925_chip *chip;
|
||||
struct device_node *node = client->dev.of_node;
|
||||
|
||||
|
@ -51,7 +51,7 @@ static struct mfd_cell max8997_devs[] = {
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_device_id max8997_pmic_dt_match[] = {
|
||||
{ .compatible = "maxim,max8997-pmic", .data = TYPE_MAX8997 },
|
||||
{ .compatible = "maxim,max8997-pmic", .data = (void *)TYPE_MAX8997 },
|
||||
{},
|
||||
};
|
||||
#endif
|
||||
@ -188,10 +188,11 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max8997_dev *max8997;
|
||||
struct max8997_platform_data *pdata = i2c->dev.platform_data;
|
||||
struct max8997_platform_data *pdata = dev_get_platdata(&i2c->dev);
|
||||
int ret = 0;
|
||||
|
||||
max8997 = kzalloc(sizeof(struct max8997_dev), GFP_KERNEL);
|
||||
max8997 = devm_kzalloc(&i2c->dev, sizeof(struct max8997_dev),
|
||||
GFP_KERNEL);
|
||||
if (max8997 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -203,14 +204,12 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
|
||||
|
||||
if (max8997->dev->of_node) {
|
||||
pdata = max8997_i2c_parse_dt_pdata(max8997->dev);
|
||||
if (IS_ERR(pdata)) {
|
||||
ret = PTR_ERR(pdata);
|
||||
goto err;
|
||||
}
|
||||
if (IS_ERR(pdata))
|
||||
return PTR_ERR(pdata);
|
||||
}
|
||||
|
||||
if (!pdata)
|
||||
goto err;
|
||||
return ret;
|
||||
|
||||
max8997->pdata = pdata;
|
||||
max8997->ono = pdata->ono;
|
||||
@ -250,8 +249,6 @@ err_mfd:
|
||||
i2c_unregister_device(max8997->muic);
|
||||
i2c_unregister_device(max8997->haptic);
|
||||
i2c_unregister_device(max8997->rtc);
|
||||
err:
|
||||
kfree(max8997);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -263,7 +260,6 @@ static int max8997_i2c_remove(struct i2c_client *i2c)
|
||||
i2c_unregister_device(max8997->muic);
|
||||
i2c_unregister_device(max8997->haptic);
|
||||
i2c_unregister_device(max8997->rtc);
|
||||
kfree(max8997);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -184,11 +184,12 @@ static inline int max8998_i2c_get_driver_data(struct i2c_client *i2c,
|
||||
static int max8998_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max8998_platform_data *pdata = i2c->dev.platform_data;
|
||||
struct max8998_platform_data *pdata = dev_get_platdata(&i2c->dev);
|
||||
struct max8998_dev *max8998;
|
||||
int ret = 0;
|
||||
|
||||
max8998 = kzalloc(sizeof(struct max8998_dev), GFP_KERNEL);
|
||||
max8998 = devm_kzalloc(&i2c->dev, sizeof(struct max8998_dev),
|
||||
GFP_KERNEL);
|
||||
if (max8998 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -246,7 +247,6 @@ err:
|
||||
mfd_remove_devices(max8998->dev);
|
||||
max8998_irq_exit(max8998);
|
||||
i2c_unregister_device(max8998->rtc);
|
||||
kfree(max8998);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -257,7 +257,6 @@ static int max8998_i2c_remove(struct i2c_client *i2c)
|
||||
mfd_remove_devices(max8998->dev);
|
||||
max8998_irq_exit(max8998);
|
||||
i2c_unregister_device(max8998->rtc);
|
||||
kfree(max8998);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ static struct mcp_ops mcp_sa11x0 = {
|
||||
|
||||
static int mcp_sa11x0_probe(struct platform_device *dev)
|
||||
{
|
||||
struct mcp_plat_data *data = dev->dev.platform_data;
|
||||
struct mcp_plat_data *data = dev_get_platdata(&dev->dev);
|
||||
struct resource *mem0, *mem1;
|
||||
struct mcp_sa11x0 *m;
|
||||
struct mcp *mcp;
|
||||
|
@ -442,7 +442,7 @@ void menelaus_unregister_mmc_callback(void)
|
||||
menelaus_remove_irq_work(MENELAUS_MMC_S2D1_IRQ);
|
||||
|
||||
the_menelaus->mmc_callback = NULL;
|
||||
the_menelaus->mmc_callback_data = 0;
|
||||
the_menelaus->mmc_callback_data = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(menelaus_unregister_mmc_callback);
|
||||
|
||||
@ -466,7 +466,7 @@ static int menelaus_set_voltage(const struct menelaus_vtg *vtg, int mV,
|
||||
struct i2c_client *c = the_menelaus->client;
|
||||
|
||||
mutex_lock(&the_menelaus->lock);
|
||||
if (vtg == 0)
|
||||
if (!vtg)
|
||||
goto set_voltage;
|
||||
|
||||
ret = menelaus_read_reg(vtg->vtg_reg);
|
||||
@ -1189,7 +1189,7 @@ static int menelaus_probe(struct i2c_client *client,
|
||||
int rev = 0, val;
|
||||
int err = 0;
|
||||
struct menelaus_platform_data *menelaus_pdata =
|
||||
client->dev.platform_data;
|
||||
dev_get_platdata(&client->dev);
|
||||
|
||||
if (the_menelaus) {
|
||||
dev_dbg(&client->dev, "only one %s for now\n",
|
||||
@ -1197,7 +1197,7 @@ static int menelaus_probe(struct i2c_client *client,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
menelaus = kzalloc(sizeof *menelaus, GFP_KERNEL);
|
||||
menelaus = devm_kzalloc(&client->dev, sizeof(*menelaus), GFP_KERNEL);
|
||||
if (!menelaus)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -1210,8 +1210,7 @@ static int menelaus_probe(struct i2c_client *client,
|
||||
rev = menelaus_read_reg(MENELAUS_REV);
|
||||
if (rev < 0) {
|
||||
pr_err(DRIVER_NAME ": device not found");
|
||||
err = -ENODEV;
|
||||
goto fail1;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Ack and disable all Menelaus interrupts */
|
||||
@ -1231,7 +1230,7 @@ static int menelaus_probe(struct i2c_client *client,
|
||||
if (err) {
|
||||
dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
|
||||
client->irq, err);
|
||||
goto fail1;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1242,7 +1241,7 @@ static int menelaus_probe(struct i2c_client *client,
|
||||
|
||||
val = menelaus_read_reg(MENELAUS_VCORE_CTRL1);
|
||||
if (val < 0)
|
||||
goto fail2;
|
||||
goto fail;
|
||||
if (val & (1 << 7))
|
||||
menelaus->vcore_hw_mode = 1;
|
||||
else
|
||||
@ -1251,17 +1250,15 @@ static int menelaus_probe(struct i2c_client *client,
|
||||
if (menelaus_pdata != NULL && menelaus_pdata->late_init != NULL) {
|
||||
err = menelaus_pdata->late_init(&client->dev);
|
||||
if (err < 0)
|
||||
goto fail2;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
menelaus_rtc_init(menelaus);
|
||||
|
||||
return 0;
|
||||
fail2:
|
||||
fail:
|
||||
free_irq(client->irq, menelaus);
|
||||
flush_work(&menelaus->work);
|
||||
fail1:
|
||||
kfree(menelaus);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1271,7 +1268,6 @@ static int __exit menelaus_remove(struct i2c_client *client)
|
||||
|
||||
free_irq(client->irq, menelaus);
|
||||
flush_work(&menelaus->work);
|
||||
kfree(menelaus);
|
||||
the_menelaus = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
@ -96,6 +96,8 @@ static int mfd_add_device(struct device *parent, int id,
|
||||
|
||||
pdev->dev.parent = parent;
|
||||
pdev->dev.type = &mfd_dev_type;
|
||||
pdev->dev.dma_mask = parent->dma_mask;
|
||||
pdev->dev.dma_parms = parent->dma_parms;
|
||||
|
||||
if (parent->of_node && cell->of_compatible) {
|
||||
for_each_child_of_node(parent->of_node, np) {
|
||||
|
@ -114,7 +114,7 @@ struct usbhs_hcd_omap {
|
||||
};
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
const char usbhs_driver_name[] = USBHS_DRIVER_NAME;
|
||||
static const char usbhs_driver_name[] = USBHS_DRIVER_NAME;
|
||||
static u64 usbhs_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -232,7 +232,7 @@ err_end:
|
||||
static int omap_usbhs_alloc_children(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct usbhs_omap_platform_data *pdata = dev->platform_data;
|
||||
struct usbhs_omap_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct platform_device *ehci;
|
||||
struct platform_device *ohci;
|
||||
struct resource *res;
|
||||
@ -571,7 +571,7 @@ static struct of_device_id usbhs_child_match_table[] = {
|
||||
static int usbhs_omap_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct usbhs_omap_platform_data *pdata = dev->platform_data;
|
||||
struct usbhs_omap_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct usbhs_hcd_omap *omap;
|
||||
struct resource *res;
|
||||
int ret = 0;
|
||||
|
@ -25,6 +25,52 @@
|
||||
#include <linux/mfd/palmas.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#define PALMAS_EXT_REQ (PALMAS_EXT_CONTROL_ENABLE1 | \
|
||||
PALMAS_EXT_CONTROL_ENABLE2 | \
|
||||
PALMAS_EXT_CONTROL_NSLEEP)
|
||||
|
||||
struct palmas_sleep_requestor_info {
|
||||
int id;
|
||||
int reg_offset;
|
||||
int bit_pos;
|
||||
};
|
||||
|
||||
#define EXTERNAL_REQUESTOR(_id, _offset, _pos) \
|
||||
[PALMAS_EXTERNAL_REQSTR_ID_##_id] = { \
|
||||
.id = PALMAS_EXTERNAL_REQSTR_ID_##_id, \
|
||||
.reg_offset = _offset, \
|
||||
.bit_pos = _pos, \
|
||||
}
|
||||
|
||||
static struct palmas_sleep_requestor_info sleep_req_info[] = {
|
||||
EXTERNAL_REQUESTOR(REGEN1, 0, 0),
|
||||
EXTERNAL_REQUESTOR(REGEN2, 0, 1),
|
||||
EXTERNAL_REQUESTOR(SYSEN1, 0, 2),
|
||||
EXTERNAL_REQUESTOR(SYSEN2, 0, 3),
|
||||
EXTERNAL_REQUESTOR(CLK32KG, 0, 4),
|
||||
EXTERNAL_REQUESTOR(CLK32KGAUDIO, 0, 5),
|
||||
EXTERNAL_REQUESTOR(REGEN3, 0, 6),
|
||||
EXTERNAL_REQUESTOR(SMPS12, 1, 0),
|
||||
EXTERNAL_REQUESTOR(SMPS3, 1, 1),
|
||||
EXTERNAL_REQUESTOR(SMPS45, 1, 2),
|
||||
EXTERNAL_REQUESTOR(SMPS6, 1, 3),
|
||||
EXTERNAL_REQUESTOR(SMPS7, 1, 4),
|
||||
EXTERNAL_REQUESTOR(SMPS8, 1, 5),
|
||||
EXTERNAL_REQUESTOR(SMPS9, 1, 6),
|
||||
EXTERNAL_REQUESTOR(SMPS10, 1, 7),
|
||||
EXTERNAL_REQUESTOR(LDO1, 2, 0),
|
||||
EXTERNAL_REQUESTOR(LDO2, 2, 1),
|
||||
EXTERNAL_REQUESTOR(LDO3, 2, 2),
|
||||
EXTERNAL_REQUESTOR(LDO4, 2, 3),
|
||||
EXTERNAL_REQUESTOR(LDO5, 2, 4),
|
||||
EXTERNAL_REQUESTOR(LDO6, 2, 5),
|
||||
EXTERNAL_REQUESTOR(LDO7, 2, 6),
|
||||
EXTERNAL_REQUESTOR(LDO8, 2, 7),
|
||||
EXTERNAL_REQUESTOR(LDO9, 3, 0),
|
||||
EXTERNAL_REQUESTOR(LDOLN, 3, 1),
|
||||
EXTERNAL_REQUESTOR(LDOUSB, 3, 2),
|
||||
};
|
||||
|
||||
static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = {
|
||||
{
|
||||
.reg_bits = 8,
|
||||
@ -186,6 +232,57 @@ static struct regmap_irq_chip palmas_irq_chip = {
|
||||
PALMAS_INT1_MASK),
|
||||
};
|
||||
|
||||
int palmas_ext_control_req_config(struct palmas *palmas,
|
||||
enum palmas_external_requestor_id id, int ext_ctrl, bool enable)
|
||||
{
|
||||
int preq_mask_bit = 0;
|
||||
int reg_add = 0;
|
||||
int bit_pos;
|
||||
int ret;
|
||||
|
||||
if (!(ext_ctrl & PALMAS_EXT_REQ))
|
||||
return 0;
|
||||
|
||||
if (id >= PALMAS_EXTERNAL_REQSTR_ID_MAX)
|
||||
return 0;
|
||||
|
||||
if (ext_ctrl & PALMAS_EXT_CONTROL_NSLEEP) {
|
||||
reg_add = PALMAS_NSLEEP_RES_ASSIGN;
|
||||
preq_mask_bit = 0;
|
||||
} else if (ext_ctrl & PALMAS_EXT_CONTROL_ENABLE1) {
|
||||
reg_add = PALMAS_ENABLE1_RES_ASSIGN;
|
||||
preq_mask_bit = 1;
|
||||
} else if (ext_ctrl & PALMAS_EXT_CONTROL_ENABLE2) {
|
||||
reg_add = PALMAS_ENABLE2_RES_ASSIGN;
|
||||
preq_mask_bit = 2;
|
||||
}
|
||||
|
||||
bit_pos = sleep_req_info[id].bit_pos;
|
||||
reg_add += sleep_req_info[id].reg_offset;
|
||||
if (enable)
|
||||
ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
|
||||
reg_add, BIT(bit_pos), BIT(bit_pos));
|
||||
else
|
||||
ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
|
||||
reg_add, BIT(bit_pos), 0);
|
||||
if (ret < 0) {
|
||||
dev_err(palmas->dev, "Resource reg 0x%02x update failed %d\n",
|
||||
reg_add, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Unmask the PREQ */
|
||||
ret = palmas_update_bits(palmas, PALMAS_PMU_CONTROL_BASE,
|
||||
PALMAS_POWER_CTRL, BIT(preq_mask_bit), 0);
|
||||
if (ret < 0) {
|
||||
dev_err(palmas->dev, "POWER_CTRL register update failed %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(palmas_ext_control_req_config);
|
||||
|
||||
static int palmas_set_pdata_irq_flag(struct i2c_client *i2c,
|
||||
struct palmas_platform_data *pdata)
|
||||
{
|
||||
@ -229,6 +326,32 @@ static void palmas_dt_to_pdata(struct i2c_client *i2c,
|
||||
PALMAS_POWER_CTRL_ENABLE2_MASK;
|
||||
if (i2c->irq)
|
||||
palmas_set_pdata_irq_flag(i2c, pdata);
|
||||
|
||||
pdata->pm_off = of_property_read_bool(node,
|
||||
"ti,system-power-controller");
|
||||
}
|
||||
|
||||
static struct palmas *palmas_dev;
|
||||
static void palmas_power_off(void)
|
||||
{
|
||||
unsigned int addr;
|
||||
int ret, slave;
|
||||
|
||||
if (!palmas_dev)
|
||||
return;
|
||||
|
||||
slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE);
|
||||
addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_DEV_CTRL);
|
||||
|
||||
ret = regmap_update_bits(
|
||||
palmas_dev->regmap[slave],
|
||||
addr,
|
||||
PALMAS_DEV_CTRL_DEV_ON,
|
||||
0);
|
||||
|
||||
if (ret)
|
||||
pr_err("%s: Unable to write to DEV_CTRL_DEV_ON: %d\n",
|
||||
__func__, ret);
|
||||
}
|
||||
|
||||
static unsigned int palmas_features = PALMAS_PMIC_FEATURE_SMPS10_BOOST;
|
||||
@ -423,11 +546,14 @@ no_irq:
|
||||
*/
|
||||
if (node) {
|
||||
ret = of_platform_populate(node, NULL, NULL, &i2c->dev);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
goto err_irq;
|
||||
else
|
||||
} else if (pdata->pm_off && !pm_power_off) {
|
||||
palmas_dev = palmas;
|
||||
pm_power_off = palmas_power_off;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
|
@ -203,7 +203,7 @@ static int pcf50633_adc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct pcf50633_adc *adc;
|
||||
|
||||
adc = kzalloc(sizeof(*adc), GFP_KERNEL);
|
||||
adc = devm_kzalloc(&pdev->dev, sizeof(*adc), GFP_KERNEL);
|
||||
if (!adc)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -236,7 +236,6 @@ static int pcf50633_adc_remove(struct platform_device *pdev)
|
||||
kfree(adc->queue[i]);
|
||||
|
||||
mutex_unlock(&adc->queue_mutex);
|
||||
kfree(adc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ static int pcf50633_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *ids)
|
||||
{
|
||||
struct pcf50633 *pcf;
|
||||
struct pcf50633_platform_data *pdata = client->dev.platform_data;
|
||||
struct pcf50633_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
int i, ret;
|
||||
int version, variant;
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define pr_fmt(fmt) "%s: " fmt, __func__
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
@ -106,7 +107,7 @@ static int pm8921_add_subdevices(const struct pm8921_platform_data
|
||||
|
||||
static int pm8921_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct pm8921_platform_data *pdata = pdev->dev.platform_data;
|
||||
const struct pm8921_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct pm8921 *pmic;
|
||||
int rc;
|
||||
u8 val;
|
||||
@ -117,7 +118,7 @@ static int pm8921_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pmic = kzalloc(sizeof(struct pm8921), GFP_KERNEL);
|
||||
pmic = devm_kzalloc(&pdev->dev, sizeof(struct pm8921), GFP_KERNEL);
|
||||
if (!pmic) {
|
||||
pr_err("Cannot alloc pm8921 struct\n");
|
||||
return -ENOMEM;
|
||||
@ -127,7 +128,7 @@ static int pm8921_probe(struct platform_device *pdev)
|
||||
rc = ssbi_read(pdev->dev.parent, REG_HWREV, &val, sizeof(val));
|
||||
if (rc) {
|
||||
pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc);
|
||||
goto err_read_rev;
|
||||
return rc;
|
||||
}
|
||||
pr_info("PMIC revision 1: %02X\n", val);
|
||||
rev = val;
|
||||
@ -137,7 +138,7 @@ static int pm8921_probe(struct platform_device *pdev)
|
||||
if (rc) {
|
||||
pr_err("Failed to read hw rev 2 reg %d:rc=%d\n",
|
||||
REG_HWREV_2, rc);
|
||||
goto err_read_rev;
|
||||
return rc;
|
||||
}
|
||||
pr_info("PMIC revision 2: %02X\n", val);
|
||||
rev |= val << BITS_PER_BYTE;
|
||||
@ -159,9 +160,6 @@ static int pm8921_probe(struct platform_device *pdev)
|
||||
|
||||
err:
|
||||
mfd_remove_devices(pmic->dev);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
err_read_rev:
|
||||
kfree(pmic);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -179,8 +177,6 @@ static int pm8921_remove(struct platform_device *pdev)
|
||||
pm8xxx_irq_exit(pmic->irq_chip);
|
||||
pmic->irq_chip = NULL;
|
||||
}
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
kfree(pmic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ static int rc5t583_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct rc5t583 *rc5t583;
|
||||
struct rc5t583_platform_data *pdata = i2c->dev.platform_data;
|
||||
struct rc5t583_platform_data *pdata = dev_get_platdata(&i2c->dev);
|
||||
int ret;
|
||||
bool irq_init_success = false;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Driver for Realtek PCI-Express card reader
|
||||
*
|
||||
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
|
||||
* Copyright(c) 2009-2013 Realtek Semiconductor Corp. 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 the
|
||||
@ -17,7 +17,7 @@
|
||||
*
|
||||
* Author:
|
||||
* Wei WANG <wei_wang@realsil.com.cn>
|
||||
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
|
||||
* Roger Tseng <rogerable@realtek.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -47,19 +47,77 @@ static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
|
||||
{
|
||||
u32 reg1;
|
||||
u8 reg3;
|
||||
|
||||
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®1);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1);
|
||||
|
||||
if (!rtsx_vendor_setting_valid(reg1))
|
||||
return;
|
||||
|
||||
pcr->aspm_en = rtsx_reg_to_aspm(reg1);
|
||||
pcr->sd30_drive_sel_1v8 =
|
||||
map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg1));
|
||||
pcr->card_drive_sel &= 0x3F;
|
||||
pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg1);
|
||||
|
||||
rtsx_pci_read_config_byte(pcr, PCR_SETTING_REG3, ®3);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG3, reg3);
|
||||
pcr->sd30_drive_sel_3v3 = rtl8411_reg_to_sd30_drive_sel_3v3(reg3);
|
||||
}
|
||||
|
||||
static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
|
||||
|
||||
if (!rtsx_vendor_setting_valid(reg))
|
||||
return;
|
||||
|
||||
pcr->aspm_en = rtsx_reg_to_aspm(reg);
|
||||
pcr->sd30_drive_sel_1v8 =
|
||||
map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg));
|
||||
pcr->sd30_drive_sel_3v3 =
|
||||
map_sd_drive(rtl8411b_reg_to_sd30_drive_sel_3v3(reg));
|
||||
}
|
||||
|
||||
static void rtl8411_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
|
||||
{
|
||||
rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07);
|
||||
}
|
||||
|
||||
static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr)
|
||||
{
|
||||
return rtsx_pci_write_register(pcr, CD_PAD_CTL,
|
||||
rtsx_pci_init_cmd(pcr);
|
||||
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
|
||||
0xFF, pcr->sd30_drive_sel_3v3);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL,
|
||||
CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
|
||||
|
||||
return rtsx_pci_send_cmd(pcr, 100);
|
||||
}
|
||||
|
||||
static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr)
|
||||
{
|
||||
if (rtl8411b_is_qfn48(pcr))
|
||||
rtsx_pci_write_register(pcr, CARD_PULL_CTL3, 0xFF, 0xF5);
|
||||
rtsx_pci_init_cmd(pcr);
|
||||
|
||||
return rtsx_pci_write_register(pcr, CD_PAD_CTL,
|
||||
if (rtl8411b_is_qfn48(pcr))
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
|
||||
CARD_PULL_CTL3, 0xFF, 0xF5);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
|
||||
0xFF, pcr->sd30_drive_sel_3v3);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL,
|
||||
CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, FUNC_FORCE_CTL,
|
||||
0x06, 0x00);
|
||||
|
||||
return rtsx_pci_send_cmd(pcr, 100);
|
||||
}
|
||||
|
||||
static int rtl8411_turn_on_led(struct rtsx_pcr *pcr)
|
||||
@ -141,13 +199,13 @@ static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK;
|
||||
if (voltage == OUTPUT_3V3) {
|
||||
err = rtsx_pci_write_register(pcr,
|
||||
SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D);
|
||||
SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
|
||||
if (err < 0)
|
||||
return err;
|
||||
val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3;
|
||||
} else if (voltage == OUTPUT_1V8) {
|
||||
err = rtsx_pci_write_register(pcr,
|
||||
SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B);
|
||||
SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
|
||||
if (err < 0)
|
||||
return err;
|
||||
val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8;
|
||||
@ -222,6 +280,7 @@ static int rtl8411_conv_clk_and_div_n(int input, int dir)
|
||||
}
|
||||
|
||||
static const struct pcr_ops rtl8411_pcr_ops = {
|
||||
.fetch_vendor_settings = rtl8411_fetch_vendor_settings,
|
||||
.extra_init_hw = rtl8411_extra_init_hw,
|
||||
.optimize_phy = NULL,
|
||||
.turn_on_led = rtl8411_turn_on_led,
|
||||
@ -233,9 +292,11 @@ static const struct pcr_ops rtl8411_pcr_ops = {
|
||||
.switch_output_voltage = rtl8411_switch_output_voltage,
|
||||
.cd_deglitch = rtl8411_cd_deglitch,
|
||||
.conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
|
||||
.force_power_down = rtl8411_force_power_down,
|
||||
};
|
||||
|
||||
static const struct pcr_ops rtl8411b_pcr_ops = {
|
||||
.fetch_vendor_settings = rtl8411b_fetch_vendor_settings,
|
||||
.extra_init_hw = rtl8411b_extra_init_hw,
|
||||
.optimize_phy = NULL,
|
||||
.turn_on_led = rtl8411_turn_on_led,
|
||||
@ -247,6 +308,7 @@ static const struct pcr_ops rtl8411b_pcr_ops = {
|
||||
.switch_output_voltage = rtl8411_switch_output_voltage,
|
||||
.cd_deglitch = rtl8411_cd_deglitch,
|
||||
.conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
|
||||
.force_power_down = rtl8411_force_power_down,
|
||||
};
|
||||
|
||||
/* SD Pull Control Enable:
|
||||
@ -385,6 +447,14 @@ void rtl8411_init_params(struct rtsx_pcr *pcr)
|
||||
pcr->num_slots = 2;
|
||||
pcr->ops = &rtl8411_pcr_ops;
|
||||
|
||||
pcr->flags = 0;
|
||||
pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT;
|
||||
pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
|
||||
pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
|
||||
pcr->aspm_en = ASPM_L1_EN;
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14);
|
||||
pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10);
|
||||
|
||||
pcr->ic_version = rtl8411_get_ic_version(pcr);
|
||||
pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl;
|
||||
pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl;
|
||||
@ -398,6 +468,14 @@ void rtl8411b_init_params(struct rtsx_pcr *pcr)
|
||||
pcr->num_slots = 2;
|
||||
pcr->ops = &rtl8411b_pcr_ops;
|
||||
|
||||
pcr->flags = 0;
|
||||
pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT;
|
||||
pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
|
||||
pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
|
||||
pcr->aspm_en = ASPM_L1_EN;
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14);
|
||||
pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10);
|
||||
|
||||
pcr->ic_version = rtl8411_get_ic_version(pcr);
|
||||
|
||||
if (rtl8411b_is_qfn48(pcr)) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Driver for Realtek PCI-Express card reader
|
||||
*
|
||||
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
|
||||
* Copyright(c) 2009-2013 Realtek Semiconductor Corp. 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 the
|
||||
@ -17,7 +17,6 @@
|
||||
*
|
||||
* Author:
|
||||
* Wei WANG <wei_wang@realsil.com.cn>
|
||||
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -34,19 +33,34 @@ static u8 rts5209_get_ic_version(struct rtsx_pcr *pcr)
|
||||
return val & 0x0F;
|
||||
}
|
||||
|
||||
static void rts5209_init_vendor_cfg(struct rtsx_pcr *pcr)
|
||||
static void rts5209_fetch_vendor_settings(struct rtsx_pcr *pcr)
|
||||
{
|
||||
u32 val;
|
||||
u32 reg;
|
||||
|
||||
rtsx_pci_read_config_dword(pcr, 0x724, &val);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x724: 0x%x\n", val);
|
||||
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
|
||||
|
||||
if (!(val & 0x80)) {
|
||||
if (val & 0x08)
|
||||
pcr->ms_pmos = false;
|
||||
else
|
||||
pcr->ms_pmos = true;
|
||||
if (rts5209_vendor_setting1_valid(reg)) {
|
||||
if (rts5209_reg_check_ms_pmos(reg))
|
||||
pcr->flags |= PCR_MS_PMOS;
|
||||
pcr->aspm_en = rts5209_reg_to_aspm(reg);
|
||||
}
|
||||
|
||||
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
|
||||
|
||||
if (rts5209_vendor_setting2_valid(reg)) {
|
||||
pcr->sd30_drive_sel_1v8 =
|
||||
rts5209_reg_to_sd30_drive_sel_1v8(reg);
|
||||
pcr->sd30_drive_sel_3v3 =
|
||||
rts5209_reg_to_sd30_drive_sel_3v3(reg);
|
||||
pcr->card_drive_sel = rts5209_reg_to_card_drive_sel(reg);
|
||||
}
|
||||
}
|
||||
|
||||
static void rts5209_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
|
||||
{
|
||||
rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07);
|
||||
}
|
||||
|
||||
static int rts5209_extra_init_hw(struct rtsx_pcr *pcr)
|
||||
@ -55,8 +69,15 @@ static int rts5209_extra_init_hw(struct rtsx_pcr *pcr)
|
||||
|
||||
/* Turn off LED */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO, 0xFF, 0x03);
|
||||
/* Reset ASPM state to default value */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
|
||||
/* Force CLKREQ# PIN to drive 0 to request clock */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x08, 0x08);
|
||||
/* Configure GPIO as output */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO_DIR, 0xFF, 0x03);
|
||||
/* Configure driving */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
|
||||
0xFF, pcr->sd30_drive_sel_3v3);
|
||||
|
||||
return rtsx_pci_send_cmd(pcr, 100);
|
||||
}
|
||||
@ -95,7 +116,7 @@ static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card)
|
||||
partial_pwr_on = SD_PARTIAL_POWER_ON;
|
||||
pwr_on = SD_POWER_ON;
|
||||
|
||||
if (pcr->ms_pmos && (card == RTSX_MS_CARD)) {
|
||||
if ((pcr->flags & PCR_MS_PMOS) && (card == RTSX_MS_CARD)) {
|
||||
pwr_mask = MS_POWER_MASK;
|
||||
partial_pwr_on = MS_PARTIAL_POWER_ON;
|
||||
pwr_on = MS_POWER_ON;
|
||||
@ -131,7 +152,7 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
|
||||
pwr_mask = SD_POWER_MASK;
|
||||
pwr_off = SD_POWER_OFF;
|
||||
|
||||
if (pcr->ms_pmos && (card == RTSX_MS_CARD)) {
|
||||
if ((pcr->flags & PCR_MS_PMOS) && (card == RTSX_MS_CARD)) {
|
||||
pwr_mask = MS_POWER_MASK;
|
||||
pwr_off = MS_POWER_OFF;
|
||||
}
|
||||
@ -140,7 +161,7 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
|
||||
pwr_mask | PMOS_STRG_MASK, pwr_off | PMOS_STRG_400mA);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
|
||||
LDO3318_PWR_MASK, 0X06);
|
||||
LDO3318_PWR_MASK, 0x06);
|
||||
return rtsx_pci_send_cmd(pcr, 100);
|
||||
}
|
||||
|
||||
@ -150,7 +171,7 @@ static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
|
||||
if (voltage == OUTPUT_3V3) {
|
||||
err = rtsx_pci_write_register(pcr,
|
||||
SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D);
|
||||
SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
|
||||
@ -158,7 +179,7 @@ static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
return err;
|
||||
} else if (voltage == OUTPUT_1V8) {
|
||||
err = rtsx_pci_write_register(pcr,
|
||||
SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B);
|
||||
SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
|
||||
@ -172,6 +193,7 @@ static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
}
|
||||
|
||||
static const struct pcr_ops rts5209_pcr_ops = {
|
||||
.fetch_vendor_settings = rts5209_fetch_vendor_settings,
|
||||
.extra_init_hw = rts5209_extra_init_hw,
|
||||
.optimize_phy = rts5209_optimize_phy,
|
||||
.turn_on_led = rts5209_turn_on_led,
|
||||
@ -183,6 +205,7 @@ static const struct pcr_ops rts5209_pcr_ops = {
|
||||
.switch_output_voltage = rts5209_switch_output_voltage,
|
||||
.cd_deglitch = NULL,
|
||||
.conv_clk_and_div_n = NULL,
|
||||
.force_power_down = rts5209_force_power_down,
|
||||
};
|
||||
|
||||
/* SD Pull Control Enable:
|
||||
@ -242,7 +265,13 @@ void rts5209_init_params(struct rtsx_pcr *pcr)
|
||||
pcr->num_slots = 2;
|
||||
pcr->ops = &rts5209_pcr_ops;
|
||||
|
||||
rts5209_init_vendor_cfg(pcr);
|
||||
pcr->flags = 0;
|
||||
pcr->card_drive_sel = RTS5209_CARD_DRIVE_DEFAULT;
|
||||
pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
|
||||
pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
|
||||
pcr->aspm_en = ASPM_L1_EN;
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 16);
|
||||
pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);
|
||||
|
||||
pcr->ic_version = rts5209_get_ic_version(pcr);
|
||||
pcr->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Driver for Realtek PCI-Express card reader
|
||||
*
|
||||
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
|
||||
* Copyright(c) 2009-2013 Realtek Semiconductor Corp. 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 the
|
||||
@ -17,10 +17,7 @@
|
||||
*
|
||||
* Author:
|
||||
* Wei WANG <wei_wang@realsil.com.cn>
|
||||
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
|
||||
*
|
||||
* Roger Tseng <rogerable@realtek.com>
|
||||
* No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -29,6 +26,73 @@
|
||||
|
||||
#include "rtsx_pcr.h"
|
||||
|
||||
static void rts5227_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
|
||||
{
|
||||
u8 driving_3v3[4][3] = {
|
||||
{0x13, 0x13, 0x13},
|
||||
{0x96, 0x96, 0x96},
|
||||
{0x7F, 0x7F, 0x7F},
|
||||
{0x96, 0x96, 0x96},
|
||||
};
|
||||
u8 driving_1v8[4][3] = {
|
||||
{0x99, 0x99, 0x99},
|
||||
{0xAA, 0xAA, 0xAA},
|
||||
{0xFE, 0xFE, 0xFE},
|
||||
{0xB3, 0xB3, 0xB3},
|
||||
};
|
||||
u8 (*driving)[3], drive_sel;
|
||||
|
||||
if (voltage == OUTPUT_3V3) {
|
||||
driving = driving_3v3;
|
||||
drive_sel = pcr->sd30_drive_sel_3v3;
|
||||
} else {
|
||||
driving = driving_1v8;
|
||||
drive_sel = pcr->sd30_drive_sel_1v8;
|
||||
}
|
||||
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
|
||||
0xFF, driving[drive_sel][0]);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
|
||||
0xFF, driving[drive_sel][1]);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
|
||||
0xFF, driving[drive_sel][2]);
|
||||
}
|
||||
|
||||
static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
|
||||
|
||||
if (!rtsx_vendor_setting_valid(reg))
|
||||
return;
|
||||
|
||||
pcr->aspm_en = rtsx_reg_to_aspm(reg);
|
||||
pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg);
|
||||
pcr->card_drive_sel &= 0x3F;
|
||||
pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
|
||||
|
||||
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
|
||||
pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
|
||||
if (rtsx_reg_check_reverse_socket(reg))
|
||||
pcr->flags |= PCR_REVERSE_SOCKET;
|
||||
}
|
||||
|
||||
static void rts5227_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
|
||||
{
|
||||
/* Set relink_time to 0 */
|
||||
rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0);
|
||||
rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0);
|
||||
rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0);
|
||||
|
||||
if (pm_state == HOST_ENTER_S3)
|
||||
rtsx_pci_write_register(pcr, PM_CTRL3, 0x10, 0x10);
|
||||
|
||||
rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
|
||||
}
|
||||
|
||||
static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
|
||||
{
|
||||
u16 cap;
|
||||
@ -37,6 +101,8 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
|
||||
|
||||
/* Configure GPIO as output */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
|
||||
/* Reset ASPM state to default value */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
|
||||
/* Switch LDO3318 source from DV33 to card_3v3 */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
|
||||
@ -48,17 +114,16 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3);
|
||||
/* Configure OBFF */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03);
|
||||
/* Configure force_clock_req
|
||||
* Maybe We should define 0xFF03 as some name
|
||||
*/
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 0xFF03, 0x08, 0x08);
|
||||
/* Correct driving */
|
||||
/* Configure driving */
|
||||
rts5227_fill_driving(pcr, OUTPUT_3V3);
|
||||
/* Configure force_clock_req */
|
||||
if (pcr->flags & PCR_REVERSE_SOCKET)
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
|
||||
SD30_CLK_DRIVE_SEL, 0xFF, 0x96);
|
||||
AUTOLOAD_CFG_BASE + 3, 0xB8, 0xB8);
|
||||
else
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
|
||||
SD30_CMD_DRIVE_SEL, 0xFF, 0x96);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
|
||||
SD30_DAT_DRIVE_SEL, 0xFF, 0x96);
|
||||
AUTOLOAD_CFG_BASE + 3, 0xB8, 0x88);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00);
|
||||
|
||||
return rtsx_pci_send_cmd(pcr, 100);
|
||||
}
|
||||
@ -131,13 +196,11 @@ static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card)
|
||||
static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
{
|
||||
int err;
|
||||
u8 drive_sel;
|
||||
|
||||
if (voltage == OUTPUT_3V3) {
|
||||
err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
|
||||
if (err < 0)
|
||||
return err;
|
||||
drive_sel = 0x96;
|
||||
} else if (voltage == OUTPUT_1V8) {
|
||||
err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02);
|
||||
if (err < 0)
|
||||
@ -145,23 +208,18 @@ static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C80 | 0x24);
|
||||
if (err < 0)
|
||||
return err;
|
||||
drive_sel = 0xB3;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* set pad drive */
|
||||
rtsx_pci_init_cmd(pcr);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
|
||||
0xFF, drive_sel);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
|
||||
0xFF, drive_sel);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
|
||||
0xFF, drive_sel);
|
||||
rts5227_fill_driving(pcr, voltage);
|
||||
return rtsx_pci_send_cmd(pcr, 100);
|
||||
}
|
||||
|
||||
static const struct pcr_ops rts5227_pcr_ops = {
|
||||
.fetch_vendor_settings = rts5227_fetch_vendor_settings,
|
||||
.extra_init_hw = rts5227_extra_init_hw,
|
||||
.optimize_phy = rts5227_optimize_phy,
|
||||
.turn_on_led = rts5227_turn_on_led,
|
||||
@ -173,6 +231,7 @@ static const struct pcr_ops rts5227_pcr_ops = {
|
||||
.switch_output_voltage = rts5227_switch_output_voltage,
|
||||
.cd_deglitch = NULL,
|
||||
.conv_clk_and_div_n = NULL,
|
||||
.force_power_down = rts5227_force_power_down,
|
||||
};
|
||||
|
||||
/* SD Pull Control Enable:
|
||||
@ -227,6 +286,14 @@ void rts5227_init_params(struct rtsx_pcr *pcr)
|
||||
pcr->num_slots = 2;
|
||||
pcr->ops = &rts5227_pcr_ops;
|
||||
|
||||
pcr->flags = 0;
|
||||
pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
|
||||
pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;
|
||||
pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
|
||||
pcr->aspm_en = ASPM_L1_EN;
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15);
|
||||
pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 7, 7);
|
||||
|
||||
pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl;
|
||||
pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl;
|
||||
pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Driver for Realtek PCI-Express card reader
|
||||
*
|
||||
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
|
||||
* Copyright(c) 2009-2013 Realtek Semiconductor Corp. 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 the
|
||||
@ -17,7 +17,6 @@
|
||||
*
|
||||
* Author:
|
||||
* Wei WANG <wei_wang@realsil.com.cn>
|
||||
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -34,17 +33,51 @@ static u8 rts5229_get_ic_version(struct rtsx_pcr *pcr)
|
||||
return val & 0x0F;
|
||||
}
|
||||
|
||||
static void rts5229_fetch_vendor_settings(struct rtsx_pcr *pcr)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
|
||||
|
||||
if (!rtsx_vendor_setting_valid(reg))
|
||||
return;
|
||||
|
||||
pcr->aspm_en = rtsx_reg_to_aspm(reg);
|
||||
pcr->sd30_drive_sel_1v8 =
|
||||
map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg));
|
||||
pcr->card_drive_sel &= 0x3F;
|
||||
pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
|
||||
|
||||
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
|
||||
pcr->sd30_drive_sel_3v3 =
|
||||
map_sd_drive(rtsx_reg_to_sd30_drive_sel_3v3(reg));
|
||||
}
|
||||
|
||||
static void rts5229_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
|
||||
{
|
||||
rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
|
||||
}
|
||||
|
||||
static int rts5229_extra_init_hw(struct rtsx_pcr *pcr)
|
||||
{
|
||||
rtsx_pci_init_cmd(pcr);
|
||||
|
||||
/* Configure GPIO as output */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
|
||||
/* Reset ASPM state to default value */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
|
||||
/* Force CLKREQ# PIN to drive 0 to request clock */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x08, 0x08);
|
||||
/* Switch LDO3318 source from DV33 to card_3v3 */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
|
||||
/* LED shine disabled, set initial shine cycle period */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
|
||||
/* Configure driving */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
|
||||
0xFF, pcr->sd30_drive_sel_3v3);
|
||||
|
||||
return rtsx_pci_send_cmd(pcr, 100);
|
||||
}
|
||||
@ -110,7 +143,7 @@ static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
|
||||
SD_POWER_MASK | PMOS_STRG_MASK,
|
||||
SD_POWER_OFF | PMOS_STRG_400mA);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
|
||||
LDO3318_PWR_MASK, 0X00);
|
||||
LDO3318_PWR_MASK, 0x00);
|
||||
return rtsx_pci_send_cmd(pcr, 100);
|
||||
}
|
||||
|
||||
@ -120,7 +153,7 @@ static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
|
||||
if (voltage == OUTPUT_3V3) {
|
||||
err = rtsx_pci_write_register(pcr,
|
||||
SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D);
|
||||
SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
|
||||
@ -128,7 +161,7 @@ static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
return err;
|
||||
} else if (voltage == OUTPUT_1V8) {
|
||||
err = rtsx_pci_write_register(pcr,
|
||||
SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B);
|
||||
SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
|
||||
@ -142,6 +175,7 @@ static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
}
|
||||
|
||||
static const struct pcr_ops rts5229_pcr_ops = {
|
||||
.fetch_vendor_settings = rts5229_fetch_vendor_settings,
|
||||
.extra_init_hw = rts5229_extra_init_hw,
|
||||
.optimize_phy = rts5229_optimize_phy,
|
||||
.turn_on_led = rts5229_turn_on_led,
|
||||
@ -153,6 +187,7 @@ static const struct pcr_ops rts5229_pcr_ops = {
|
||||
.switch_output_voltage = rts5229_switch_output_voltage,
|
||||
.cd_deglitch = NULL,
|
||||
.conv_clk_and_div_n = NULL,
|
||||
.force_power_down = rts5229_force_power_down,
|
||||
};
|
||||
|
||||
/* SD Pull Control Enable:
|
||||
@ -221,6 +256,14 @@ void rts5229_init_params(struct rtsx_pcr *pcr)
|
||||
pcr->num_slots = 2;
|
||||
pcr->ops = &rts5229_pcr_ops;
|
||||
|
||||
pcr->flags = 0;
|
||||
pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
|
||||
pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
|
||||
pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
|
||||
pcr->aspm_en = ASPM_L1_EN;
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15);
|
||||
pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 6, 6);
|
||||
|
||||
pcr->ic_version = rts5229_get_ic_version(pcr);
|
||||
if (pcr->ic_version == IC_VER_C) {
|
||||
pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl2;
|
||||
|
@ -17,7 +17,6 @@
|
||||
*
|
||||
* Author:
|
||||
* Wei WANG <wei_wang@realsil.com.cn>
|
||||
* No. 128, West Shenhu Road, Suzhou Industry Park, Suzhou, China
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -34,24 +33,95 @@ static u8 rts5249_get_ic_version(struct rtsx_pcr *pcr)
|
||||
return val & 0x0F;
|
||||
}
|
||||
|
||||
static void rts5249_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
|
||||
{
|
||||
u8 driving_3v3[4][3] = {
|
||||
{0x11, 0x11, 0x11},
|
||||
{0x55, 0x55, 0x5C},
|
||||
{0x99, 0x99, 0x92},
|
||||
{0x99, 0x99, 0x92},
|
||||
};
|
||||
u8 driving_1v8[4][3] = {
|
||||
{0x3C, 0x3C, 0x3C},
|
||||
{0xB3, 0xB3, 0xB3},
|
||||
{0xFE, 0xFE, 0xFE},
|
||||
{0xC4, 0xC4, 0xC4},
|
||||
};
|
||||
u8 (*driving)[3], drive_sel;
|
||||
|
||||
if (voltage == OUTPUT_3V3) {
|
||||
driving = driving_3v3;
|
||||
drive_sel = pcr->sd30_drive_sel_3v3;
|
||||
} else {
|
||||
driving = driving_1v8;
|
||||
drive_sel = pcr->sd30_drive_sel_1v8;
|
||||
}
|
||||
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
|
||||
0xFF, driving[drive_sel][0]);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
|
||||
0xFF, driving[drive_sel][1]);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
|
||||
0xFF, driving[drive_sel][2]);
|
||||
}
|
||||
|
||||
static void rts5249_fetch_vendor_settings(struct rtsx_pcr *pcr)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
|
||||
|
||||
if (!rtsx_vendor_setting_valid(reg))
|
||||
return;
|
||||
|
||||
pcr->aspm_en = rtsx_reg_to_aspm(reg);
|
||||
pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg);
|
||||
pcr->card_drive_sel &= 0x3F;
|
||||
pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
|
||||
|
||||
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
|
||||
pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
|
||||
if (rtsx_reg_check_reverse_socket(reg))
|
||||
pcr->flags |= PCR_REVERSE_SOCKET;
|
||||
}
|
||||
|
||||
static void rts5249_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
|
||||
{
|
||||
/* Set relink_time to 0 */
|
||||
rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0);
|
||||
rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0);
|
||||
rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0);
|
||||
|
||||
if (pm_state == HOST_ENTER_S3)
|
||||
rtsx_pci_write_register(pcr, PM_CTRL3, 0x10, 0x10);
|
||||
|
||||
rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
|
||||
}
|
||||
|
||||
static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
|
||||
{
|
||||
rtsx_pci_init_cmd(pcr);
|
||||
|
||||
/* Configure GPIO as output */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
|
||||
/* Reset ASPM state to default value */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
|
||||
/* Switch LDO3318 source from DV33 to card_3v3 */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
|
||||
/* LED shine disabled, set initial shine cycle period */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
|
||||
/* Correct driving */
|
||||
/* Configure driving */
|
||||
rts5249_fill_driving(pcr, OUTPUT_3V3);
|
||||
if (pcr->flags & PCR_REVERSE_SOCKET)
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
|
||||
SD30_CLK_DRIVE_SEL, 0xFF, 0x99);
|
||||
AUTOLOAD_CFG_BASE + 3, 0xB0, 0xB0);
|
||||
else
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
|
||||
SD30_CMD_DRIVE_SEL, 0xFF, 0x99);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
|
||||
SD30_DAT_DRIVE_SEL, 0xFF, 0x92);
|
||||
AUTOLOAD_CFG_BASE + 3, 0xB0, 0x80);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00);
|
||||
|
||||
return rtsx_pci_send_cmd(pcr, 100);
|
||||
}
|
||||
@ -129,15 +199,11 @@ static int rts5249_card_power_off(struct rtsx_pcr *pcr, int card)
|
||||
static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
{
|
||||
int err;
|
||||
u8 clk_drive, cmd_drive, dat_drive;
|
||||
|
||||
if (voltage == OUTPUT_3V3) {
|
||||
err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4FC0 | 0x24);
|
||||
if (err < 0)
|
||||
return err;
|
||||
clk_drive = 0x99;
|
||||
cmd_drive = 0x99;
|
||||
dat_drive = 0x92;
|
||||
} else if (voltage == OUTPUT_1V8) {
|
||||
err = rtsx_pci_write_phy_register(pcr, PHY_BACR, 0x3C02);
|
||||
if (err < 0)
|
||||
@ -145,25 +211,18 @@ static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4C40 | 0x24);
|
||||
if (err < 0)
|
||||
return err;
|
||||
clk_drive = 0xb3;
|
||||
cmd_drive = 0xb3;
|
||||
dat_drive = 0xb3;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* set pad drive */
|
||||
rtsx_pci_init_cmd(pcr);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
|
||||
0xFF, clk_drive);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
|
||||
0xFF, cmd_drive);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
|
||||
0xFF, dat_drive);
|
||||
rts5249_fill_driving(pcr, voltage);
|
||||
return rtsx_pci_send_cmd(pcr, 100);
|
||||
}
|
||||
|
||||
static const struct pcr_ops rts5249_pcr_ops = {
|
||||
.fetch_vendor_settings = rts5249_fetch_vendor_settings,
|
||||
.extra_init_hw = rts5249_extra_init_hw,
|
||||
.optimize_phy = rts5249_optimize_phy,
|
||||
.turn_on_led = rts5249_turn_on_led,
|
||||
@ -173,6 +232,7 @@ static const struct pcr_ops rts5249_pcr_ops = {
|
||||
.card_power_on = rts5249_card_power_on,
|
||||
.card_power_off = rts5249_card_power_off,
|
||||
.switch_output_voltage = rts5249_switch_output_voltage,
|
||||
.force_power_down = rts5249_force_power_down,
|
||||
};
|
||||
|
||||
/* SD Pull Control Enable:
|
||||
@ -233,6 +293,14 @@ void rts5249_init_params(struct rtsx_pcr *pcr)
|
||||
pcr->num_slots = 2;
|
||||
pcr->ops = &rts5249_pcr_ops;
|
||||
|
||||
pcr->flags = 0;
|
||||
pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
|
||||
pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_C;
|
||||
pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
|
||||
pcr->aspm_en = ASPM_L1_EN;
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(1, 29, 16);
|
||||
pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);
|
||||
|
||||
pcr->ic_version = rts5249_get_ic_version(pcr);
|
||||
pcr->sd_pull_ctl_enable_tbl = rts5249_sd_pull_ctl_enable_tbl;
|
||||
pcr->sd_pull_ctl_disable_tbl = rts5249_sd_pull_ctl_disable_tbl;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Driver for Realtek PCI-Express card reader
|
||||
*
|
||||
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
|
||||
* Copyright(c) 2009-2013 Realtek Semiconductor Corp. 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 the
|
||||
@ -17,7 +17,6 @@
|
||||
*
|
||||
* Author:
|
||||
* Wei WANG <wei_wang@realsil.com.cn>
|
||||
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
@ -73,6 +72,9 @@ void rtsx_pci_start_run(struct rtsx_pcr *pcr)
|
||||
pcr->state = PDEV_STAT_RUN;
|
||||
if (pcr->ops->enable_auto_blink)
|
||||
pcr->ops->enable_auto_blink(pcr);
|
||||
|
||||
if (pcr->aspm_en)
|
||||
rtsx_pci_write_config_byte(pcr, LCTLR, 0);
|
||||
}
|
||||
|
||||
mod_delayed_work(system_wq, &pcr->idle_work, msecs_to_jiffies(200));
|
||||
@ -717,7 +719,7 @@ int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card)
|
||||
[RTSX_MS_CARD] = MS_EXIST
|
||||
};
|
||||
|
||||
if (!pcr->ms_pmos) {
|
||||
if (!(pcr->flags & PCR_MS_PMOS)) {
|
||||
/* When using single PMOS, accessing card is not permitted
|
||||
* if the existing card is not the designated one.
|
||||
*/
|
||||
@ -918,9 +920,27 @@ static void rtsx_pci_idle_work(struct work_struct *work)
|
||||
if (pcr->ops->turn_off_led)
|
||||
pcr->ops->turn_off_led(pcr);
|
||||
|
||||
if (pcr->aspm_en)
|
||||
rtsx_pci_write_config_byte(pcr, LCTLR, pcr->aspm_en);
|
||||
|
||||
mutex_unlock(&pcr->pcr_mutex);
|
||||
}
|
||||
|
||||
static void rtsx_pci_power_off(struct rtsx_pcr *pcr, u8 pm_state)
|
||||
{
|
||||
if (pcr->ops->turn_off_led)
|
||||
pcr->ops->turn_off_led(pcr);
|
||||
|
||||
rtsx_pci_writel(pcr, RTSX_BIER, 0);
|
||||
pcr->bier = 0;
|
||||
|
||||
rtsx_pci_write_register(pcr, PETXCFG, 0x08, 0x08);
|
||||
rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, pm_state);
|
||||
|
||||
if (pcr->ops->force_power_down)
|
||||
pcr->ops->force_power_down(pcr, pm_state);
|
||||
}
|
||||
|
||||
static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
|
||||
{
|
||||
int err;
|
||||
@ -951,13 +971,11 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, HOST_SLEEP_STATE, 0x03, 0x00);
|
||||
/* Disable card clock */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, 0x1E, 0);
|
||||
/* Reset ASPM state to default value */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
|
||||
/* Reset delink mode */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CHANGE_LINK_STATE, 0x0A, 0);
|
||||
/* Card driving select */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
|
||||
0x07, DRIVER_TYPE_D);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DRIVE_SEL,
|
||||
0xFF, pcr->card_drive_sel);
|
||||
/* Enable SSC Clock */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1,
|
||||
0xFF, SSC_8X_EN | SSC_SEL_4M);
|
||||
@ -982,13 +1000,13 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
|
||||
* 0: ELBI interrupt flag[31:22] & [7:0] only can be write clear
|
||||
*/
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, NFTS_TX_CTRL, 0x02, 0);
|
||||
/* Force CLKREQ# PIN to drive 0 to request clock */
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x08, 0x08);
|
||||
|
||||
err = rtsx_pci_send_cmd(pcr, 100);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
rtsx_pci_write_config_byte(pcr, LCTLR, 0);
|
||||
|
||||
/* Enable clk_request_n to enable clock power management */
|
||||
rtsx_pci_write_config_byte(pcr, 0x81, 1);
|
||||
/* Enter L1 when host tx idle */
|
||||
@ -1053,6 +1071,18 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
|
||||
if (!pcr->slots)
|
||||
return -ENOMEM;
|
||||
|
||||
if (pcr->ops->fetch_vendor_settings)
|
||||
pcr->ops->fetch_vendor_settings(pcr);
|
||||
|
||||
dev_dbg(&(pcr->pci->dev), "pcr->aspm_en = 0x%x\n", pcr->aspm_en);
|
||||
dev_dbg(&(pcr->pci->dev), "pcr->sd30_drive_sel_1v8 = 0x%x\n",
|
||||
pcr->sd30_drive_sel_1v8);
|
||||
dev_dbg(&(pcr->pci->dev), "pcr->sd30_drive_sel_3v3 = 0x%x\n",
|
||||
pcr->sd30_drive_sel_3v3);
|
||||
dev_dbg(&(pcr->pci->dev), "pcr->card_drive_sel = 0x%x\n",
|
||||
pcr->card_drive_sel);
|
||||
dev_dbg(&(pcr->pci->dev), "pcr->flags = 0x%x\n", pcr->flags);
|
||||
|
||||
pcr->state = PDEV_STAT_IDLE;
|
||||
err = rtsx_pci_init_hw(pcr);
|
||||
if (err < 0) {
|
||||
@ -1235,7 +1265,6 @@ static int rtsx_pci_suspend(struct pci_dev *pcidev, pm_message_t state)
|
||||
{
|
||||
struct pcr_handle *handle;
|
||||
struct rtsx_pcr *pcr;
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
|
||||
|
||||
@ -1247,14 +1276,7 @@ static int rtsx_pci_suspend(struct pci_dev *pcidev, pm_message_t state)
|
||||
|
||||
mutex_lock(&pcr->pcr_mutex);
|
||||
|
||||
if (pcr->ops->turn_off_led)
|
||||
pcr->ops->turn_off_led(pcr);
|
||||
|
||||
rtsx_pci_writel(pcr, RTSX_BIER, 0);
|
||||
pcr->bier = 0;
|
||||
|
||||
rtsx_pci_write_register(pcr, PETXCFG, 0x08, 0x08);
|
||||
rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, 0x02);
|
||||
rtsx_pci_power_off(pcr, HOST_ENTER_S3);
|
||||
|
||||
pci_save_state(pcidev);
|
||||
pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0);
|
||||
@ -1262,7 +1284,7 @@ static int rtsx_pci_suspend(struct pci_dev *pcidev, pm_message_t state)
|
||||
pci_set_power_state(pcidev, pci_choose_state(pcidev, state));
|
||||
|
||||
mutex_unlock(&pcr->pcr_mutex);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtsx_pci_resume(struct pci_dev *pcidev)
|
||||
@ -1300,10 +1322,25 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rtsx_pci_shutdown(struct pci_dev *pcidev)
|
||||
{
|
||||
struct pcr_handle *handle;
|
||||
struct rtsx_pcr *pcr;
|
||||
|
||||
dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
|
||||
|
||||
handle = pci_get_drvdata(pcidev);
|
||||
pcr = handle->pcr;
|
||||
rtsx_pci_power_off(pcr, HOST_ENTER_S1);
|
||||
|
||||
pci_disable_device(pcidev);
|
||||
}
|
||||
|
||||
#else /* CONFIG_PM */
|
||||
|
||||
#define rtsx_pci_suspend NULL
|
||||
#define rtsx_pci_resume NULL
|
||||
#define rtsx_pci_shutdown NULL
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
@ -1314,6 +1351,7 @@ static struct pci_driver rtsx_pci_driver = {
|
||||
.remove = rtsx_pci_remove,
|
||||
.suspend = rtsx_pci_suspend,
|
||||
.resume = rtsx_pci_resume,
|
||||
.shutdown = rtsx_pci_shutdown,
|
||||
};
|
||||
module_pci_driver(rtsx_pci_driver);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Driver for Realtek PCI-Express card reader
|
||||
*
|
||||
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
|
||||
* Copyright(c) 2009-2013 Realtek Semiconductor Corp. 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 the
|
||||
@ -17,7 +17,6 @@
|
||||
*
|
||||
* Author:
|
||||
* Wei WANG <wei_wang@realsil.com.cn>
|
||||
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
|
||||
*/
|
||||
|
||||
#ifndef __RTSX_PCR_H
|
||||
@ -35,4 +34,33 @@ void rts5227_init_params(struct rtsx_pcr *pcr);
|
||||
void rts5249_init_params(struct rtsx_pcr *pcr);
|
||||
void rtl8411b_init_params(struct rtsx_pcr *pcr);
|
||||
|
||||
static inline u8 map_sd_drive(int idx)
|
||||
{
|
||||
u8 sd_drive[4] = {
|
||||
0x01, /* Type D */
|
||||
0x02, /* Type C */
|
||||
0x05, /* Type A */
|
||||
0x03 /* Type B */
|
||||
};
|
||||
|
||||
return sd_drive[idx];
|
||||
}
|
||||
|
||||
#define rtsx_vendor_setting_valid(reg) (!((reg) & 0x1000000))
|
||||
#define rts5209_vendor_setting1_valid(reg) (!((reg) & 0x80))
|
||||
#define rts5209_vendor_setting2_valid(reg) ((reg) & 0x80)
|
||||
|
||||
#define rtsx_reg_to_aspm(reg) (((reg) >> 28) & 0x03)
|
||||
#define rtsx_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 26) & 0x03)
|
||||
#define rtsx_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 5) & 0x03)
|
||||
#define rtsx_reg_to_card_drive_sel(reg) ((((reg) >> 25) & 0x01) << 6)
|
||||
#define rtsx_reg_check_reverse_socket(reg) ((reg) & 0x4000)
|
||||
#define rts5209_reg_to_aspm(reg) (((reg) >> 5) & 0x03)
|
||||
#define rts5209_reg_check_ms_pmos(reg) (!((reg) & 0x08))
|
||||
#define rts5209_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 3) & 0x07)
|
||||
#define rts5209_reg_to_sd30_drive_sel_3v3(reg) ((reg) & 0x07)
|
||||
#define rts5209_reg_to_card_drive_sel(reg) ((reg) >> 8)
|
||||
#define rtl8411_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 5) & 0x07)
|
||||
#define rtl8411b_reg_to_sd30_drive_sel_3v3(reg) ((reg) & 0x03)
|
||||
|
||||
#endif
|
||||
|
@ -61,7 +61,9 @@ static struct mfd_cell s5m8767_devs[] = {
|
||||
static struct mfd_cell s2mps11_devs[] = {
|
||||
{
|
||||
.name = "s2mps11-pmic",
|
||||
},
|
||||
}, {
|
||||
.name = "s2mps11-clk",
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
@ -69,6 +71,9 @@ static struct of_device_id sec_dt_match[] = {
|
||||
{ .compatible = "samsung,s5m8767-pmic",
|
||||
.data = (void *)S5M8767X,
|
||||
},
|
||||
{ .compatible = "samsung,s2mps11-pmic",
|
||||
.data = (void *)S2MPS11X,
|
||||
},
|
||||
{},
|
||||
};
|
||||
#endif
|
||||
@ -103,6 +108,31 @@ int sec_reg_update(struct sec_pmic_dev *sec_pmic, u8 reg, u8 val, u8 mask)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sec_reg_update);
|
||||
|
||||
static bool s2mps11_volatile(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case S2MPS11_REG_INT1M:
|
||||
case S2MPS11_REG_INT2M:
|
||||
case S2MPS11_REG_INT3M:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool s5m8763_volatile(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case S5M8763_REG_IRQM1:
|
||||
case S5M8763_REG_IRQM2:
|
||||
case S5M8763_REG_IRQM3:
|
||||
case S5M8763_REG_IRQM4:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static struct regmap_config sec_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
@ -113,6 +143,8 @@ static struct regmap_config s2mps11_regmap_config = {
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = S2MPS11_REG_L38CTRL,
|
||||
.volatile_reg = s2mps11_volatile,
|
||||
.cache_type = REGCACHE_FLAT,
|
||||
};
|
||||
|
||||
static struct regmap_config s5m8763_regmap_config = {
|
||||
@ -120,6 +152,8 @@ static struct regmap_config s5m8763_regmap_config = {
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = S5M8763_REG_LBCNFG2,
|
||||
.volatile_reg = s5m8763_volatile,
|
||||
.cache_type = REGCACHE_FLAT,
|
||||
};
|
||||
|
||||
static struct regmap_config s5m8767_regmap_config = {
|
||||
@ -127,6 +161,8 @@ static struct regmap_config s5m8767_regmap_config = {
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = S5M8767_REG_LDO28CTRL,
|
||||
.volatile_reg = s2mps11_volatile,
|
||||
.cache_type = REGCACHE_FLAT,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
@ -182,7 +218,7 @@ static inline int sec_i2c_get_driver_data(struct i2c_client *i2c,
|
||||
static int sec_pmic_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct sec_platform_data *pdata = i2c->dev.platform_data;
|
||||
struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev);
|
||||
const struct regmap_config *regmap;
|
||||
struct sec_pmic_dev *sec_pmic;
|
||||
int ret;
|
||||
|
@ -718,7 +718,7 @@ static int si476x_core_probe(struct i2c_client *client,
|
||||
atomic_set(&core->is_alive, 0);
|
||||
core->power_state = SI476X_POWER_DOWN;
|
||||
|
||||
pdata = client->dev.platform_data;
|
||||
pdata = dev_get_platdata(&client->dev);
|
||||
if (pdata) {
|
||||
memcpy(&core->power_up_parameters,
|
||||
&pdata->power_up_parameters,
|
||||
|
@ -840,7 +840,7 @@ static int sm501_register_uart(struct sm501_devdata *sm, int devices)
|
||||
if (!pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
uart_data = pdev->dev.platform_data;
|
||||
uart_data = dev_get_platdata(&pdev->dev);
|
||||
|
||||
if (devices & SM501_USE_UART0) {
|
||||
sm501_setup_uart_data(sm, uart_data++, 0x30000);
|
||||
@ -1167,7 +1167,7 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
|
||||
if (!pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
icd = pdev->dev.platform_data;
|
||||
icd = dev_get_platdata(&pdev->dev);
|
||||
|
||||
/* We keep the pin_sda and pin_scl fields relative in case the
|
||||
* same platform data is passed to >1 SM501.
|
||||
@ -1403,7 +1403,7 @@ static int sm501_plat_probe(struct platform_device *dev)
|
||||
|
||||
sm->dev = &dev->dev;
|
||||
sm->pdev_id = dev->id;
|
||||
sm->platdata = dev->dev.platform_data;
|
||||
sm->platdata = dev_get_platdata(&dev->dev);
|
||||
|
||||
ret = platform_get_irq(dev, 0);
|
||||
if (ret < 0) {
|
||||
|
@ -133,7 +133,7 @@ int sta2x11_mfd_get_regs_data(struct platform_device *dev,
|
||||
void __iomem **regs,
|
||||
spinlock_t **lock)
|
||||
{
|
||||
struct pci_dev *pdev = *(struct pci_dev **)(dev->dev.platform_data);
|
||||
struct pci_dev *pdev = *(struct pci_dev **)dev_get_platdata(&dev->dev);
|
||||
struct sta2x11_mfd *mfd;
|
||||
|
||||
if (!pdev)
|
||||
@ -312,7 +312,7 @@ static int sta2x11_mfd_platform_probe(struct platform_device *dev,
|
||||
const char *name = sta2x11_mfd_names[index];
|
||||
struct regmap_config *regmap_config = sta2x11_mfd_regmap_configs[index];
|
||||
|
||||
pdev = dev->dev.platform_data;
|
||||
pdev = dev_get_platdata(&dev->dev);
|
||||
mfd = sta2x11_mfd_find(*pdev);
|
||||
if (!mfd)
|
||||
return -ENODEV;
|
||||
|
@ -1106,7 +1106,8 @@ static int stmpe_devices_init(struct stmpe *stmpe)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void stmpe_of_probe(struct stmpe_platform_data *pdata, struct device_node *np)
|
||||
static void stmpe_of_probe(struct stmpe_platform_data *pdata,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct device_node *child;
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
static struct platform_driver syscon_driver;
|
||||
|
||||
struct syscon {
|
||||
void __iomem *base;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
@ -129,6 +128,7 @@ static int syscon_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct syscon *syscon;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
|
||||
syscon = devm_kzalloc(dev, sizeof(*syscon), GFP_KERNEL);
|
||||
if (!syscon)
|
||||
@ -138,12 +138,12 @@ static int syscon_probe(struct platform_device *pdev)
|
||||
if (!res)
|
||||
return -ENOENT;
|
||||
|
||||
syscon->base = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (!syscon->base)
|
||||
base = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (!base)
|
||||
return -ENOMEM;
|
||||
|
||||
syscon_regmap_config.max_register = res->end - res->start - 3;
|
||||
syscon->regmap = devm_regmap_init_mmio(dev, syscon->base,
|
||||
syscon->regmap = devm_regmap_init_mmio(dev, base,
|
||||
&syscon_regmap_config);
|
||||
if (IS_ERR(syscon->regmap)) {
|
||||
dev_err(dev, "regmap init failed\n");
|
||||
|
@ -281,7 +281,7 @@ static void t7l66xb_detach_irq(struct platform_device *dev)
|
||||
static int t7l66xb_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
|
||||
struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
|
||||
struct t7l66xb_platform_data *pdata = dev_get_platdata(&dev->dev);
|
||||
|
||||
if (pdata && pdata->suspend)
|
||||
pdata->suspend(dev);
|
||||
@ -293,7 +293,7 @@ static int t7l66xb_suspend(struct platform_device *dev, pm_message_t state)
|
||||
static int t7l66xb_resume(struct platform_device *dev)
|
||||
{
|
||||
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
|
||||
struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
|
||||
struct t7l66xb_platform_data *pdata = dev_get_platdata(&dev->dev);
|
||||
|
||||
clk_enable(t7l66xb->clk48m);
|
||||
if (pdata && pdata->resume)
|
||||
@ -313,7 +313,7 @@ static int t7l66xb_resume(struct platform_device *dev)
|
||||
|
||||
static int t7l66xb_probe(struct platform_device *dev)
|
||||
{
|
||||
struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
|
||||
struct t7l66xb_platform_data *pdata = dev_get_platdata(&dev->dev);
|
||||
struct t7l66xb *t7l66xb;
|
||||
struct resource *iomem, *rscr;
|
||||
int ret;
|
||||
@ -409,7 +409,7 @@ err_noirq:
|
||||
|
||||
static int t7l66xb_remove(struct platform_device *dev)
|
||||
{
|
||||
struct t7l66xb_platform_data *pdata = dev->dev.platform_data;
|
||||
struct t7l66xb_platform_data *pdata = dev_get_platdata(&dev->dev);
|
||||
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
|
@ -325,7 +325,7 @@ static int tc3589x_of_probe(struct device_node *np,
|
||||
static int tc3589x_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
|
||||
struct tc3589x_platform_data *pdata = dev_get_platdata(&i2c->dev);
|
||||
struct device_node *np = i2c->dev.of_node;
|
||||
struct tc3589x *tc3589x;
|
||||
int ret;
|
||||
|
@ -48,7 +48,7 @@ static struct resource tc6387xb_mmc_resources[] = {
|
||||
static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
|
||||
struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
|
||||
struct tc6387xb_platform_data *pdata = dev_get_platdata(&dev->dev);
|
||||
|
||||
if (pdata && pdata->suspend)
|
||||
pdata->suspend(dev);
|
||||
@ -60,7 +60,7 @@ static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state)
|
||||
static int tc6387xb_resume(struct platform_device *dev)
|
||||
{
|
||||
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
|
||||
struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
|
||||
struct tc6387xb_platform_data *pdata = dev_get_platdata(&dev->dev);
|
||||
|
||||
clk_enable(tc6387xb->clk32k);
|
||||
if (pdata && pdata->resume)
|
||||
@ -140,7 +140,7 @@ static struct mfd_cell tc6387xb_cells[] = {
|
||||
|
||||
static int tc6387xb_probe(struct platform_device *dev)
|
||||
{
|
||||
struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
|
||||
struct tc6387xb_platform_data *pdata = dev_get_platdata(&dev->dev);
|
||||
struct resource *iomem, *rscr;
|
||||
struct clk *clk32k;
|
||||
struct tc6387xb *tc6387xb;
|
||||
|
@ -604,7 +604,7 @@ static void tc6393xb_detach_irq(struct platform_device *dev)
|
||||
|
||||
static int tc6393xb_probe(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
|
||||
struct tc6393xb_platform_data *tcpd = dev_get_platdata(&dev->dev);
|
||||
struct tc6393xb *tc6393xb;
|
||||
struct resource *iomem, *rscr;
|
||||
int ret, temp;
|
||||
@ -733,7 +733,7 @@ err_kzalloc:
|
||||
|
||||
static int tc6393xb_remove(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
|
||||
struct tc6393xb_platform_data *tcpd = dev_get_platdata(&dev->dev);
|
||||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
@ -765,7 +765,7 @@ static int tc6393xb_remove(struct platform_device *dev)
|
||||
#ifdef CONFIG_PM
|
||||
static int tc6393xb_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
|
||||
struct tc6393xb_platform_data *tcpd = dev_get_platdata(&dev->dev);
|
||||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
int i, ret;
|
||||
|
||||
@ -788,7 +788,7 @@ static int tc6393xb_suspend(struct platform_device *dev, pm_message_t state)
|
||||
|
||||
static int tc6393xb_resume(struct platform_device *dev)
|
||||
{
|
||||
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
|
||||
struct tc6393xb_platform_data *tcpd = dev_get_platdata(&dev->dev);
|
||||
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
|
||||
int ret;
|
||||
int i;
|
||||
|
@ -318,7 +318,7 @@ static irqreturn_t ti_ssp_interrupt(int irq, void *dev_data)
|
||||
static int ti_ssp_probe(struct platform_device *pdev)
|
||||
{
|
||||
static struct ti_ssp *ssp;
|
||||
const struct ti_ssp_data *pdata = pdev->dev.platform_data;
|
||||
const struct ti_ssp_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
int error = 0, prediv = 0xff, id;
|
||||
unsigned long sysclk;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
@ -57,20 +57,20 @@ EXPORT_SYMBOL_GPL(am335x_tsc_se_update);
|
||||
void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val)
|
||||
{
|
||||
spin_lock(&tsadc->reg_lock);
|
||||
tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE);
|
||||
tsadc->reg_se_cache |= val;
|
||||
spin_unlock(&tsadc->reg_lock);
|
||||
|
||||
am335x_tsc_se_update(tsadc);
|
||||
spin_unlock(&tsadc->reg_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(am335x_tsc_se_set);
|
||||
|
||||
void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
|
||||
{
|
||||
spin_lock(&tsadc->reg_lock);
|
||||
tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE);
|
||||
tsadc->reg_se_cache &= ~val;
|
||||
spin_unlock(&tsadc->reg_lock);
|
||||
|
||||
am335x_tsc_se_update(tsadc);
|
||||
spin_unlock(&tsadc->reg_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(am335x_tsc_se_clr);
|
||||
|
||||
@ -197,23 +197,20 @@ static int ti_tscadc_probe(struct platform_device *pdev)
|
||||
clock_rate = clk_get_rate(clk);
|
||||
clk_put(clk);
|
||||
clk_value = clock_rate / ADC_CLK;
|
||||
if (clk_value < MAX_CLK_DIV) {
|
||||
dev_err(&pdev->dev, "clock input less than min clock requirement\n");
|
||||
err = -EINVAL;
|
||||
goto err_disable_clk;
|
||||
}
|
||||
|
||||
/* TSCADC_CLKDIV needs to be configured to the value minus 1 */
|
||||
clk_value = clk_value - 1;
|
||||
tscadc_writel(tscadc, REG_CLKDIV, clk_value);
|
||||
|
||||
/* Set the control register bits */
|
||||
ctrl = CNTRLREG_STEPCONFIGWRT |
|
||||
CNTRLREG_TSCENB |
|
||||
CNTRLREG_STEPID |
|
||||
CNTRLREG_4WIRE;
|
||||
CNTRLREG_STEPID;
|
||||
if (tsc_wires > 0)
|
||||
ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB;
|
||||
tscadc_writel(tscadc, REG_CTRL, ctrl);
|
||||
|
||||
/* Set register bits for Idle Config Mode */
|
||||
if (tsc_wires > 0)
|
||||
tscadc_idle_config(tscadc);
|
||||
|
||||
/* Enable the TSC module enable bit */
|
||||
@ -294,9 +291,12 @@ static int tscadc_resume(struct device *dev)
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
/* context restore */
|
||||
ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_TSCENB |
|
||||
CNTRLREG_STEPID | CNTRLREG_4WIRE;
|
||||
ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID;
|
||||
if (tscadc_dev->tsc_cell != -1)
|
||||
ctrl |= CNTRLREG_TSCENB | CNTRLREG_4WIRE;
|
||||
tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
|
||||
|
||||
if (tscadc_dev->tsc_cell != -1)
|
||||
tscadc_idle_config(tscadc_dev);
|
||||
am335x_tsc_se_update(tscadc_dev);
|
||||
restore = tscadc_readl(tscadc_dev, REG_CTRL);
|
||||
|
@ -115,11 +115,11 @@ static const struct resource timberdale_ocores_resources[] = {
|
||||
},
|
||||
};
|
||||
|
||||
const struct max7301_platform_data timberdale_max7301_platform_data = {
|
||||
static const struct max7301_platform_data timberdale_max7301_platform_data = {
|
||||
.base = 200
|
||||
};
|
||||
|
||||
const struct mc33880_platform_data timberdale_mc33880_platform_data = {
|
||||
static const struct mc33880_platform_data timberdale_mc33880_platform_data = {
|
||||
.base = 100
|
||||
};
|
||||
|
||||
@ -781,7 +781,6 @@ static int timb_probe(struct pci_dev *dev,
|
||||
priv->fw.major, priv->fw.minor, ip_setup);
|
||||
err = -ENODEV;
|
||||
goto err_mfd;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
@ -869,34 +868,7 @@ static struct pci_driver timberdale_pci_driver = {
|
||||
.remove = timb_remove,
|
||||
};
|
||||
|
||||
static int __init timberdale_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = pci_register_driver(&timberdale_pci_driver);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR
|
||||
"Failed to register PCI driver for %s device.\n",
|
||||
timberdale_pci_driver.name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Driver for %s has been successfully registered.\n",
|
||||
timberdale_pci_driver.name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit timberdale_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&timberdale_pci_driver);
|
||||
|
||||
printk(KERN_INFO "Driver for %s has been successfully unregistered.\n",
|
||||
timberdale_pci_driver.name);
|
||||
}
|
||||
|
||||
module_init(timberdale_init);
|
||||
module_exit(timberdale_exit);
|
||||
module_pci_driver(timberdale_pci_driver);
|
||||
|
||||
MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
|
@ -147,7 +147,7 @@ static int tps6105x_probe(struct i2c_client *client,
|
||||
|
||||
i2c_set_clientdata(client, tps6105x);
|
||||
tps6105x->client = client;
|
||||
pdata = client->dev.platform_data;
|
||||
pdata = dev_get_platdata(&client->dev);
|
||||
tps6105x->pdata = pdata;
|
||||
mutex_init(&tps6105x->lock);
|
||||
|
||||
|
@ -242,8 +242,8 @@ static int dbg_show(struct seq_file *s, void *_)
|
||||
seq_printf(s, "mask2 %s\n", buf);
|
||||
/* ignore ackint2 */
|
||||
|
||||
schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
|
||||
|
||||
queue_delayed_work(system_power_efficient_wq, &tps->work,
|
||||
POWER_POLL_DELAY);
|
||||
|
||||
/* VMAIN voltage, enable lowpower, etc */
|
||||
value = i2c_smbus_read_byte_data(tps->client, TPS_VDCDC1);
|
||||
@ -400,7 +400,8 @@ static void tps65010_interrupt(struct tps65010 *tps)
|
||||
&& (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC)))
|
||||
poll = 1;
|
||||
if (poll)
|
||||
schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
|
||||
queue_delayed_work(system_power_efficient_wq, &tps->work,
|
||||
POWER_POLL_DELAY);
|
||||
|
||||
/* also potentially gpio-in rise or fall */
|
||||
}
|
||||
@ -448,7 +449,7 @@ static irqreturn_t tps65010_irq(int irq, void *_tps)
|
||||
|
||||
disable_irq_nosync(irq);
|
||||
set_bit(FLAG_IRQ_ENABLE, &tps->flags);
|
||||
schedule_delayed_work(&tps->work, 0);
|
||||
queue_delayed_work(system_power_efficient_wq, &tps->work, 0);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -517,7 +518,7 @@ static struct tps65010 *the_tps;
|
||||
static int __exit tps65010_remove(struct i2c_client *client)
|
||||
{
|
||||
struct tps65010 *tps = i2c_get_clientdata(client);
|
||||
struct tps65010_board *board = client->dev.platform_data;
|
||||
struct tps65010_board *board = dev_get_platdata(&client->dev);
|
||||
|
||||
if (board && board->teardown) {
|
||||
int status = board->teardown(client, board->context);
|
||||
@ -529,7 +530,6 @@ static int __exit tps65010_remove(struct i2c_client *client)
|
||||
free_irq(client->irq, tps);
|
||||
cancel_delayed_work_sync(&tps->work);
|
||||
debugfs_remove(tps->file);
|
||||
kfree(tps);
|
||||
the_tps = NULL;
|
||||
return 0;
|
||||
}
|
||||
@ -539,7 +539,7 @@ static int tps65010_probe(struct i2c_client *client,
|
||||
{
|
||||
struct tps65010 *tps;
|
||||
int status;
|
||||
struct tps65010_board *board = client->dev.platform_data;
|
||||
struct tps65010_board *board = dev_get_platdata(&client->dev);
|
||||
|
||||
if (the_tps) {
|
||||
dev_dbg(&client->dev, "only one tps6501x chip allowed\n");
|
||||
@ -549,7 +549,7 @@ static int tps65010_probe(struct i2c_client *client,
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -EINVAL;
|
||||
|
||||
tps = kzalloc(sizeof *tps, GFP_KERNEL);
|
||||
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
|
||||
if (!tps)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -567,7 +567,7 @@ static int tps65010_probe(struct i2c_client *client,
|
||||
if (status < 0) {
|
||||
dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
|
||||
client->irq, status);
|
||||
goto fail1;
|
||||
return status;
|
||||
}
|
||||
/* annoying race here, ideally we'd have an option
|
||||
* to claim the irq now and enable it later.
|
||||
@ -667,9 +667,6 @@ static int tps65010_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail1:
|
||||
kfree(tps);
|
||||
return status;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tps65010_id[] = {
|
||||
@ -718,7 +715,8 @@ int tps65010_set_vbus_draw(unsigned mA)
|
||||
&& test_and_set_bit(
|
||||
FLAG_VBUS_CHANGED, &the_tps->flags)) {
|
||||
/* gadget drivers call this in_irq() */
|
||||
schedule_delayed_work(&the_tps->work, 0);
|
||||
queue_delayed_work(system_power_efficient_wq, &the_tps->work,
|
||||
0);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
||||
|
@ -172,7 +172,7 @@ MODULE_DEVICE_TABLE(of, tps65090_of_match);
|
||||
static int tps65090_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct tps65090_platform_data *pdata = client->dev.platform_data;
|
||||
struct tps65090_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
int irq_base = 0;
|
||||
struct tps65090 *tps65090;
|
||||
int ret;
|
||||
|
@ -462,7 +462,7 @@ static void tps6586x_power_off(void)
|
||||
static int tps6586x_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct tps6586x_platform_data *pdata = client->dev.platform_data;
|
||||
struct tps6586x_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct tps6586x *tps6586x;
|
||||
int ret;
|
||||
|
||||
|
@ -123,7 +123,7 @@ EXPORT_SYMBOL_GPL(tps65912_reg_write);
|
||||
|
||||
int tps65912_device_init(struct tps65912 *tps65912)
|
||||
{
|
||||
struct tps65912_board *pmic_plat_data = tps65912->dev->platform_data;
|
||||
struct tps65912_board *pmic_plat_data = dev_get_platdata(tps65912->dev);
|
||||
struct tps65912_platform_data *init_data;
|
||||
int ret, dcdc_avs, value;
|
||||
|
||||
|
@ -418,7 +418,7 @@ static const struct regmap_config tps80031_regmap_configs[] = {
|
||||
static int tps80031_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct tps80031_platform_data *pdata = client->dev.platform_data;
|
||||
struct tps80031_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct tps80031 *tps80031;
|
||||
int ret;
|
||||
uint8_t es_version;
|
||||
|
@ -1137,7 +1137,7 @@ static int twl_remove(struct i2c_client *client)
|
||||
static int
|
||||
twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
struct twl4030_platform_data *pdata = client->dev.platform_data;
|
||||
struct twl4030_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct device_node *node = client->dev.of_node;
|
||||
struct platform_device *pdev;
|
||||
struct regmap_config *twl_regmap_config;
|
||||
|
@ -187,7 +187,7 @@ static bool twl4030_audio_has_vibra(struct twl4030_audio_data *pdata,
|
||||
static int twl4030_audio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct twl4030_audio *audio;
|
||||
struct twl4030_audio_data *pdata = pdev->dev.platform_data;
|
||||
struct twl4030_audio_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct mfd_cell *cell = NULL;
|
||||
int ret, childs = 0;
|
||||
|
@ -701,7 +701,7 @@ static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
|
||||
static int twl4030_madc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct twl4030_madc_data *madc;
|
||||
struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct twl4030_madc_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
int ret;
|
||||
u8 regval;
|
||||
|
||||
|
@ -493,7 +493,7 @@ int twl4030_remove_script(u8 flags)
|
||||
return err;
|
||||
}
|
||||
|
||||
int twl4030_power_configure_scripts(struct twl4030_power_data *pdata)
|
||||
static int twl4030_power_configure_scripts(struct twl4030_power_data *pdata)
|
||||
{
|
||||
int err;
|
||||
int i;
|
||||
@ -509,7 +509,7 @@ int twl4030_power_configure_scripts(struct twl4030_power_data *pdata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int twl4030_power_configure_resources(struct twl4030_power_data *pdata)
|
||||
static int twl4030_power_configure_resources(struct twl4030_power_data *pdata)
|
||||
{
|
||||
struct twl4030_resconfig *resconfig = pdata->resource_config;
|
||||
int err;
|
||||
@ -553,9 +553,9 @@ static bool twl4030_power_use_poweroff(struct twl4030_power_data *pdata,
|
||||
return false;
|
||||
}
|
||||
|
||||
int twl4030_power_probe(struct platform_device *pdev)
|
||||
static int twl4030_power_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct twl4030_power_data *pdata = pdev->dev.platform_data;
|
||||
struct twl4030_power_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int err = 0;
|
||||
int err2 = 0;
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include "twl-core.h"
|
||||
|
||||
@ -84,39 +85,77 @@ static int twl6030_interrupt_mapping[24] = {
|
||||
CHARGERFAULT_INTR_OFFSET, /* Bit 22 INT_CHRG */
|
||||
RSV_INTR_OFFSET, /* Bit 23 Reserved */
|
||||
};
|
||||
|
||||
static int twl6032_interrupt_mapping[24] = {
|
||||
PWR_INTR_OFFSET, /* Bit 0 PWRON */
|
||||
PWR_INTR_OFFSET, /* Bit 1 RPWRON */
|
||||
PWR_INTR_OFFSET, /* Bit 2 SYS_VLOW */
|
||||
RTC_INTR_OFFSET, /* Bit 3 RTC_ALARM */
|
||||
RTC_INTR_OFFSET, /* Bit 4 RTC_PERIOD */
|
||||
HOTDIE_INTR_OFFSET, /* Bit 5 HOT_DIE */
|
||||
SMPSLDO_INTR_OFFSET, /* Bit 6 VXXX_SHORT */
|
||||
PWR_INTR_OFFSET, /* Bit 7 SPDURATION */
|
||||
|
||||
PWR_INTR_OFFSET, /* Bit 8 WATCHDOG */
|
||||
BATDETECT_INTR_OFFSET, /* Bit 9 BAT */
|
||||
SIMDETECT_INTR_OFFSET, /* Bit 10 SIM */
|
||||
MMCDETECT_INTR_OFFSET, /* Bit 11 MMC */
|
||||
MADC_INTR_OFFSET, /* Bit 12 GPADC_RT_EOC */
|
||||
MADC_INTR_OFFSET, /* Bit 13 GPADC_SW_EOC */
|
||||
GASGAUGE_INTR_OFFSET, /* Bit 14 CC_EOC */
|
||||
GASGAUGE_INTR_OFFSET, /* Bit 15 CC_AUTOCAL */
|
||||
|
||||
USBOTG_INTR_OFFSET, /* Bit 16 ID_WKUP */
|
||||
USBOTG_INTR_OFFSET, /* Bit 17 VBUS_WKUP */
|
||||
USBOTG_INTR_OFFSET, /* Bit 18 ID */
|
||||
USB_PRES_INTR_OFFSET, /* Bit 19 VBUS */
|
||||
CHARGER_INTR_OFFSET, /* Bit 20 CHRG_CTRL */
|
||||
CHARGERFAULT_INTR_OFFSET, /* Bit 21 EXT_CHRG */
|
||||
CHARGERFAULT_INTR_OFFSET, /* Bit 22 INT_CHRG */
|
||||
RSV_INTR_OFFSET, /* Bit 23 Reserved */
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static unsigned twl6030_irq_base;
|
||||
static int twl_irq;
|
||||
static bool twl_irq_wake_enabled;
|
||||
struct twl6030_irq {
|
||||
unsigned int irq_base;
|
||||
int twl_irq;
|
||||
bool irq_wake_enabled;
|
||||
atomic_t wakeirqs;
|
||||
struct notifier_block pm_nb;
|
||||
struct irq_chip irq_chip;
|
||||
struct irq_domain *irq_domain;
|
||||
const int *irq_mapping_tbl;
|
||||
};
|
||||
|
||||
static struct completion irq_event;
|
||||
static atomic_t twl6030_wakeirqs = ATOMIC_INIT(0);
|
||||
static struct twl6030_irq *twl6030_irq;
|
||||
|
||||
static int twl6030_irq_pm_notifier(struct notifier_block *notifier,
|
||||
unsigned long pm_event, void *unused)
|
||||
{
|
||||
int chained_wakeups;
|
||||
struct twl6030_irq *pdata = container_of(notifier, struct twl6030_irq,
|
||||
pm_nb);
|
||||
|
||||
switch (pm_event) {
|
||||
case PM_SUSPEND_PREPARE:
|
||||
chained_wakeups = atomic_read(&twl6030_wakeirqs);
|
||||
chained_wakeups = atomic_read(&pdata->wakeirqs);
|
||||
|
||||
if (chained_wakeups && !twl_irq_wake_enabled) {
|
||||
if (enable_irq_wake(twl_irq))
|
||||
if (chained_wakeups && !pdata->irq_wake_enabled) {
|
||||
if (enable_irq_wake(pdata->twl_irq))
|
||||
pr_err("twl6030 IRQ wake enable failed\n");
|
||||
else
|
||||
twl_irq_wake_enabled = true;
|
||||
} else if (!chained_wakeups && twl_irq_wake_enabled) {
|
||||
disable_irq_wake(twl_irq);
|
||||
twl_irq_wake_enabled = false;
|
||||
pdata->irq_wake_enabled = true;
|
||||
} else if (!chained_wakeups && pdata->irq_wake_enabled) {
|
||||
disable_irq_wake(pdata->twl_irq);
|
||||
pdata->irq_wake_enabled = false;
|
||||
}
|
||||
|
||||
disable_irq(twl_irq);
|
||||
disable_irq(pdata->twl_irq);
|
||||
break;
|
||||
|
||||
case PM_POST_SUSPEND:
|
||||
enable_irq(twl_irq);
|
||||
enable_irq(pdata->twl_irq);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -126,47 +165,27 @@ static int twl6030_irq_pm_notifier(struct notifier_block *notifier,
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block twl6030_irq_pm_notifier_block = {
|
||||
.notifier_call = twl6030_irq_pm_notifier,
|
||||
};
|
||||
|
||||
/*
|
||||
* This thread processes interrupts reported by the Primary Interrupt Handler.
|
||||
*/
|
||||
static int twl6030_irq_thread(void *data)
|
||||
* Threaded irq handler for the twl6030 interrupt.
|
||||
* We query the interrupt controller in the twl6030 to determine
|
||||
* which module is generating the interrupt request and call
|
||||
* handle_nested_irq for that module.
|
||||
*/
|
||||
static irqreturn_t twl6030_irq_thread(int irq, void *data)
|
||||
{
|
||||
long irq = (long)data;
|
||||
static unsigned i2c_errors;
|
||||
static const unsigned max_i2c_errors = 100;
|
||||
int ret;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
int i;
|
||||
int i, ret;
|
||||
union {
|
||||
u8 bytes[4];
|
||||
u32 int_sts;
|
||||
} sts;
|
||||
|
||||
/* Wait for IRQ, then read PIH irq status (also blocking) */
|
||||
wait_for_completion_interruptible(&irq_event);
|
||||
struct twl6030_irq *pdata = data;
|
||||
|
||||
/* read INT_STS_A, B and C in one shot using a burst read */
|
||||
ret = twl_i2c_read(TWL_MODULE_PIH, sts.bytes,
|
||||
REG_INT_STS_A, 3);
|
||||
ret = twl_i2c_read(TWL_MODULE_PIH, sts.bytes, REG_INT_STS_A, 3);
|
||||
if (ret) {
|
||||
pr_warning("twl6030: I2C error %d reading PIH ISR\n",
|
||||
ret);
|
||||
if (++i2c_errors >= max_i2c_errors) {
|
||||
printk(KERN_ERR "Maximum I2C error count"
|
||||
" exceeded. Terminating %s.\n",
|
||||
__func__);
|
||||
break;
|
||||
pr_warn("twl6030_irq: I2C error %d reading PIH ISR\n", ret);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
complete(&irq_event);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sts.bytes[3] = 0; /* Only 24 bits are valid*/
|
||||
|
||||
@ -177,15 +196,18 @@ static int twl6030_irq_thread(void *data)
|
||||
if (sts.bytes[2] & 0x10)
|
||||
sts.bytes[2] |= 0x08;
|
||||
|
||||
for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++) {
|
||||
local_irq_disable();
|
||||
for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++)
|
||||
if (sts.int_sts & 0x1) {
|
||||
int module_irq = twl6030_irq_base +
|
||||
twl6030_interrupt_mapping[i];
|
||||
generic_handle_irq(module_irq);
|
||||
|
||||
}
|
||||
local_irq_enable();
|
||||
int module_irq =
|
||||
irq_find_mapping(pdata->irq_domain,
|
||||
pdata->irq_mapping_tbl[i]);
|
||||
if (module_irq)
|
||||
handle_nested_irq(module_irq);
|
||||
else
|
||||
pr_err("twl6030_irq: Unmapped PIH ISR %u detected\n",
|
||||
i);
|
||||
pr_debug("twl6030_irq: PIH ISR %u, virq%u\n",
|
||||
i, module_irq);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -199,51 +221,21 @@ static int twl6030_irq_thread(void *data)
|
||||
*/
|
||||
ret = twl_i2c_write_u8(TWL_MODULE_PIH, 0x00, REG_INT_STS_A);
|
||||
if (ret)
|
||||
pr_warning("twl6030: I2C error in clearing PIH ISR\n");
|
||||
pr_warn("twl6030_irq: I2C error in clearing PIH ISR\n");
|
||||
|
||||
enable_irq(irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle_twl6030_int() is the desc->handle method for the twl6030 interrupt.
|
||||
* This is a chained interrupt, so there is no desc->action method for it.
|
||||
* Now we need to query the interrupt controller in the twl6030 to determine
|
||||
* which module is generating the interrupt request. However, we can't do i2c
|
||||
* transactions in interrupt context, so we must defer that work to a kernel
|
||||
* thread. All we do here is acknowledge and mask the interrupt and wakeup
|
||||
* the kernel thread.
|
||||
*/
|
||||
static irqreturn_t handle_twl6030_pih(int irq, void *devid)
|
||||
{
|
||||
disable_irq_nosync(irq);
|
||||
complete(devid);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static inline void activate_irq(int irq)
|
||||
{
|
||||
#ifdef CONFIG_ARM
|
||||
/* ARM requires an extra step to clear IRQ_NOREQUEST, which it
|
||||
* sets on behalf of every irq_chip. Also sets IRQ_NOPROBE.
|
||||
*/
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
#else
|
||||
/* same effect on other architectures */
|
||||
irq_set_noprobe(irq);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int twl6030_irq_set_wake(struct irq_data *d, unsigned int on)
|
||||
{
|
||||
struct twl6030_irq *pdata = irq_get_chip_data(d->irq);
|
||||
|
||||
if (on)
|
||||
atomic_inc(&twl6030_wakeirqs);
|
||||
atomic_inc(&pdata->wakeirqs);
|
||||
else
|
||||
atomic_dec(&twl6030_wakeirqs);
|
||||
atomic_dec(&pdata->wakeirqs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -318,7 +310,8 @@ int twl6030_mmc_card_detect_config(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return twl6030_irq_base + MMCDETECT_INTR_OFFSET;
|
||||
return irq_find_mapping(twl6030_irq->irq_domain,
|
||||
MMCDETECT_INTR_OFFSET);
|
||||
}
|
||||
EXPORT_SYMBOL(twl6030_mmc_card_detect_config);
|
||||
|
||||
@ -347,99 +340,143 @@ int twl6030_mmc_card_detect(struct device *dev, int slot)
|
||||
}
|
||||
EXPORT_SYMBOL(twl6030_mmc_card_detect);
|
||||
|
||||
static int twl6030_irq_map(struct irq_domain *d, unsigned int virq,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
struct twl6030_irq *pdata = d->host_data;
|
||||
|
||||
irq_set_chip_data(virq, pdata);
|
||||
irq_set_chip_and_handler(virq, &pdata->irq_chip, handle_simple_irq);
|
||||
irq_set_nested_thread(virq, true);
|
||||
irq_set_parent(virq, pdata->twl_irq);
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
/*
|
||||
* ARM requires an extra step to clear IRQ_NOREQUEST, which it
|
||||
* sets on behalf of every irq_chip. Also sets IRQ_NOPROBE.
|
||||
*/
|
||||
set_irq_flags(virq, IRQF_VALID);
|
||||
#else
|
||||
/* same effect on other architectures */
|
||||
irq_set_noprobe(virq);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void twl6030_irq_unmap(struct irq_domain *d, unsigned int virq)
|
||||
{
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(virq, 0);
|
||||
#endif
|
||||
irq_set_chip_and_handler(virq, NULL, NULL);
|
||||
irq_set_chip_data(virq, NULL);
|
||||
}
|
||||
|
||||
static struct irq_domain_ops twl6030_irq_domain_ops = {
|
||||
.map = twl6030_irq_map,
|
||||
.unmap = twl6030_irq_unmap,
|
||||
.xlate = irq_domain_xlate_onetwocell,
|
||||
};
|
||||
|
||||
static const struct of_device_id twl6030_of_match[] = {
|
||||
{.compatible = "ti,twl6030", &twl6030_interrupt_mapping},
|
||||
{.compatible = "ti,twl6032", &twl6032_interrupt_mapping},
|
||||
{ },
|
||||
};
|
||||
|
||||
int twl6030_init_irq(struct device *dev, int irq_num)
|
||||
{
|
||||
struct device_node *node = dev->of_node;
|
||||
int nr_irqs, irq_base, irq_end;
|
||||
struct task_struct *task;
|
||||
static struct irq_chip twl6030_irq_chip;
|
||||
int status = 0;
|
||||
int i;
|
||||
int nr_irqs;
|
||||
int status;
|
||||
u8 mask[3];
|
||||
const struct of_device_id *of_id;
|
||||
|
||||
of_id = of_match_device(twl6030_of_match, dev);
|
||||
if (!of_id || !of_id->data) {
|
||||
dev_err(dev, "Unknown TWL device model\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nr_irqs = TWL6030_NR_IRQS;
|
||||
|
||||
irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
|
||||
if (IS_ERR_VALUE(irq_base)) {
|
||||
dev_err(dev, "Fail to allocate IRQ descs\n");
|
||||
return irq_base;
|
||||
twl6030_irq = devm_kzalloc(dev, sizeof(*twl6030_irq), GFP_KERNEL);
|
||||
if (!twl6030_irq) {
|
||||
dev_err(dev, "twl6030_irq: Memory allocation failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
irq_domain_add_legacy(node, nr_irqs, irq_base, 0,
|
||||
&irq_domain_simple_ops, NULL);
|
||||
|
||||
irq_end = irq_base + nr_irqs;
|
||||
|
||||
mask[0] = 0xFF;
|
||||
mask[1] = 0xFF;
|
||||
mask[2] = 0xFF;
|
||||
|
||||
/* mask all int lines */
|
||||
twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_LINE_A, 3);
|
||||
status = twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_LINE_A, 3);
|
||||
/* mask all int sts */
|
||||
twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_STS_A, 3);
|
||||
status |= twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_STS_A, 3);
|
||||
/* clear INT_STS_A,B,C */
|
||||
twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_STS_A, 3);
|
||||
status |= twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_STS_A, 3);
|
||||
|
||||
twl6030_irq_base = irq_base;
|
||||
if (status < 0) {
|
||||
dev_err(dev, "I2C err writing TWL_MODULE_PIH: %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* install an irq handler for each of the modules;
|
||||
* clone dummy irq_chip since PIH can't *do* anything
|
||||
*/
|
||||
twl6030_irq_chip = dummy_irq_chip;
|
||||
twl6030_irq_chip.name = "twl6030";
|
||||
twl6030_irq_chip.irq_set_type = NULL;
|
||||
twl6030_irq_chip.irq_set_wake = twl6030_irq_set_wake;
|
||||
twl6030_irq->irq_chip = dummy_irq_chip;
|
||||
twl6030_irq->irq_chip.name = "twl6030";
|
||||
twl6030_irq->irq_chip.irq_set_type = NULL;
|
||||
twl6030_irq->irq_chip.irq_set_wake = twl6030_irq_set_wake;
|
||||
|
||||
for (i = irq_base; i < irq_end; i++) {
|
||||
irq_set_chip_and_handler(i, &twl6030_irq_chip,
|
||||
handle_simple_irq);
|
||||
irq_set_chip_data(i, (void *)irq_num);
|
||||
activate_irq(i);
|
||||
twl6030_irq->pm_nb.notifier_call = twl6030_irq_pm_notifier;
|
||||
atomic_set(&twl6030_irq->wakeirqs, 0);
|
||||
twl6030_irq->irq_mapping_tbl = of_id->data;
|
||||
|
||||
twl6030_irq->irq_domain =
|
||||
irq_domain_add_linear(node, nr_irqs,
|
||||
&twl6030_irq_domain_ops, twl6030_irq);
|
||||
if (!twl6030_irq->irq_domain) {
|
||||
dev_err(dev, "Can't add irq_domain\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev_info(dev, "PIH (irq %d) chaining IRQs %d..%d\n",
|
||||
irq_num, irq_base, irq_end);
|
||||
dev_info(dev, "PIH (irq %d) nested IRQs\n", irq_num);
|
||||
|
||||
/* install an irq handler to demultiplex the TWL6030 interrupt */
|
||||
init_completion(&irq_event);
|
||||
|
||||
status = request_irq(irq_num, handle_twl6030_pih, 0, "TWL6030-PIH",
|
||||
&irq_event);
|
||||
status = request_threaded_irq(irq_num, NULL, twl6030_irq_thread,
|
||||
IRQF_ONESHOT, "TWL6030-PIH", twl6030_irq);
|
||||
if (status < 0) {
|
||||
dev_err(dev, "could not claim irq %d: %d\n", irq_num, status);
|
||||
goto fail_irq;
|
||||
}
|
||||
|
||||
task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq");
|
||||
if (IS_ERR(task)) {
|
||||
dev_err(dev, "could not create irq %d thread!\n", irq_num);
|
||||
status = PTR_ERR(task);
|
||||
goto fail_kthread;
|
||||
}
|
||||
|
||||
twl_irq = irq_num;
|
||||
register_pm_notifier(&twl6030_irq_pm_notifier_block);
|
||||
return irq_base;
|
||||
|
||||
fail_kthread:
|
||||
free_irq(irq_num, &irq_event);
|
||||
twl6030_irq->twl_irq = irq_num;
|
||||
register_pm_notifier(&twl6030_irq->pm_nb);
|
||||
return 0;
|
||||
|
||||
fail_irq:
|
||||
for (i = irq_base; i < irq_end; i++)
|
||||
irq_set_chip_and_handler(i, NULL, NULL);
|
||||
|
||||
irq_domain_remove(twl6030_irq->irq_domain);
|
||||
return status;
|
||||
}
|
||||
|
||||
int twl6030_exit_irq(void)
|
||||
{
|
||||
unregister_pm_notifier(&twl6030_irq_pm_notifier_block);
|
||||
|
||||
if (twl6030_irq_base) {
|
||||
pr_err("twl6030: can't yet clean up IRQs?\n");
|
||||
return -ENOSYS;
|
||||
if (twl6030_irq && twl6030_irq->twl_irq) {
|
||||
unregister_pm_notifier(&twl6030_irq->pm_nb);
|
||||
free_irq(twl6030_irq->twl_irq, NULL);
|
||||
/*
|
||||
* TODO: IRQ domain and allocated nested IRQ descriptors
|
||||
* should be freed somehow here. Now It can't be done, because
|
||||
* child devices will not be deleted during removing of
|
||||
* TWL Core driver and they will still contain allocated
|
||||
* virt IRQs in their Resources tables.
|
||||
* The same prevents us from using devm_request_threaded_irq()
|
||||
* in this module.
|
||||
*/
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -44,17 +44,12 @@
|
||||
#define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
|
||||
#define TWL6040_NUM_SUPPLIES (2)
|
||||
|
||||
static bool twl6040_has_vibra(struct twl6040_platform_data *pdata,
|
||||
struct device_node *node)
|
||||
static bool twl6040_has_vibra(struct device_node *node)
|
||||
{
|
||||
if (pdata && pdata->vibra)
|
||||
return true;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
if (of_find_node_by_name(node, "vibra"))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -63,15 +58,9 @@ int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
|
||||
int ret;
|
||||
unsigned int val;
|
||||
|
||||
/* Vibra control registers from cache */
|
||||
if (unlikely(reg == TWL6040_REG_VIBCTLL ||
|
||||
reg == TWL6040_REG_VIBCTLR)) {
|
||||
val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)];
|
||||
} else {
|
||||
ret = regmap_read(twl6040->regmap, reg, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
@ -82,9 +71,6 @@ int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(twl6040->regmap, reg, val);
|
||||
/* Cache the vibra control registers */
|
||||
if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)
|
||||
twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -461,9 +447,20 @@ EXPORT_SYMBOL(twl6040_get_sysclk);
|
||||
/* Get the combined status of the vibra control register */
|
||||
int twl6040_get_vibralr_status(struct twl6040 *twl6040)
|
||||
{
|
||||
unsigned int reg;
|
||||
int ret;
|
||||
u8 status;
|
||||
|
||||
status = twl6040->vibra_ctrl_cache[0] | twl6040->vibra_ctrl_cache[1];
|
||||
ret = regmap_read(twl6040->regmap, TWL6040_REG_VIBCTLL, ®);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
status = reg;
|
||||
|
||||
ret = regmap_read(twl6040->regmap, TWL6040_REG_VIBCTLR, ®);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
status |= reg;
|
||||
|
||||
status &= (TWL6040_VIBENA | TWL6040_VIBSEL);
|
||||
|
||||
return status;
|
||||
@ -490,12 +487,27 @@ static bool twl6040_readable_reg(struct device *dev, unsigned int reg)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool twl6040_volatile_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case TWL6040_REG_VIBCTLL:
|
||||
case TWL6040_REG_VIBCTLR:
|
||||
case TWL6040_REG_INTMR:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static struct regmap_config twl6040_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = TWL6040_REG_STATUS, /* 0x2e */
|
||||
|
||||
.readable_reg = twl6040_readable_reg,
|
||||
.volatile_reg = twl6040_volatile_reg,
|
||||
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static const struct regmap_irq twl6040_irqs[] = {
|
||||
@ -520,14 +532,13 @@ static struct regmap_irq_chip twl6040_irq_chip = {
|
||||
static int twl6040_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct twl6040_platform_data *pdata = client->dev.platform_data;
|
||||
struct device_node *node = client->dev.of_node;
|
||||
struct twl6040 *twl6040;
|
||||
struct mfd_cell *cell = NULL;
|
||||
int irq, ret, children = 0;
|
||||
|
||||
if (!pdata && !node) {
|
||||
dev_err(&client->dev, "Platform data is missing\n");
|
||||
if (!node) {
|
||||
dev_err(&client->dev, "of node is missing\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -539,16 +550,12 @@ static int twl6040_probe(struct i2c_client *client,
|
||||
|
||||
twl6040 = devm_kzalloc(&client->dev, sizeof(struct twl6040),
|
||||
GFP_KERNEL);
|
||||
if (!twl6040) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
if (!twl6040)
|
||||
return -ENOMEM;
|
||||
|
||||
twl6040->regmap = devm_regmap_init_i2c(client, &twl6040_regmap_config);
|
||||
if (IS_ERR(twl6040->regmap)) {
|
||||
ret = PTR_ERR(twl6040->regmap);
|
||||
goto err;
|
||||
}
|
||||
if (IS_ERR(twl6040->regmap))
|
||||
return PTR_ERR(twl6040->regmap);
|
||||
|
||||
i2c_set_clientdata(client, twl6040);
|
||||
|
||||
@ -576,13 +583,10 @@ static int twl6040_probe(struct i2c_client *client,
|
||||
twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
|
||||
|
||||
/* ERRATA: Automatic power-up is not possible in ES1.0 */
|
||||
if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0) {
|
||||
if (pdata)
|
||||
twl6040->audpwron = pdata->audpwron_gpio;
|
||||
else
|
||||
if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0)
|
||||
twl6040->audpwron = of_get_named_gpio(node,
|
||||
"ti,audpwron-gpio", 0);
|
||||
} else
|
||||
else
|
||||
twl6040->audpwron = -EINVAL;
|
||||
|
||||
if (gpio_is_valid(twl6040->audpwron)) {
|
||||
@ -592,9 +596,8 @@ static int twl6040_probe(struct i2c_client *client,
|
||||
goto gpio_err;
|
||||
}
|
||||
|
||||
ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq,
|
||||
IRQF_ONESHOT, 0, &twl6040_irq_chip,
|
||||
&twl6040->irq_data);
|
||||
ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq, IRQF_ONESHOT,
|
||||
0, &twl6040_irq_chip,&twl6040->irq_data);
|
||||
if (ret < 0)
|
||||
goto gpio_err;
|
||||
|
||||
@ -625,8 +628,6 @@ static int twl6040_probe(struct i2c_client *client,
|
||||
/*
|
||||
* The main functionality of twl6040 to provide audio on OMAP4+ systems.
|
||||
* We can add the ASoC codec child whenever this driver has been loaded.
|
||||
* The ASoC codec can work without pdata, pass the platform_data only if
|
||||
* it has been provided.
|
||||
*/
|
||||
irq = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_PLUG);
|
||||
cell = &twl6040->cells[children];
|
||||
@ -635,13 +636,10 @@ static int twl6040_probe(struct i2c_client *client,
|
||||
twl6040_codec_rsrc[0].end = irq;
|
||||
cell->resources = twl6040_codec_rsrc;
|
||||
cell->num_resources = ARRAY_SIZE(twl6040_codec_rsrc);
|
||||
if (pdata && pdata->codec) {
|
||||
cell->platform_data = pdata->codec;
|
||||
cell->pdata_size = sizeof(*pdata->codec);
|
||||
}
|
||||
children++;
|
||||
|
||||
if (twl6040_has_vibra(pdata, node)) {
|
||||
/* Vibra input driver support */
|
||||
if (twl6040_has_vibra(node)) {
|
||||
irq = regmap_irq_get_virq(twl6040->irq_data, TWL6040_IRQ_VIB);
|
||||
|
||||
cell = &twl6040->cells[children];
|
||||
@ -650,28 +648,13 @@ static int twl6040_probe(struct i2c_client *client,
|
||||
twl6040_vibra_rsrc[0].end = irq;
|
||||
cell->resources = twl6040_vibra_rsrc;
|
||||
cell->num_resources = ARRAY_SIZE(twl6040_vibra_rsrc);
|
||||
|
||||
if (pdata && pdata->vibra) {
|
||||
cell->platform_data = pdata->vibra;
|
||||
cell->pdata_size = sizeof(*pdata->vibra);
|
||||
}
|
||||
children++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the GPO driver in the following cases:
|
||||
* DT booted kernel or legacy boot with valid gpo platform_data
|
||||
*/
|
||||
if (!pdata || (pdata && pdata->gpo)) {
|
||||
/* GPO support */
|
||||
cell = &twl6040->cells[children];
|
||||
cell->name = "twl6040-gpo";
|
||||
|
||||
if (pdata) {
|
||||
cell->platform_data = pdata->gpo;
|
||||
cell->pdata_size = sizeof(*pdata->gpo);
|
||||
}
|
||||
children++;
|
||||
}
|
||||
|
||||
ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
|
||||
NULL, 0, NULL);
|
||||
@ -690,7 +673,7 @@ gpio_err:
|
||||
regulator_bulk_disable(TWL6040_NUM_SUPPLIES, twl6040->supplies);
|
||||
regulator_get_err:
|
||||
i2c_set_clientdata(client, NULL);
|
||||
err:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ static int ucb1400_core_probe(struct device *dev)
|
||||
struct ucb1400_ts ucb_ts;
|
||||
struct ucb1400_gpio ucb_gpio;
|
||||
struct snd_ac97 *ac97;
|
||||
struct ucb1400_pdata *pdata = dev->platform_data;
|
||||
struct ucb1400_pdata *pdata = dev_get_platdata(dev);
|
||||
|
||||
memset(&ucb_ts, 0, sizeof(ucb_ts));
|
||||
memset(&ucb_gpio, 0, sizeof(ucb_gpio));
|
||||
|
@ -393,22 +393,24 @@ static struct irq_chip ucb1x00_irqchip = {
|
||||
static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv)
|
||||
{
|
||||
struct ucb1x00_dev *dev;
|
||||
int ret = -ENOMEM;
|
||||
int ret;
|
||||
|
||||
dev = kmalloc(sizeof(struct ucb1x00_dev), GFP_KERNEL);
|
||||
if (dev) {
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->ucb = ucb;
|
||||
dev->drv = drv;
|
||||
|
||||
ret = drv->add(dev);
|
||||
if (ret) {
|
||||
kfree(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
list_add_tail(&dev->dev_node, &ucb->devs);
|
||||
list_add_tail(&dev->drv_node, &drv->devs);
|
||||
} else {
|
||||
kfree(dev);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -669,9 +671,10 @@ void ucb1x00_unregister_driver(struct ucb1x00_driver *drv)
|
||||
mutex_unlock(&ucb1x00_mutex);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int ucb1x00_suspend(struct device *dev)
|
||||
{
|
||||
struct ucb1x00_plat_data *pdata = dev->platform_data;
|
||||
struct ucb1x00_plat_data *pdata = dev_get_platdata(dev);
|
||||
struct ucb1x00 *ucb = dev_get_drvdata(dev);
|
||||
struct ucb1x00_dev *udev;
|
||||
|
||||
@ -703,7 +706,7 @@ static int ucb1x00_suspend(struct device *dev)
|
||||
|
||||
static int ucb1x00_resume(struct device *dev)
|
||||
{
|
||||
struct ucb1x00_plat_data *pdata = dev->platform_data;
|
||||
struct ucb1x00_plat_data *pdata = dev_get_platdata(dev);
|
||||
struct ucb1x00 *ucb = dev_get_drvdata(dev);
|
||||
struct ucb1x00_dev *udev;
|
||||
|
||||
@ -736,6 +739,7 @@ static int ucb1x00_resume(struct device *dev)
|
||||
mutex_unlock(&ucb1x00_mutex);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops ucb1x00_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(ucb1x00_suspend, ucb1x00_resume)
|
||||
|
@ -172,12 +172,9 @@ static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume)
|
||||
|
||||
static int wl1273_core_remove(struct i2c_client *client)
|
||||
{
|
||||
struct wl1273_core *core = i2c_get_clientdata(client);
|
||||
|
||||
dev_dbg(&client->dev, "%s\n", __func__);
|
||||
|
||||
mfd_remove_devices(&client->dev);
|
||||
kfree(core);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -185,7 +182,7 @@ static int wl1273_core_remove(struct i2c_client *client)
|
||||
static int wl1273_core_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct wl1273_fm_platform_data *pdata = client->dev.platform_data;
|
||||
struct wl1273_fm_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct wl1273_core *core;
|
||||
struct mfd_cell *cell;
|
||||
int children = 0;
|
||||
@ -203,7 +200,7 @@ static int wl1273_core_probe(struct i2c_client *client,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
core = kzalloc(sizeof(*core), GFP_KERNEL);
|
||||
core = devm_kzalloc(&client->dev, sizeof(*core), GFP_KERNEL);
|
||||
if (!core)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -249,7 +246,6 @@ static int wl1273_core_probe(struct i2c_client *client,
|
||||
|
||||
err:
|
||||
pdata->free_resources();
|
||||
kfree(core);
|
||||
|
||||
dev_dbg(&client->dev, "%s\n", __func__);
|
||||
|
||||
|
@ -468,12 +468,14 @@ static const struct reg_default wm5110_reg_default[] = {
|
||||
{ 0x00000176, 0x0000 }, /* R374 - FLL1 Control 6 */
|
||||
{ 0x00000177, 0x0281 }, /* R375 - FLL1 Loop Filter Test 1 */
|
||||
{ 0x00000178, 0x0000 }, /* R376 - FLL1 NCO Test 0 */
|
||||
{ 0x00000179, 0x0000 }, /* R376 - FLL1 Control 7 */
|
||||
{ 0x00000181, 0x0000 }, /* R385 - FLL1 Synchroniser 1 */
|
||||
{ 0x00000182, 0x0000 }, /* R386 - FLL1 Synchroniser 2 */
|
||||
{ 0x00000183, 0x0000 }, /* R387 - FLL1 Synchroniser 3 */
|
||||
{ 0x00000184, 0x0000 }, /* R388 - FLL1 Synchroniser 4 */
|
||||
{ 0x00000185, 0x0000 }, /* R389 - FLL1 Synchroniser 5 */
|
||||
{ 0x00000186, 0x0000 }, /* R390 - FLL1 Synchroniser 6 */
|
||||
{ 0x00000187, 0x0001 }, /* R390 - FLL1 Synchroniser 7 */
|
||||
{ 0x00000189, 0x0000 }, /* R393 - FLL1 Spread Spectrum */
|
||||
{ 0x0000018A, 0x0004 }, /* R394 - FLL1 GPIO Clock */
|
||||
{ 0x00000191, 0x0000 }, /* R401 - FLL2 Control 1 */
|
||||
@ -484,12 +486,14 @@ static const struct reg_default wm5110_reg_default[] = {
|
||||
{ 0x00000196, 0x0000 }, /* R406 - FLL2 Control 6 */
|
||||
{ 0x00000197, 0x0000 }, /* R407 - FLL2 Loop Filter Test 1 */
|
||||
{ 0x00000198, 0x0000 }, /* R408 - FLL2 NCO Test 0 */
|
||||
{ 0x00000199, 0x0000 }, /* R408 - FLL2 Control 7 */
|
||||
{ 0x000001A1, 0x0000 }, /* R417 - FLL2 Synchroniser 1 */
|
||||
{ 0x000001A2, 0x0000 }, /* R418 - FLL2 Synchroniser 2 */
|
||||
{ 0x000001A3, 0x0000 }, /* R419 - FLL2 Synchroniser 3 */
|
||||
{ 0x000001A4, 0x0000 }, /* R420 - FLL2 Synchroniser 4 */
|
||||
{ 0x000001A5, 0x0000 }, /* R421 - FLL2 Synchroniser 5 */
|
||||
{ 0x000001A6, 0x0000 }, /* R422 - FLL2 Synchroniser 6 */
|
||||
{ 0x000001A7, 0x0001 }, /* R422 - FLL2 Synchroniser 7 */
|
||||
{ 0x000001A9, 0x0000 }, /* R425 - FLL2 Spread Spectrum */
|
||||
{ 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */
|
||||
{ 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */
|
||||
@ -503,6 +507,11 @@ static const struct reg_default wm5110_reg_default[] = {
|
||||
{ 0x0000029C, 0x0000 }, /* R668 - Headphone Detect 2 */
|
||||
{ 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */
|
||||
{ 0x000002A4, 0x009F }, /* R676 - Mic Detect 2 */
|
||||
{ 0x000002A5, 0x0000 }, /* R677 - Mic Detect 3 */
|
||||
{ 0x000002A6, 0x3737 }, /* R678 - Mic Detect Level 1 */
|
||||
{ 0x000002A7, 0x372C }, /* R679 - Mic Detect Level 2 */
|
||||
{ 0x000002A8, 0x1422 }, /* R680 - Mic Detect Level 3 */
|
||||
{ 0x000002A9, 0x300A }, /* R681 - Mic Detect Level 4 */
|
||||
{ 0x000002C3, 0x0000 }, /* R707 - Mic noise mix control 1 */
|
||||
{ 0x000002D3, 0x0000 }, /* R723 - Jack detect analogue */
|
||||
{ 0x00000300, 0x0000 }, /* R768 - Input Enables */
|
||||
@ -1392,6 +1401,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
|
||||
case ARIZONA_FLL1_CONTROL_4:
|
||||
case ARIZONA_FLL1_CONTROL_5:
|
||||
case ARIZONA_FLL1_CONTROL_6:
|
||||
case ARIZONA_FLL1_CONTROL_7:
|
||||
case ARIZONA_FLL1_LOOP_FILTER_TEST_1:
|
||||
case ARIZONA_FLL1_NCO_TEST_0:
|
||||
case ARIZONA_FLL1_SYNCHRONISER_1:
|
||||
@ -1400,6 +1410,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
|
||||
case ARIZONA_FLL1_SYNCHRONISER_4:
|
||||
case ARIZONA_FLL1_SYNCHRONISER_5:
|
||||
case ARIZONA_FLL1_SYNCHRONISER_6:
|
||||
case ARIZONA_FLL1_SYNCHRONISER_7:
|
||||
case ARIZONA_FLL1_SPREAD_SPECTRUM:
|
||||
case ARIZONA_FLL1_GPIO_CLOCK:
|
||||
case ARIZONA_FLL2_CONTROL_1:
|
||||
@ -1408,6 +1419,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
|
||||
case ARIZONA_FLL2_CONTROL_4:
|
||||
case ARIZONA_FLL2_CONTROL_5:
|
||||
case ARIZONA_FLL2_CONTROL_6:
|
||||
case ARIZONA_FLL2_CONTROL_7:
|
||||
case ARIZONA_FLL2_LOOP_FILTER_TEST_1:
|
||||
case ARIZONA_FLL2_NCO_TEST_0:
|
||||
case ARIZONA_FLL2_SYNCHRONISER_1:
|
||||
@ -1416,6 +1428,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
|
||||
case ARIZONA_FLL2_SYNCHRONISER_4:
|
||||
case ARIZONA_FLL2_SYNCHRONISER_5:
|
||||
case ARIZONA_FLL2_SYNCHRONISER_6:
|
||||
case ARIZONA_FLL2_SYNCHRONISER_7:
|
||||
case ARIZONA_FLL2_SPREAD_SPECTRUM:
|
||||
case ARIZONA_FLL2_GPIO_CLOCK:
|
||||
case ARIZONA_MIC_CHARGE_PUMP_1:
|
||||
@ -1430,6 +1443,10 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
|
||||
case ARIZONA_MIC_DETECT_1:
|
||||
case ARIZONA_MIC_DETECT_2:
|
||||
case ARIZONA_MIC_DETECT_3:
|
||||
case ARIZONA_MIC_DETECT_LEVEL_1:
|
||||
case ARIZONA_MIC_DETECT_LEVEL_2:
|
||||
case ARIZONA_MIC_DETECT_LEVEL_3:
|
||||
case ARIZONA_MIC_DETECT_LEVEL_4:
|
||||
case ARIZONA_MIC_NOISE_MIX_CONTROL_1:
|
||||
case ARIZONA_JACK_DETECT_ANALOGUE:
|
||||
case ARIZONA_INPUT_ENABLES:
|
||||
@ -2332,6 +2349,7 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
|
||||
case ARIZONA_IRQ_PIN_STATUS:
|
||||
case ARIZONA_AOD_IRQ1:
|
||||
case ARIZONA_AOD_IRQ2:
|
||||
case ARIZONA_FX_CTRL2:
|
||||
case ARIZONA_ASRC_STATUS:
|
||||
case ARIZONA_DSP_STATUS:
|
||||
case ARIZONA_DSP1_CONTROL_1:
|
||||
|
@ -1618,7 +1618,7 @@ EXPORT_SYMBOL_GPL(wm831x_regmap_config);
|
||||
*/
|
||||
int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
|
||||
{
|
||||
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
|
||||
struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
|
||||
int rev, wm831x_num;
|
||||
enum wm831x_parent parent;
|
||||
int ret, i;
|
||||
|
@ -571,7 +571,7 @@ static struct irq_domain_ops wm831x_irq_domain_ops = {
|
||||
|
||||
int wm831x_irq_init(struct wm831x *wm831x, int irq)
|
||||
{
|
||||
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
|
||||
struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
|
||||
struct irq_domain *domain;
|
||||
int i, ret, irq_base;
|
||||
|
||||
|
@ -34,7 +34,6 @@ static int wm831x_spi_probe(struct spi_device *spi)
|
||||
if (wm831x == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
spi->bits_per_word = 16;
|
||||
spi->mode = SPI_MODE_0;
|
||||
|
||||
spi_set_drvdata(spi, wm831x);
|
||||
|
@ -27,6 +27,7 @@ static int wm8350_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct wm8350 *wm8350;
|
||||
struct wm8350_platform_data *pdata = dev_get_platdata(&i2c->dev);
|
||||
int ret = 0;
|
||||
|
||||
wm8350 = devm_kzalloc(&i2c->dev, sizeof(struct wm8350), GFP_KERNEL);
|
||||
@ -44,7 +45,7 @@ static int wm8350_i2c_probe(struct i2c_client *i2c,
|
||||
i2c_set_clientdata(i2c, wm8350);
|
||||
wm8350->dev = &i2c->dev;
|
||||
|
||||
return wm8350_device_init(wm8350, i2c->irq, i2c->dev.platform_data);
|
||||
return wm8350_device_init(wm8350, i2c->irq, pdata);
|
||||
}
|
||||
|
||||
static int wm8350_i2c_remove(struct i2c_client *i2c)
|
||||
|
@ -178,7 +178,7 @@ static int wm8400_i2c_probe(struct i2c_client *i2c,
|
||||
wm8400->dev = &i2c->dev;
|
||||
i2c_set_clientdata(i2c, wm8400);
|
||||
|
||||
ret = wm8400_init(wm8400, i2c->dev.platform_data);
|
||||
ret = wm8400_init(wm8400, dev_get_platdata(&i2c->dev));
|
||||
if (ret != 0)
|
||||
goto err;
|
||||
|
||||
|
@ -201,35 +201,7 @@ static int wm8994_suspend(struct device *dev)
|
||||
int ret;
|
||||
|
||||
/* Don't actually go through with the suspend if the CODEC is
|
||||
* still active (eg, for audio passthrough from CP. */
|
||||
ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_1);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to read power status: %d\n", ret);
|
||||
} else if (ret & WM8994_VMID_SEL_MASK) {
|
||||
dev_dbg(dev, "CODEC still active, ignoring suspend\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_4);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to read power status: %d\n", ret);
|
||||
} else if (ret & (WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA |
|
||||
WM8994_AIF1ADC2L_ENA | WM8994_AIF1ADC2R_ENA |
|
||||
WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC1R_ENA)) {
|
||||
dev_dbg(dev, "CODEC still active, ignoring suspend\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_5);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to read power status: %d\n", ret);
|
||||
} else if (ret & (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
|
||||
WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA |
|
||||
WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA)) {
|
||||
dev_dbg(dev, "CODEC still active, ignoring suspend\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
* still active for accessory detect. */
|
||||
switch (wm8994->type) {
|
||||
case WM8958:
|
||||
case WM1811:
|
||||
@ -245,20 +217,6 @@ static int wm8994_suspend(struct device *dev)
|
||||
break;
|
||||
}
|
||||
|
||||
switch (wm8994->type) {
|
||||
case WM1811:
|
||||
ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to read jackdet: %d\n", ret);
|
||||
} else if (ret & WM1811_JACKDET_MODE_MASK) {
|
||||
dev_dbg(dev, "CODEC still active, ignoring suspend\n");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable LDO pulldowns while the device is suspended if we
|
||||
* don't know that something will be driving them. */
|
||||
if (!wm8994->ldo_ena_always_driven)
|
||||
|
@ -193,7 +193,7 @@ int wm8994_irq_init(struct wm8994 *wm8994)
|
||||
{
|
||||
int ret;
|
||||
unsigned long irqflags;
|
||||
struct wm8994_pdata *pdata = wm8994->dev->platform_data;
|
||||
struct wm8994_pdata *pdata = dev_get_platdata(wm8994->dev);
|
||||
|
||||
if (!wm8994->irq) {
|
||||
dev_warn(wm8994->dev,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Realtek PCI-Express SD/MMC Card Interface driver
|
||||
*
|
||||
* Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
|
||||
* Copyright(c) 2009-2013 Realtek Semiconductor Corp. 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 the
|
||||
@ -17,7 +17,6 @@
|
||||
*
|
||||
* Author:
|
||||
* Wei WANG <wei_wang@realsil.com.cn>
|
||||
* No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -56,7 +55,6 @@ struct realtek_pci_sdmmc {
|
||||
bool double_clk;
|
||||
bool eject;
|
||||
bool initial_mode;
|
||||
bool ddr_mode;
|
||||
int power_state;
|
||||
#define SDMMC_POWER_ON 1
|
||||
#define SDMMC_POWER_OFF 0
|
||||
@ -228,6 +226,7 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
|
||||
int stat_idx = 0;
|
||||
u8 rsp_type;
|
||||
int rsp_len = 5;
|
||||
bool clock_toggled = false;
|
||||
|
||||
dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n",
|
||||
__func__, cmd_idx, arg);
|
||||
@ -271,6 +270,8 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
|
||||
0xFF, SD_CLK_TOGGLE_EN);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
clock_toggled = true;
|
||||
}
|
||||
|
||||
rtsx_pci_init_cmd(pcr);
|
||||
@ -351,6 +352,10 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
|
||||
|
||||
out:
|
||||
cmd->error = err;
|
||||
|
||||
if (err && clock_toggled)
|
||||
rtsx_pci_write_register(pcr, SD_BUS_STAT,
|
||||
SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
|
||||
}
|
||||
|
||||
static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
|
||||
@ -475,18 +480,24 @@ static void sd_normal_rw(struct realtek_pci_sdmmc *host,
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
static int sd_change_phase(struct realtek_pci_sdmmc *host, u8 sample_point)
|
||||
static int sd_change_phase(struct realtek_pci_sdmmc *host,
|
||||
u8 sample_point, bool rx)
|
||||
{
|
||||
struct rtsx_pcr *pcr = host->pcr;
|
||||
int err;
|
||||
|
||||
dev_dbg(sdmmc_dev(host), "%s: sample_point = %d\n",
|
||||
__func__, sample_point);
|
||||
dev_dbg(sdmmc_dev(host), "%s(%s): sample_point = %d\n",
|
||||
__func__, rx ? "RX" : "TX", sample_point);
|
||||
|
||||
rtsx_pci_init_cmd(pcr);
|
||||
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPRX_CTL, 0x1F, sample_point);
|
||||
if (rx)
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
|
||||
SD_VPRX_CTL, 0x1F, sample_point);
|
||||
else
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
|
||||
SD_VPTX_CTL, 0x1F, sample_point);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
|
||||
PHASE_NOT_RESET, PHASE_NOT_RESET);
|
||||
@ -602,7 +613,7 @@ static int sd_tuning_rx_cmd(struct realtek_pci_sdmmc *host,
|
||||
int err;
|
||||
u8 cmd[5] = {0};
|
||||
|
||||
err = sd_change_phase(host, sample_point);
|
||||
err = sd_change_phase(host, sample_point, true);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@ -664,7 +675,7 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode)
|
||||
if (final_phase == 0xFF)
|
||||
return -EINVAL;
|
||||
|
||||
err = sd_change_phase(host, final_phase);
|
||||
err = sd_change_phase(host, final_phase, true);
|
||||
if (err < 0)
|
||||
return err;
|
||||
} else {
|
||||
@ -833,14 +844,11 @@ static int sd_set_power_mode(struct realtek_pci_sdmmc *host,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sd_set_timing(struct realtek_pci_sdmmc *host,
|
||||
unsigned char timing, bool *ddr_mode)
|
||||
static int sd_set_timing(struct realtek_pci_sdmmc *host, unsigned char timing)
|
||||
{
|
||||
struct rtsx_pcr *pcr = host->pcr;
|
||||
int err = 0;
|
||||
|
||||
*ddr_mode = false;
|
||||
|
||||
rtsx_pci_init_cmd(pcr);
|
||||
|
||||
switch (timing) {
|
||||
@ -857,8 +865,6 @@ static int sd_set_timing(struct realtek_pci_sdmmc *host,
|
||||
break;
|
||||
|
||||
case MMC_TIMING_UHS_DDR50:
|
||||
*ddr_mode = true;
|
||||
|
||||
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,
|
||||
0x0C | SD_ASYNC_FIFO_NOT_RST,
|
||||
SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST);
|
||||
@ -926,7 +932,7 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
|
||||
sd_set_bus_width(host, ios->bus_width);
|
||||
sd_set_power_mode(host, ios->power_mode);
|
||||
sd_set_timing(host, ios->timing, &host->ddr_mode);
|
||||
sd_set_timing(host, ios->timing);
|
||||
|
||||
host->vpclk = false;
|
||||
host->double_clk = true;
|
||||
@ -1121,11 +1127,11 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
/* Stop toggle SD clock in idle */
|
||||
err = rtsx_pci_write_register(pcr, SD_BUS_STAT,
|
||||
SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
|
||||
|
||||
out:
|
||||
mutex_unlock(&pcr->pcr_mutex);
|
||||
|
||||
return err;
|
||||
@ -1148,9 +1154,35 @@ static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
||||
|
||||
rtsx_pci_start_run(pcr);
|
||||
|
||||
if (!host->ddr_mode)
|
||||
err = sd_tuning_rx(host, MMC_SEND_TUNING_BLOCK);
|
||||
/* Set initial TX phase */
|
||||
switch (mmc->ios.timing) {
|
||||
case MMC_TIMING_UHS_SDR104:
|
||||
err = sd_change_phase(host, SDR104_TX_PHASE(pcr), false);
|
||||
break;
|
||||
|
||||
case MMC_TIMING_UHS_SDR50:
|
||||
err = sd_change_phase(host, SDR50_TX_PHASE(pcr), false);
|
||||
break;
|
||||
|
||||
case MMC_TIMING_UHS_DDR50:
|
||||
err = sd_change_phase(host, DDR50_TX_PHASE(pcr), false);
|
||||
break;
|
||||
|
||||
default:
|
||||
err = 0;
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
/* Tuning RX phase */
|
||||
if ((mmc->ios.timing == MMC_TIMING_UHS_SDR104) ||
|
||||
(mmc->ios.timing == MMC_TIMING_UHS_SDR50))
|
||||
err = sd_tuning_rx(host, opcode);
|
||||
else if (mmc->ios.timing == MMC_TIMING_UHS_DDR50)
|
||||
err = sd_change_phase(host, DDR50_RX_PHASE(pcr), true);
|
||||
|
||||
out:
|
||||
mutex_unlock(&pcr->pcr_mutex);
|
||||
|
||||
return err;
|
||||
|
93
include/linux/mfd/da9063/core.h
Normal file
93
include/linux/mfd/da9063/core.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Definitions for DA9063 MFD driver
|
||||
*
|
||||
* Copyright 2012 Dialog Semiconductor Ltd.
|
||||
*
|
||||
* Author: Michal Hajduk <michal.hajduk@diasemi.com>
|
||||
* Krystian Garbaciak <krystian.garbaciak@diasemi.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MFD_DA9063_CORE_H__
|
||||
#define __MFD_DA9063_CORE_H__
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/da9063/registers.h>
|
||||
|
||||
/* DA9063 modules */
|
||||
#define DA9063_DRVNAME_CORE "da9063-core"
|
||||
#define DA9063_DRVNAME_REGULATORS "da9063-regulators"
|
||||
#define DA9063_DRVNAME_LEDS "da9063-leds"
|
||||
#define DA9063_DRVNAME_WATCHDOG "da9063-watchdog"
|
||||
#define DA9063_DRVNAME_HWMON "da9063-hwmon"
|
||||
#define DA9063_DRVNAME_ONKEY "da9063-onkey"
|
||||
#define DA9063_DRVNAME_RTC "da9063-rtc"
|
||||
#define DA9063_DRVNAME_VIBRATION "da9063-vibration"
|
||||
|
||||
enum da9063_models {
|
||||
PMIC_DA9063 = 0x61,
|
||||
};
|
||||
|
||||
/* Interrupts */
|
||||
enum da9063_irqs {
|
||||
DA9063_IRQ_ONKEY = 0,
|
||||
DA9063_IRQ_ALARM,
|
||||
DA9063_IRQ_TICK,
|
||||
DA9063_IRQ_ADC_RDY,
|
||||
DA9063_IRQ_SEQ_RDY,
|
||||
DA9063_IRQ_WAKE,
|
||||
DA9063_IRQ_TEMP,
|
||||
DA9063_IRQ_COMP_1V2,
|
||||
DA9063_IRQ_LDO_LIM,
|
||||
DA9063_IRQ_REG_UVOV,
|
||||
DA9063_IRQ_VDD_MON,
|
||||
DA9063_IRQ_WARN,
|
||||
DA9063_IRQ_GPI0,
|
||||
DA9063_IRQ_GPI1,
|
||||
DA9063_IRQ_GPI2,
|
||||
DA9063_IRQ_GPI3,
|
||||
DA9063_IRQ_GPI4,
|
||||
DA9063_IRQ_GPI5,
|
||||
DA9063_IRQ_GPI6,
|
||||
DA9063_IRQ_GPI7,
|
||||
DA9063_IRQ_GPI8,
|
||||
DA9063_IRQ_GPI9,
|
||||
DA9063_IRQ_GPI10,
|
||||
DA9063_IRQ_GPI11,
|
||||
DA9063_IRQ_GPI12,
|
||||
DA9063_IRQ_GPI13,
|
||||
DA9063_IRQ_GPI14,
|
||||
DA9063_IRQ_GPI15,
|
||||
};
|
||||
|
||||
#define DA9063_IRQ_BASE_OFFSET 0
|
||||
#define DA9063_NUM_IRQ (DA9063_IRQ_GPI15 + 1 - DA9063_IRQ_BASE_OFFSET)
|
||||
|
||||
struct da9063 {
|
||||
/* Device */
|
||||
struct device *dev;
|
||||
unsigned short model;
|
||||
unsigned short revision;
|
||||
unsigned int flags;
|
||||
|
||||
/* Control interface */
|
||||
struct regmap *regmap;
|
||||
|
||||
/* Interrupts */
|
||||
int chip_irq;
|
||||
unsigned int irq_base;
|
||||
struct regmap_irq_chip_data *regmap_irq;
|
||||
};
|
||||
|
||||
int da9063_device_init(struct da9063 *da9063, unsigned int irq);
|
||||
int da9063_irq_init(struct da9063 *da9063);
|
||||
|
||||
void da9063_device_exit(struct da9063 *da9063);
|
||||
void da9063_irq_exit(struct da9063 *da9063);
|
||||
|
||||
#endif /* __MFD_DA9063_CORE_H__ */
|
111
include/linux/mfd/da9063/pdata.h
Normal file
111
include/linux/mfd/da9063/pdata.h
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Platform configuration options for DA9063
|
||||
*
|
||||
* Copyright 2012 Dialog Semiconductor Ltd.
|
||||
*
|
||||
* Author: Michal Hajduk <michal.hajduk@diasemi.com>
|
||||
* Author: Krystian Garbaciak <krystian.garbaciak@diasemi.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MFD_DA9063_PDATA_H__
|
||||
#define __MFD_DA9063_PDATA_H__
|
||||
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
/*
|
||||
* Regulator configuration
|
||||
*/
|
||||
/* DA9063 regulator IDs */
|
||||
enum {
|
||||
/* BUCKs */
|
||||
DA9063_ID_BCORE1,
|
||||
DA9063_ID_BCORE2,
|
||||
DA9063_ID_BPRO,
|
||||
DA9063_ID_BMEM,
|
||||
DA9063_ID_BIO,
|
||||
DA9063_ID_BPERI,
|
||||
|
||||
/* BCORE1 and BCORE2 in merged mode */
|
||||
DA9063_ID_BCORES_MERGED,
|
||||
/* BMEM and BIO in merged mode */
|
||||
DA9063_ID_BMEM_BIO_MERGED,
|
||||
/* When two BUCKs are merged, they cannot be reused separately */
|
||||
|
||||
/* LDOs */
|
||||
DA9063_ID_LDO1,
|
||||
DA9063_ID_LDO2,
|
||||
DA9063_ID_LDO3,
|
||||
DA9063_ID_LDO4,
|
||||
DA9063_ID_LDO5,
|
||||
DA9063_ID_LDO6,
|
||||
DA9063_ID_LDO7,
|
||||
DA9063_ID_LDO8,
|
||||
DA9063_ID_LDO9,
|
||||
DA9063_ID_LDO10,
|
||||
DA9063_ID_LDO11,
|
||||
};
|
||||
|
||||
/* Regulators platform data */
|
||||
struct da9063_regulator_data {
|
||||
int id;
|
||||
struct regulator_init_data *initdata;
|
||||
};
|
||||
|
||||
struct da9063_regulators_pdata {
|
||||
unsigned n_regulators;
|
||||
struct da9063_regulator_data *regulator_data;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* RGB LED configuration
|
||||
*/
|
||||
/* LED IDs for flags in struct led_info. */
|
||||
enum {
|
||||
DA9063_GPIO11_LED,
|
||||
DA9063_GPIO14_LED,
|
||||
DA9063_GPIO15_LED,
|
||||
|
||||
DA9063_LED_NUM
|
||||
};
|
||||
#define DA9063_LED_ID_MASK 0x3
|
||||
|
||||
/* LED polarity for flags in struct led_info. */
|
||||
#define DA9063_LED_HIGH_LEVEL_ACTIVE 0x0
|
||||
#define DA9063_LED_LOW_LEVEL_ACTIVE 0x4
|
||||
|
||||
|
||||
/*
|
||||
* General PMIC configuration
|
||||
*/
|
||||
/* HWMON ADC channels configuration */
|
||||
#define DA9063_FLG_FORCE_IN0_MANUAL_MODE 0x0010
|
||||
#define DA9063_FLG_FORCE_IN0_AUTO_MODE 0x0020
|
||||
#define DA9063_FLG_FORCE_IN1_MANUAL_MODE 0x0040
|
||||
#define DA9063_FLG_FORCE_IN1_AUTO_MODE 0x0080
|
||||
#define DA9063_FLG_FORCE_IN2_MANUAL_MODE 0x0100
|
||||
#define DA9063_FLG_FORCE_IN2_AUTO_MODE 0x0200
|
||||
#define DA9063_FLG_FORCE_IN3_MANUAL_MODE 0x0400
|
||||
#define DA9063_FLG_FORCE_IN3_AUTO_MODE 0x0800
|
||||
|
||||
/* Disable register caching. */
|
||||
#define DA9063_FLG_NO_CACHE 0x0008
|
||||
|
||||
struct da9063;
|
||||
|
||||
/* DA9063 platform data */
|
||||
struct da9063_pdata {
|
||||
int (*init)(struct da9063 *da9063);
|
||||
int irq_base;
|
||||
unsigned flags;
|
||||
struct da9063_regulators_pdata *regulators_pdata;
|
||||
struct led_platform_data *leds_pdata;
|
||||
};
|
||||
|
||||
#endif /* __MFD_DA9063_PDATA_H__ */
|
1028
include/linux/mfd/da9063/registers.h
Normal file
1028
include/linux/mfd/da9063/registers.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -30,6 +30,8 @@
|
||||
|
||||
#include <mach/hardware.h>
|
||||
|
||||
struct regmap;
|
||||
|
||||
/*
|
||||
* Register values.
|
||||
*/
|
||||
@ -113,6 +115,7 @@ struct davinci_vc {
|
||||
|
||||
/* Memory resources */
|
||||
void __iomem *base;
|
||||
struct regmap *regmap;
|
||||
|
||||
/* MFD cells */
|
||||
struct mfd_cell cells[DAVINCI_VC_CELLS];
|
||||
|
@ -10,6 +10,8 @@
|
||||
#ifndef MCP_H
|
||||
#define MCP_H
|
||||
|
||||
#include <linux/device.h>
|
||||
|
||||
struct mcp_ops;
|
||||
|
||||
struct mcp {
|
||||
|
@ -184,6 +184,50 @@ enum palmas_regulators {
|
||||
PALMAS_NUM_REGS,
|
||||
};
|
||||
|
||||
/* External controll signal name */
|
||||
enum {
|
||||
PALMAS_EXT_CONTROL_ENABLE1 = 0x1,
|
||||
PALMAS_EXT_CONTROL_ENABLE2 = 0x2,
|
||||
PALMAS_EXT_CONTROL_NSLEEP = 0x4,
|
||||
};
|
||||
|
||||
/*
|
||||
* Palmas device resources can be controlled externally for
|
||||
* enabling/disabling it rather than register write through i2c.
|
||||
* Add the external controlled requestor ID for different resources.
|
||||
*/
|
||||
enum palmas_external_requestor_id {
|
||||
PALMAS_EXTERNAL_REQSTR_ID_REGEN1,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_REGEN2,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_SYSEN1,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_SYSEN2,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_CLK32KG,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_CLK32KGAUDIO,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_REGEN3,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_SMPS12,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_SMPS3,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_SMPS45,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_SMPS6,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_SMPS7,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_SMPS8,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_SMPS9,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_SMPS10,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_LDO1,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_LDO2,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_LDO3,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_LDO4,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_LDO5,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_LDO6,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_LDO7,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_LDO8,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_LDO9,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_LDOLN,
|
||||
PALMAS_EXTERNAL_REQSTR_ID_LDOUSB,
|
||||
|
||||
/* Last entry */
|
||||
PALMAS_EXTERNAL_REQSTR_ID_MAX,
|
||||
};
|
||||
|
||||
struct palmas_pmic_platform_data {
|
||||
/* An array of pointers to regulator init data indexed by regulator
|
||||
* ID
|
||||
@ -259,6 +303,7 @@ struct palmas_platform_data {
|
||||
*/
|
||||
int mux_from_pdata;
|
||||
u8 pad1, pad2;
|
||||
bool pm_off;
|
||||
|
||||
struct palmas_pmic_platform_data *pmic_pdata;
|
||||
struct palmas_gpadc_platform_data *gpadc_pdata;
|
||||
@ -2878,4 +2923,9 @@ static inline int palmas_irq_get_virq(struct palmas *palmas, int irq)
|
||||
return regmap_irq_get_virq(palmas->irq_data, irq);
|
||||
}
|
||||
|
||||
|
||||
int palmas_ext_control_req_config(struct palmas *palmas,
|
||||
enum palmas_external_requestor_id ext_control_req_id,
|
||||
int ext_ctrl, bool enable);
|
||||
|
||||
#endif /* __LINUX_MFD_PALMAS_H */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user