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:
Linus Torvalds 2013-09-07 20:14:19 -07:00
commit 8de4651abe
106 changed files with 3220 additions and 654 deletions

View File

@ -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

View 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>;
};
};
};

View File

@ -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";

View File

@ -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>

View File

@ -333,9 +333,11 @@ static int device_rtc_init(struct pm80x_chip *chip,
{
int ret;
rtc_devs[0].platform_data = pdata->rtc;
rtc_devs[0].pdata_size =
pdata->rtc ? sizeof(struct pm80x_rtc_pdata) : 0;
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;

View File

@ -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:

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;

View File

@ -494,7 +494,7 @@ static int da903x_add_subdevs(struct da903x_chip *chip,
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;

View File

@ -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);

View File

@ -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,

View File

@ -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
View 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
View 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
View 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);
}

View File

@ -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");

View File

@ -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 @@ int prcmu_ac_wake_req(void)
/**
* 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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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__);

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
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;
}

View File

@ -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 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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) {

View File

@ -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 @@ static struct platform_device *omap_usbhs_alloc_child(const char *name,
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;

View File

@ -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,10 +546,13 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
*/
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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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, &reg1);
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, &reg3);
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, &reg);
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)) {

View File

@ -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, &reg);
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, &reg);
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;

View File

@ -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, &reg);
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, &reg);
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 */
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
SD30_CLK_DRIVE_SEL, 0xFF, 0x96);
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);
/* 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,
AUTOLOAD_CFG_BASE + 3, 0xB8, 0xB8);
else
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
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;

View File

@ -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, &reg);
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, &reg);
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;

View File

@ -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, &reg);
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, &reg);
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 */
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
SD30_CLK_DRIVE_SEL, 0xFF, 0x99);
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);
/* Configure driving */
rts5249_fill_driving(pcr, OUTPUT_3V3);
if (pcr->flags & PCR_REVERSE_SOCKET)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
AUTOLOAD_CFG_BASE + 3, 0xB0, 0xB0);
else
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
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;

View File

@ -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 @@ static int rtsx_pci_resume(struct pci_dev *pcidev)
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);

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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");

View File

@ -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 @@ static int t7l66xb_probe(struct platform_device *dev)
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;

View File

@ -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;

View File

@ -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;

View File

@ -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 @@ static int tc6393xb_probe(struct platform_device *dev)
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;

View File

@ -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;

View File

@ -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,24 +197,21 @@ 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 */
tscadc_idle_config(tscadc);
if (tsc_wires > 0)
tscadc_idle_config(tscadc);
/* Enable the TSC module enable bit */
ctrl = tscadc_readl(tscadc, REG_CTRL);
@ -294,10 +291,13 @@ 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);
tscadc_idle_config(tscadc_dev);
if (tscadc_dev->tsc_cell != -1)
tscadc_idle_config(tscadc_dev);
am335x_tsc_se_update(tscadc_dev);
restore = tscadc_readl(tscadc_dev, REG_CTRL);
tscadc_writel(tscadc_dev, REG_CTRL,

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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,124 +165,77 @@ 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;
union {
int i, ret;
union {
u8 bytes[4];
u32 int_sts;
} sts;
} sts;
struct twl6030_irq *pdata = data;
/* Wait for IRQ, then read PIH irq status (also blocking) */
wait_for_completion_interruptible(&irq_event);
/* 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);
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;
}
complete(&irq_event);
continue;
}
sts.bytes[3] = 0; /* Only 24 bits are valid*/
/*
* Since VBUS status bit is not reliable for VBUS disconnect
* use CHARGER VBUS detection status bit instead.
*/
if (sts.bytes[2] & 0x10)
sts.bytes[2] |= 0x08;
for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++) {
local_irq_disable();
if (sts.int_sts & 0x1) {
int module_irq = twl6030_irq_base +
twl6030_interrupt_mapping[i];
generic_handle_irq(module_irq);
}
local_irq_enable();
}
/*
* NOTE:
* Simulation confirms that documentation is wrong w.r.t the
* interrupt status clear operation. A single *byte* write to
* any one of STS_A to STS_C register results in all three
* STS registers being reset. Since it does not matter which
* value is written, all three registers are cleared on a
* single byte write, so we just use 0x0 to clear.
*/
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");
enable_irq(irq);
/* 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);
if (ret) {
pr_warn("twl6030_irq: I2C error %d reading PIH ISR\n", ret);
return IRQ_HANDLED;
}
return 0;
}
sts.bytes[3] = 0; /* Only 24 bits are valid*/
/*
* Since VBUS status bit is not reliable for VBUS disconnect
* use CHARGER VBUS detection status bit instead.
*/
if (sts.bytes[2] & 0x10)
sts.bytes[2] |= 0x08;
for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++)
if (sts.int_sts & 0x1) {
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);
}
/*
* NOTE:
* Simulation confirms that documentation is wrong w.r.t the
* interrupt status clear operation. A single *byte* write to
* any one of STS_A to STS_C register results in all three
* STS registers being reset. Since it does not matter which
* value is written, all three registers are cleared on a
* single byte write, so we just use 0x0 to clear.
*/
ret = twl_i2c_write_u8(TWL_MODULE_PIH, 0x00, REG_INT_STS_A);
if (ret)
pr_warn("twl6030_irq: I2C error in clearing PIH ISR\n");
/*
* 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;
}

View File

@ -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;
}
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, &reg);
if (ret != 0)
return ret;
status = reg;
ret = regmap_read(twl6040->regmap, TWL6040_REG_VIBCTLR, &reg);
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,23 +550,19 @@ 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);
twl6040->supplies[0].supply = "vio";
twl6040->supplies[1].supply = "v2v1";
ret = devm_regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES,
twl6040->supplies);
twl6040->supplies);
if (ret != 0) {
dev_err(&client->dev, "Failed to get supplies: %d\n", ret);
goto regulator_get_err;
@ -576,44 +583,40 @@ 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
twl6040->audpwron = of_get_named_gpio(node,
"ti,audpwron-gpio", 0);
} else
if (twl6040_get_revid(twl6040) > TWL6040_REV_ES1_0)
twl6040->audpwron = of_get_named_gpio(node,
"ti,audpwron-gpio", 0);
else
twl6040->audpwron = -EINVAL;
if (gpio_is_valid(twl6040->audpwron)) {
ret = devm_gpio_request_one(&client->dev, twl6040->audpwron,
GPIOF_OUT_INIT_LOW, "audpwron");
GPIOF_OUT_INIT_LOW, "audpwron");
if (ret)
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;
twl6040->irq_ready = regmap_irq_get_virq(twl6040->irq_data,
TWL6040_IRQ_READY);
TWL6040_IRQ_READY);
twl6040->irq_th = regmap_irq_get_virq(twl6040->irq_data,
TWL6040_IRQ_TH);
TWL6040_IRQ_TH);
ret = devm_request_threaded_irq(twl6040->dev, twl6040->irq_ready, NULL,
twl6040_readyint_handler, IRQF_ONESHOT,
"twl6040_irq_ready", twl6040);
twl6040_readyint_handler, IRQF_ONESHOT,
"twl6040_irq_ready", twl6040);
if (ret) {
dev_err(twl6040->dev, "READY IRQ request failed: %d\n", ret);
goto readyirq_err;
}
ret = devm_request_threaded_irq(twl6040->dev, twl6040->irq_th, NULL,
twl6040_thint_handler, IRQF_ONESHOT,
"twl6040_irq_th", twl6040);
twl6040_thint_handler, IRQF_ONESHOT,
"twl6040_irq_th", twl6040);
if (ret) {
dev_err(twl6040->dev, "Thermal IRQ request failed: %d\n", ret);
goto thirq_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)) {
cell = &twl6040->cells[children];
cell->name = "twl6040-gpo";
if (pdata) {
cell->platform_data = pdata->gpo;
cell->pdata_size = sizeof(*pdata->gpo);
}
children++;
}
/* GPO support */
cell = &twl6040->cells[children];
cell->name = "twl6040-gpo";
children++;
ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
NULL, 0, NULL);
@ -690,7 +673,7 @@ static int twl6040_probe(struct i2c_client *client,
regulator_bulk_disable(TWL6040_NUM_SUPPLIES, twl6040->supplies);
regulator_get_err:
i2c_set_clientdata(client, NULL);
err:
return ret;
}

View File

@ -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));

View File

@ -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) {
dev->ucb = ucb;
dev->drv = drv;
if (!dev)
return -ENOMEM;
ret = drv->add(dev);
dev->ucb = ucb;
dev->drv = drv;
if (ret == 0) {
list_add_tail(&dev->dev_node, &ucb->devs);
list_add_tail(&dev->drv_node, &drv->devs);
} else {
kfree(dev);
}
ret = drv->add(dev);
if (ret) {
kfree(dev);
return ret;
}
list_add_tail(&dev->dev_node, &ucb->devs);
list_add_tail(&dev->drv_node, &drv->devs);
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)

View File

@ -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__);

View File

@ -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:

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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,

View File

@ -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;

View 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__ */

View 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__ */

File diff suppressed because it is too large Load Diff

View File

@ -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];

View File

@ -10,6 +10,8 @@
#ifndef MCP_H
#define MCP_H
#include <linux/device.h>
struct mcp_ops;
struct mcp {

View File

@ -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