summaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-01-29 19:59:24 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2018-01-29 19:59:24 +0100
commitbc4e118355caf83f472a5d31b850e73adddcf0ab (patch)
treea2263dff4a54ce68c648292721612c7ae6f50225 /drivers/mfd
parentMerge tag 'pnp-4.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/raf... (diff)
parentmfd: lpc_ich: Do not touch SPI-NOR write protection bit on Apollo Lake (diff)
downloadlinux-bc4e118355caf83f472a5d31b850e73adddcf0ab.tar.xz
linux-bc4e118355caf83f472a5d31b850e73adddcf0ab.zip
Merge tag 'mfd-next-4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones: "New Drivers: - Add support for RAVE Supervisory Processor Moved drivers: - Move Realtek Card Reader Driver to Misc New Device Support: - Add support for Pinctrl to axp20x New Functionality: - Add resume support to atmel-flexcom Fix-ups: - Split MFD (mfd) and userspace handlers (platform) in cros_ec - Fix trivial (whitespace, spelling) issue(s) in pcf50633-core - Clean-up error handling in ab8500-debugfs - General tidying up in tmio_core - Kconfig fix-ups for qcom-pm8xxx - Licensing changes (SPDX) to stm32-lptimer, stm32-timers - Device Tree fixups in mc13xxx - Simplify/remove unused code in cros_ec_spi, axp20x, ti_am335x_tscadc, kempld-core, intel_soc_pmic_core.c, ab8500-debugfs" * tag 'mfd-next-4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (32 commits) mfd: lpc_ich: Do not touch SPI-NOR write protection bit on Apollo Lake mfd: axp20x: Mark axp288 CHRG_BAK_CTRL register volatile mfd: ab8500: Introduce DEFINE_SHOW_ATTRIBUTE() macro atmel_flexcom: Support resuming after a chip reset mfd: Remove duplicate includes dt-bindings: mfd: mc13xxx: Add the unit address to sysled mfd: stm32: Adopt SPDX identifier mfd: axp20x: Add pinctrl cell for AXP813 mfd: pm8xxx: Make elegible for COMPILE_TEST mfd: kempld-core: Use resource_size function on resource object mfd: tmio: Move register macros to tmio_core.c mfd: cros ec: spi: Simplify delay handling between SPI messages mfd: palmas: Assign the right powerhold mask for tps65917 mfd: ab8500-debugfs: Use common error handling code in ab8500_print_modem_registers() mfd: ti_am335x_tscadc: Remove redundant assignment to node mfd: pcf50633: Fix spelling mistake: 'Falied' -> 'Failed' dt-bindings: watchdog: Add bindings for RAVE SP watchdog driver watchdog: Add RAVE SP watchdog driver mfd: Add driver for RAVE Supervisory Processor serdev: Introduce devm_serdev_device_open() ...
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Kconfig41
-rw-r--r--drivers/mfd/Makefile7
-rw-r--r--drivers/mfd/ab8500-debugfs.c439
-rw-r--r--drivers/mfd/atmel-flexcom.c63
-rw-r--r--drivers/mfd/axp20x.c4
-rw-r--r--drivers/mfd/cros_ec.c4
-rw-r--r--drivers/mfd/cros_ec_dev.c552
-rw-r--r--drivers/mfd/cros_ec_dev.h52
-rw-r--r--drivers/mfd/cros_ec_spi.c25
-rw-r--r--drivers/mfd/intel_soc_pmic_core.c1
-rw-r--r--drivers/mfd/kempld-core.c2
-rw-r--r--drivers/mfd/lpc_ich.c5
-rw-r--r--drivers/mfd/max77843.c1
-rw-r--r--drivers/mfd/palmas.c10
-rw-r--r--drivers/mfd/pcf50633-core.c2
-rw-r--r--drivers/mfd/rave-sp.c710
-rw-r--r--drivers/mfd/rtl8411.c508
-rw-r--r--drivers/mfd/rts5209.c277
-rw-r--r--drivers/mfd/rts5227.c374
-rw-r--r--drivers/mfd/rts5229.c273
-rw-r--r--drivers/mfd/rts5249.c741
-rw-r--r--drivers/mfd/rtsx_pcr.c1572
-rw-r--r--drivers/mfd/rtsx_pcr.h103
-rw-r--r--drivers/mfd/rtsx_usb.c791
-rw-r--r--drivers/mfd/stm32-lptimer.c6
-rw-r--r--drivers/mfd/stm32-timers.c4
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c2
-rw-r--r--drivers/mfd/tmio_core.c20
28 files changed, 1513 insertions, 5076 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 1d20a800e967..b860eb5aa194 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -222,6 +222,16 @@ config MFD_CROS_EC_SPI
response time cannot be guaranteed, we support ignoring
'pre-amble' bytes before the response actually starts.
+config MFD_CROS_EC_CHARDEV
+ tristate "Chrome OS Embedded Controller userspace device interface"
+ depends on MFD_CROS_EC
+ select CROS_EC_CTL
+ ---help---
+ This driver adds support to talk with the ChromeOS EC from userspace.
+
+ If you have a supported Chromebook, choose Y or M here.
+ The module will be called cros_ec_dev.
+
config MFD_ASIC3
bool "Compaq ASIC3"
depends on GPIOLIB && ARM
@@ -877,7 +887,7 @@ config UCB1400_CORE
config MFD_PM8XXX
tristate "Qualcomm PM8xxx PMIC chips driver"
- depends on (ARM || HEXAGON)
+ depends on (ARM || HEXAGON || COMPILE_TEST)
select IRQ_DOMAIN
select MFD_CORE
select REGMAP
@@ -929,17 +939,6 @@ config MFD_RDC321X
southbridge which provides access to GPIOs and Watchdog using the
southbridge PCI device configuration space.
-config MFD_RTSX_PCI
- tristate "Realtek PCI-E card reader"
- depends on PCI
- select MFD_CORE
- help
- This supports for Realtek PCI-Express card reader including rts5209,
- rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411, etc.
- Realtek card reader supports access to many types of memory cards,
- such as Memory Stick, Memory Stick Pro, Secure Digital and
- MultiMediaCard.
-
config MFD_RT5033
tristate "Richtek RT5033 Power Management IC"
depends on I2C
@@ -953,16 +952,6 @@ config MFD_RT5033
sub-devices like charger, fuel gauge, flash LED, current source,
LDO and Buck.
-config MFD_RTSX_USB
- tristate "Realtek USB card reader"
- depends on USB
- select MFD_CORE
- help
- Select this option to get support for Realtek USB 2.0 card readers
- including RTS5129, RTS5139, RTS5179 and RTS5170.
- Realtek card reader supports access to many types of memory cards,
- such as Memory Stick Pro, Secure Digital and MultiMediaCard.
-
config MFD_RC5T583
bool "Ricoh RC5T583 Power Management system device"
depends on I2C=y
@@ -1859,5 +1848,13 @@ config MFD_VEXPRESS_SYSREG
System Registers are the platform configuration block
on the ARM Ltd. Versatile Express board.
+config RAVE_SP_CORE
+ tristate "RAVE SP MCU core driver"
+ depends on SERIAL_DEV_BUS
+ select CRC_CCITT
+ help
+ Select this to get support for the Supervisory Processor
+ device found on several devices in RAVE line of hardware.
+
endmenu
endif
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index d9474ade32e6..d9d2cf0d32ef 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -17,12 +17,9 @@ cros_ec_core-$(CONFIG_ACPI) += cros_ec_acpi_gpe.o
obj-$(CONFIG_MFD_CROS_EC) += cros_ec_core.o
obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
+obj-$(CONFIG_MFD_CROS_EC_CHARDEV) += cros_ec_dev.o
obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
-rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
-obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o
-obj-$(CONFIG_MFD_RTSX_USB) += rtsx_usb.o
-
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o
@@ -230,3 +227,5 @@ obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o
obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o
obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o
+obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o
+
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
index c1c815241e02..1afa27de7191 100644
--- a/drivers/mfd/ab8500-debugfs.c
+++ b/drivers/mfd/ab8500-debugfs.c
@@ -1258,6 +1258,19 @@ static struct ab8500_prcmu_ranges ab8540_debug_ranges[AB8500_NUM_BANKS] = {
},
};
+#define DEFINE_SHOW_ATTRIBUTE(__name) \
+static int __name ## _open(struct inode *inode, struct file *file) \
+{ \
+ return single_open(file, __name ## _show, inode->i_private); \
+} \
+ \
+static const struct file_operations __name ## _fops = { \
+ .owner = THIS_MODULE, \
+ .open = __name ## _open, \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .release = single_release, \
+} \
static irqreturn_t ab8500_debug_handler(int irq, void *data)
{
@@ -1318,7 +1331,7 @@ static int ab8500_registers_print(struct device *dev, u32 bank,
return 0;
}
-static int ab8500_print_bank_registers(struct seq_file *s, void *p)
+static int ab8500_bank_registers_show(struct seq_file *s, void *p)
{
struct device *dev = s->private;
u32 bank = debug_bank;
@@ -1330,18 +1343,7 @@ static int ab8500_print_bank_registers(struct seq_file *s, void *p)
return ab8500_registers_print(dev, bank, s);
}
-static int ab8500_registers_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_print_bank_registers, inode->i_private);
-}
-
-static const struct file_operations ab8500_registers_fops = {
- .open = ab8500_registers_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8500_bank_registers);
static int ab8500_print_all_banks(struct seq_file *s, void *p)
{
@@ -1528,7 +1530,7 @@ void ab8500_debug_register_interrupt(int line)
num_interrupts[line]++;
}
-static int ab8500_interrupts_print(struct seq_file *s, void *p)
+static int ab8500_interrupts_show(struct seq_file *s, void *p)
{
int line;
@@ -1557,10 +1559,7 @@ static int ab8500_interrupts_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_interrupts_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_interrupts_print, inode->i_private);
-}
+DEFINE_SHOW_ATTRIBUTE(ab8500_interrupts);
/*
* - HWREG DB8500 formated routines
@@ -1603,7 +1602,7 @@ static int ab8500_hwreg_open(struct inode *inode, struct file *file)
#define AB8500_LAST_SIM_REG 0x8B
#define AB8505_LAST_SIM_REG 0x8C
-static int ab8500_print_modem_registers(struct seq_file *s, void *p)
+static int ab8500_modem_show(struct seq_file *s, void *p)
{
struct device *dev = s->private;
struct ab8500 *ab8500;
@@ -1620,18 +1619,15 @@ static int ab8500_print_modem_registers(struct seq_file *s, void *p)
err = abx500_get_register_interruptible(dev,
AB8500_REGU_CTRL1, AB8500_SUPPLY_CONTROL_REG, &orig_value);
- if (err < 0) {
- dev_err(dev, "ab->read fail %d\n", err);
- return err;
- }
+ if (err < 0)
+ goto report_read_failure;
+
/* Config 1 will allow APE side to read SIM registers */
err = abx500_set_register_interruptible(dev,
AB8500_REGU_CTRL1, AB8500_SUPPLY_CONTROL_REG,
AB8500_SUPPLY_CONTROL_CONFIG_1);
- if (err < 0) {
- dev_err(dev, "ab->write fail %d\n", err);
- return err;
- }
+ if (err < 0)
+ goto report_write_failure;
seq_printf(s, " bank 0x%02X:\n", bank);
@@ -1641,36 +1637,30 @@ static int ab8500_print_modem_registers(struct seq_file *s, void *p)
for (reg = AB8500_FIRST_SIM_REG; reg <= last_sim_reg; reg++) {
err = abx500_get_register_interruptible(dev,
bank, reg, &value);
- if (err < 0) {
- dev_err(dev, "ab->read fail %d\n", err);
- return err;
- }
+ if (err < 0)
+ goto report_read_failure;
+
seq_printf(s, " [0x%02X/0x%02X]: 0x%02X\n", bank, reg, value);
}
err = abx500_set_register_interruptible(dev,
AB8500_REGU_CTRL1, AB8500_SUPPLY_CONTROL_REG, orig_value);
- if (err < 0) {
- dev_err(dev, "ab->write fail %d\n", err);
- return err;
- }
+ if (err < 0)
+ goto report_write_failure;
+
return 0;
-}
-static int ab8500_modem_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_print_modem_registers,
- inode->i_private);
+report_read_failure:
+ dev_err(dev, "ab->read fail %d\n", err);
+ return err;
+
+report_write_failure:
+ dev_err(dev, "ab->write fail %d\n", err);
+ return err;
}
-static const struct file_operations ab8500_modem_fops = {
- .open = ab8500_modem_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8500_modem);
-static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_bat_ctrl_show(struct seq_file *s, void *p)
{
int bat_ctrl_raw;
int bat_ctrl_convert;
@@ -1687,21 +1677,9 @@ static int ab8500_gpadc_bat_ctrl_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_bat_ctrl_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_gpadc_bat_ctrl_print,
- inode->i_private);
-}
-
-static const struct file_operations ab8500_gpadc_bat_ctrl_fops = {
- .open = ab8500_gpadc_bat_ctrl_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_bat_ctrl);
-static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_btemp_ball_show(struct seq_file *s, void *p)
{
int btemp_ball_raw;
int btemp_ball_convert;
@@ -1718,22 +1696,9 @@ static int ab8500_gpadc_btemp_ball_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_btemp_ball_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ab8500_gpadc_btemp_ball_print,
- inode->i_private);
-}
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_btemp_ball);
-static const struct file_operations ab8500_gpadc_btemp_ball_fops = {
- .open = ab8500_gpadc_btemp_ball_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_main_charger_v_show(struct seq_file *s, void *p)
{
int main_charger_v_raw;
int main_charger_v_convert;
@@ -1750,22 +1715,9 @@ static int ab8500_gpadc_main_charger_v_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_main_charger_v_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ab8500_gpadc_main_charger_v_print,
- inode->i_private);
-}
-
-static const struct file_operations ab8500_gpadc_main_charger_v_fops = {
- .open = ab8500_gpadc_main_charger_v_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_main_charger_v);
-static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_acc_detect1_show(struct seq_file *s, void *p)
{
int acc_detect1_raw;
int acc_detect1_convert;
@@ -1782,22 +1734,9 @@ static int ab8500_gpadc_acc_detect1_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_acc_detect1_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ab8500_gpadc_acc_detect1_print,
- inode->i_private);
-}
-
-static const struct file_operations ab8500_gpadc_acc_detect1_fops = {
- .open = ab8500_gpadc_acc_detect1_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_acc_detect1);
-static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_acc_detect2_show(struct seq_file *s, void *p)
{
int acc_detect2_raw;
int acc_detect2_convert;
@@ -1814,22 +1753,9 @@ static int ab8500_gpadc_acc_detect2_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_acc_detect2_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ab8500_gpadc_acc_detect2_print,
- inode->i_private);
-}
-
-static const struct file_operations ab8500_gpadc_acc_detect2_fops = {
- .open = ab8500_gpadc_acc_detect2_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_acc_detect2);
-static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_aux1_show(struct seq_file *s, void *p)
{
int aux1_raw;
int aux1_convert;
@@ -1846,20 +1772,9 @@ static int ab8500_gpadc_aux1_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_aux1_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_gpadc_aux1_print, inode->i_private);
-}
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_aux1);
-static const struct file_operations ab8500_gpadc_aux1_fops = {
- .open = ab8500_gpadc_aux1_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_aux2_show(struct seq_file *s, void *p)
{
int aux2_raw;
int aux2_convert;
@@ -1876,20 +1791,9 @@ static int ab8500_gpadc_aux2_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_aux2_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_gpadc_aux2_print, inode->i_private);
-}
-
-static const struct file_operations ab8500_gpadc_aux2_fops = {
- .open = ab8500_gpadc_aux2_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_aux2);
-static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_main_bat_v_show(struct seq_file *s, void *p)
{
int main_bat_v_raw;
int main_bat_v_convert;
@@ -1906,22 +1810,9 @@ static int ab8500_gpadc_main_bat_v_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_main_bat_v_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ab8500_gpadc_main_bat_v_print,
- inode->i_private);
-}
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_main_bat_v);
-static const struct file_operations ab8500_gpadc_main_bat_v_fops = {
- .open = ab8500_gpadc_main_bat_v_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_vbus_v_show(struct seq_file *s, void *p)
{
int vbus_v_raw;
int vbus_v_convert;
@@ -1938,20 +1829,9 @@ static int ab8500_gpadc_vbus_v_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_vbus_v_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_gpadc_vbus_v_print, inode->i_private);
-}
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_vbus_v);
-static const struct file_operations ab8500_gpadc_vbus_v_fops = {
- .open = ab8500_gpadc_vbus_v_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_main_charger_c_show(struct seq_file *s, void *p)
{
int main_charger_c_raw;
int main_charger_c_convert;
@@ -1968,22 +1848,9 @@ static int ab8500_gpadc_main_charger_c_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_main_charger_c_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ab8500_gpadc_main_charger_c_print,
- inode->i_private);
-}
-
-static const struct file_operations ab8500_gpadc_main_charger_c_fops = {
- .open = ab8500_gpadc_main_charger_c_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_main_charger_c);
-static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_usb_charger_c_show(struct seq_file *s, void *p)
{
int usb_charger_c_raw;
int usb_charger_c_convert;
@@ -2000,22 +1867,9 @@ static int ab8500_gpadc_usb_charger_c_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_usb_charger_c_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ab8500_gpadc_usb_charger_c_print,
- inode->i_private);
-}
-
-static const struct file_operations ab8500_gpadc_usb_charger_c_fops = {
- .open = ab8500_gpadc_usb_charger_c_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_usb_charger_c);
-static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_bk_bat_v_show(struct seq_file *s, void *p)
{
int bk_bat_v_raw;
int bk_bat_v_convert;
@@ -2032,21 +1886,9 @@ static int ab8500_gpadc_bk_bat_v_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_bk_bat_v_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_gpadc_bk_bat_v_print,
- inode->i_private);
-}
-
-static const struct file_operations ab8500_gpadc_bk_bat_v_fops = {
- .open = ab8500_gpadc_bk_bat_v_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_bk_bat_v);
-static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_die_temp_show(struct seq_file *s, void *p)
{
int die_temp_raw;
int die_temp_convert;
@@ -2063,21 +1905,9 @@ static int ab8500_gpadc_die_temp_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_die_temp_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_gpadc_die_temp_print,
- inode->i_private);
-}
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_die_temp);
-static const struct file_operations ab8500_gpadc_die_temp_fops = {
- .open = ab8500_gpadc_die_temp_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int ab8500_gpadc_usb_id_print(struct seq_file *s, void *p)
+static int ab8500_gpadc_usb_id_show(struct seq_file *s, void *p)
{
int usb_id_raw;
int usb_id_convert;
@@ -2094,20 +1924,9 @@ static int ab8500_gpadc_usb_id_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8500_gpadc_usb_id_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8500_gpadc_usb_id_print, inode->i_private);
-}
-
-static const struct file_operations ab8500_gpadc_usb_id_fops = {
- .open = ab8500_gpadc_usb_id_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8500_gpadc_usb_id);
-static int ab8540_gpadc_xtal_temp_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_xtal_temp_show(struct seq_file *s, void *p)
{
int xtal_temp_raw;
int xtal_temp_convert;
@@ -2124,21 +1943,9 @@ static int ab8540_gpadc_xtal_temp_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8540_gpadc_xtal_temp_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8540_gpadc_xtal_temp_print,
- inode->i_private);
-}
+DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_xtal_temp);
-static const struct file_operations ab8540_gpadc_xtal_temp_fops = {
- .open = ab8540_gpadc_xtal_temp_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int ab8540_gpadc_vbat_true_meas_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_vbat_true_meas_show(struct seq_file *s, void *p)
{
int vbat_true_meas_raw;
int vbat_true_meas_convert;
@@ -2156,22 +1963,9 @@ static int ab8540_gpadc_vbat_true_meas_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8540_gpadc_vbat_true_meas_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ab8540_gpadc_vbat_true_meas_print,
- inode->i_private);
-}
+DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_vbat_true_meas);
-static const struct file_operations ab8540_gpadc_vbat_true_meas_fops = {
- .open = ab8540_gpadc_vbat_true_meas_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int ab8540_gpadc_bat_ctrl_and_ibat_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_bat_ctrl_and_ibat_show(struct seq_file *s, void *p)
{
int bat_ctrl_raw;
int bat_ctrl_convert;
@@ -2197,22 +1991,9 @@ static int ab8540_gpadc_bat_ctrl_and_ibat_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8540_gpadc_bat_ctrl_and_ibat_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ab8540_gpadc_bat_ctrl_and_ibat_print,
- inode->i_private);
-}
-
-static const struct file_operations ab8540_gpadc_bat_ctrl_and_ibat_fops = {
- .open = ab8540_gpadc_bat_ctrl_and_ibat_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_bat_ctrl_and_ibat);
-static int ab8540_gpadc_vbat_meas_and_ibat_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_vbat_meas_and_ibat_show(struct seq_file *s, void *p)
{
int vbat_meas_raw;
int vbat_meas_convert;
@@ -2237,23 +2018,9 @@ static int ab8540_gpadc_vbat_meas_and_ibat_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8540_gpadc_vbat_meas_and_ibat_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ab8540_gpadc_vbat_meas_and_ibat_print,
- inode->i_private);
-}
+DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_vbat_meas_and_ibat);
-static const struct file_operations ab8540_gpadc_vbat_meas_and_ibat_fops = {
- .open = ab8540_gpadc_vbat_meas_and_ibat_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-static int ab8540_gpadc_vbat_true_meas_and_ibat_print(struct seq_file *s,
- void *p)
+static int ab8540_gpadc_vbat_true_meas_and_ibat_show(struct seq_file *s, void *p)
{
int vbat_true_meas_raw;
int vbat_true_meas_convert;
@@ -2279,23 +2046,9 @@ static int ab8540_gpadc_vbat_true_meas_and_ibat_print(struct seq_file *s,
return 0;
}
-static int ab8540_gpadc_vbat_true_meas_and_ibat_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ab8540_gpadc_vbat_true_meas_and_ibat_print,
- inode->i_private);
-}
-
-static const struct file_operations
-ab8540_gpadc_vbat_true_meas_and_ibat_fops = {
- .open = ab8540_gpadc_vbat_true_meas_and_ibat_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_vbat_true_meas_and_ibat);
-static int ab8540_gpadc_bat_temp_and_ibat_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_bat_temp_and_ibat_show(struct seq_file *s, void *p)
{
int bat_temp_raw;
int bat_temp_convert;
@@ -2320,22 +2073,9 @@ static int ab8540_gpadc_bat_temp_and_ibat_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8540_gpadc_bat_temp_and_ibat_open(struct inode *inode,
- struct file *file)
-{
- return single_open(file, ab8540_gpadc_bat_temp_and_ibat_print,
- inode->i_private);
-}
-
-static const struct file_operations ab8540_gpadc_bat_temp_and_ibat_fops = {
- .open = ab8540_gpadc_bat_temp_and_ibat_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_bat_temp_and_ibat);
-static int ab8540_gpadc_otp_cal_print(struct seq_file *s, void *p)
+static int ab8540_gpadc_otp_calib_show(struct seq_file *s, void *p)
{
struct ab8500_gpadc *gpadc;
u16 vmain_l, vmain_h, btemp_l, btemp_h;
@@ -2359,18 +2099,7 @@ static int ab8540_gpadc_otp_cal_print(struct seq_file *s, void *p)
return 0;
}
-static int ab8540_gpadc_otp_cal_open(struct inode *inode, struct file *file)
-{
- return single_open(file, ab8540_gpadc_otp_cal_print, inode->i_private);
-}
-
-static const struct file_operations ab8540_gpadc_otp_calib_fops = {
- .open = ab8540_gpadc_otp_cal_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+DEFINE_SHOW_ATTRIBUTE(ab8540_gpadc_otp_calib);
static int ab8500_gpadc_avg_sample_print(struct seq_file *s, void *p)
{
@@ -2903,14 +2632,6 @@ static const struct file_operations ab8500_val_fops = {
.owner = THIS_MODULE,
};
-static const struct file_operations ab8500_interrupts_fops = {
- .open = ab8500_interrupts_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
static const struct file_operations ab8500_subscribe_fops = {
.open = ab8500_subscribe_unsubscribe_open,
.write = ab8500_subscribe_write,
@@ -2997,7 +2718,7 @@ static int ab8500_debug_probe(struct platform_device *plf)
goto err;
file = debugfs_create_file("all-bank-registers", S_IRUGO, ab8500_dir,
- &plf->dev, &ab8500_registers_fops);
+ &plf->dev, &ab8500_bank_registers_fops);
if (!file)
goto err;
diff --git a/drivers/mfd/atmel-flexcom.c b/drivers/mfd/atmel-flexcom.c
index 064bde9cff5a..f684a93a3340 100644
--- a/drivers/mfd/atmel-flexcom.c
+++ b/drivers/mfd/atmel-flexcom.c
@@ -39,34 +39,43 @@
#define FLEX_MR_OPMODE(opmode) (((opmode) << FLEX_MR_OPMODE_OFFSET) & \
FLEX_MR_OPMODE_MASK)
+struct atmel_flexcom {
+ void __iomem *base;
+ u32 opmode;
+ struct clk *clk;
+};
static int atmel_flexcom_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct clk *clk;
struct resource *res;
- void __iomem *base;
- u32 opmode;
+ struct atmel_flexcom *ddata;
int err;
- err = of_property_read_u32(np, "atmel,flexcom-mode", &opmode);
+ ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, ddata);
+
+ err = of_property_read_u32(np, "atmel,flexcom-mode", &ddata->opmode);
if (err)
return err;
- if (opmode < ATMEL_FLEXCOM_MODE_USART ||
- opmode > ATMEL_FLEXCOM_MODE_TWI)
+ if (ddata->opmode < ATMEL_FLEXCOM_MODE_USART ||
+ ddata->opmode > ATMEL_FLEXCOM_MODE_TWI)
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(base))
- return PTR_ERR(base);
+ ddata->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ddata->base))
+ return PTR_ERR(ddata->base);
- clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
+ ddata->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(ddata->clk))
+ return PTR_ERR(ddata->clk);
- err = clk_prepare_enable(clk);
+ err = clk_prepare_enable(ddata->clk);
if (err)
return err;
@@ -76,9 +85,9 @@ static int atmel_flexcom_probe(struct platform_device *pdev)
* inaccessible and are read as zero. Also the external I/O lines of the
* Flexcom are muxed to reach the selected device.
*/
- writel(FLEX_MR_OPMODE(opmode), base + FLEX_MR);
+ writel(FLEX_MR_OPMODE(ddata->opmode), ddata->base + FLEX_MR);
- clk_disable_unprepare(clk);
+ clk_disable_unprepare(ddata->clk);
return devm_of_platform_populate(&pdev->dev);
}
@@ -89,10 +98,34 @@ static const struct of_device_id atmel_flexcom_of_match[] = {
};
MODULE_DEVICE_TABLE(of, atmel_flexcom_of_match);
+#ifdef CONFIG_PM_SLEEP
+static int atmel_flexcom_resume(struct device *dev)
+{
+ struct atmel_flexcom *ddata = dev_get_drvdata(dev);
+ int err;
+ u32 val;
+
+ err = clk_prepare_enable(ddata->clk);
+ if (err)
+ return err;
+
+ val = FLEX_MR_OPMODE(ddata->opmode),
+ writel(val, ddata->base + FLEX_MR);
+
+ clk_disable_unprepare(ddata->clk);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(atmel_flexcom_pm_ops, NULL,
+ atmel_flexcom_resume);
+
static struct platform_driver atmel_flexcom_driver = {
.probe = atmel_flexcom_probe,
.driver = {
.name = "atmel_flexcom",
+ .pm = &atmel_flexcom_pm_ops,
.of_match_table = atmel_flexcom_of_match,
},
};
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 2468b431bb22..e94c72c2faa2 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -129,6 +129,7 @@ static const struct regmap_range axp288_volatile_ranges[] = {
regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP288_POWER_REASON),
regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL),
regmap_reg_range(AXP288_BC_DET_STAT, AXP288_BC_DET_STAT),
+ regmap_reg_range(AXP20X_CHRG_BAK_CTRL, AXP20X_CHRG_BAK_CTRL),
regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
@@ -878,6 +879,9 @@ static struct mfd_cell axp813_cells[] = {
.resources = axp803_pek_resources,
}, {
.name = "axp20x-regulator",
+ }, {
+ .name = "axp20x-gpio",
+ .of_compatible = "x-powers,axp813-gpio",
}
};
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index b0ca5a4c841e..d61024141e2b 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -40,13 +40,13 @@ static struct cros_ec_platform pd_p = {
};
static const struct mfd_cell ec_cell = {
- .name = "cros-ec-ctl",
+ .name = "cros-ec-dev",
.platform_data = &ec_p,
.pdata_size = sizeof(ec_p),
};
static const struct mfd_cell ec_pd_cell = {
- .name = "cros-ec-ctl",
+ .name = "cros-ec-dev",
.platform_data = &pd_p,
.pdata_size = sizeof(pd_p),
};
diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
new file mode 100644
index 000000000000..e4fafdd96e5e
--- /dev/null
+++ b/drivers/mfd/cros_ec_dev.c
@@ -0,0 +1,552 @@
+/*
+ * cros_ec_dev - expose the Chrome OS Embedded Controller to user-space
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/fs.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include "cros_ec_dev.h"
+
+#define DRV_NAME "cros-ec-dev"
+
+/* Device variables */
+#define CROS_MAX_DEV 128
+static int ec_major;
+
+static const struct attribute_group *cros_ec_groups[] = {
+ &cros_ec_attr_group,
+ &cros_ec_lightbar_attr_group,
+ &cros_ec_vbc_attr_group,
+ NULL,
+};
+
+static struct class cros_class = {
+ .owner = THIS_MODULE,
+ .name = "chromeos",
+ .dev_groups = cros_ec_groups,
+};
+
+/* Basic communication */
+static int ec_get_version(struct cros_ec_dev *ec, char *str, int maxlen)
+{
+ struct ec_response_get_version *resp;
+ static const char * const current_image_name[] = {
+ "unknown", "read-only", "read-write", "invalid",
+ };
+ struct cros_ec_command *msg;
+ int ret;
+
+ msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ msg->version = 0;
+ msg->command = EC_CMD_GET_VERSION + ec->cmd_offset;
+ msg->insize = sizeof(*resp);
+ msg->outsize = 0;
+
+ ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+ if (ret < 0)
+ goto exit;
+
+ if (msg->result != EC_RES_SUCCESS) {
+ snprintf(str, maxlen,
+ "%s\nUnknown EC version: EC returned %d\n",
+ CROS_EC_DEV_VERSION, msg->result);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ resp = (struct ec_response_get_version *)msg->data;
+ if (resp->current_image >= ARRAY_SIZE(current_image_name))
+ resp->current_image = 3; /* invalid */
+
+ snprintf(str, maxlen, "%s\n%s\n%s\n%s\n", CROS_EC_DEV_VERSION,
+ resp->version_string_ro, resp->version_string_rw,
+ current_image_name[resp->current_image]);
+
+ ret = 0;
+exit:
+ kfree(msg);
+ return ret;
+}
+
+static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
+{
+ struct cros_ec_command *msg;
+ int ret;
+
+ if (ec->features[0] == -1U && ec->features[1] == -1U) {
+ /* features bitmap not read yet */
+
+ msg = kmalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ msg->version = 0;
+ msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
+ msg->insize = sizeof(ec->features);
+ msg->outsize = 0;
+
+ ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+ if (ret < 0 || msg->result != EC_RES_SUCCESS) {
+ dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
+ ret, msg->result);
+ memset(ec->features, 0, sizeof(ec->features));
+ }
+
+ memcpy(ec->features, msg->data, sizeof(ec->features));
+
+ dev_dbg(ec->dev, "EC features %08x %08x\n",
+ ec->features[0], ec->features[1]);
+
+ kfree(msg);
+ }
+
+ return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature);
+}
+
+/* Device file ops */
+static int ec_device_open(struct inode *inode, struct file *filp)
+{
+ struct cros_ec_dev *ec = container_of(inode->i_cdev,
+ struct cros_ec_dev, cdev);
+ filp->private_data = ec;
+ nonseekable_open(inode, filp);
+ return 0;
+}
+
+static int ec_device_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static ssize_t ec_device_read(struct file *filp, char __user *buffer,
+ size_t length, loff_t *offset)
+{
+ struct cros_ec_dev *ec = filp->private_data;
+ char msg[sizeof(struct ec_response_get_version) +
+ sizeof(CROS_EC_DEV_VERSION)];
+ size_t count;
+ int ret;
+
+ if (*offset != 0)
+ return 0;
+
+ ret = ec_get_version(ec, msg, sizeof(msg));
+ if (ret)
+ return ret;
+
+ count = min(length, strlen(msg));
+
+ if (copy_to_user(buffer, msg, count))
+ return -EFAULT;
+
+ *offset = count;
+ return count;
+}
+
+/* Ioctls */
+static long ec_device_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg)
+{
+ long ret;
+ struct cros_ec_command u_cmd;
+ struct cros_ec_command *s_cmd;
+
+ if (copy_from_user(&u_cmd, arg, sizeof(u_cmd)))
+ return -EFAULT;
+
+ if ((u_cmd.outsize > EC_MAX_MSG_BYTES) ||
+ (u_cmd.insize > EC_MAX_MSG_BYTES))
+ return -EINVAL;
+
+ s_cmd = kmalloc(sizeof(*s_cmd) + max(u_cmd.outsize, u_cmd.insize),
+ GFP_KERNEL);
+ if (!s_cmd)
+ return -ENOMEM;
+
+ if (copy_from_user(s_cmd, arg, sizeof(*s_cmd) + u_cmd.outsize)) {
+ ret = -EFAULT;
+ goto exit;
+ }
+
+ if (u_cmd.outsize != s_cmd->outsize ||
+ u_cmd.insize != s_cmd->insize) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ s_cmd->command += ec->cmd_offset;
+ ret = cros_ec_cmd_xfer(ec->ec_dev, s_cmd);
+ /* Only copy data to userland if data was received. */
+ if (ret < 0)
+ goto exit;
+
+ if (copy_to_user(arg, s_cmd, sizeof(*s_cmd) + s_cmd->insize))
+ ret = -EFAULT;
+exit:
+ kfree(s_cmd);
+ return ret;
+}
+
+static long ec_device_ioctl_readmem(struct cros_ec_dev *ec, void __user *arg)
+{
+ struct cros_ec_device *ec_dev = ec->ec_dev;
+ struct cros_ec_readmem s_mem = { };
+ long num;
+
+ /* Not every platform supports direct reads */
+ if (!ec_dev->cmd_readmem)
+ return -ENOTTY;
+
+ if (copy_from_user(&s_mem, arg, sizeof(s_mem)))
+ return -EFAULT;
+
+ num = ec_dev->cmd_readmem(ec_dev, s_mem.offset, s_mem.bytes,
+ s_mem.buffer);
+ if (num <= 0)
+ return num;
+
+ if (copy_to_user((void __user *)arg, &s_mem, sizeof(s_mem)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static long ec_device_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct cros_ec_dev *ec = filp->private_data;
+
+ if (_IOC_TYPE(cmd) != CROS_EC_DEV_IOC)
+ return -ENOTTY;
+
+ switch (cmd) {
+ case CROS_EC_DEV_IOCXCMD:
+ return ec_device_ioctl_xcmd(ec, (void __user *)arg);
+ case CROS_EC_DEV_IOCRDMEM:
+ return ec_device_ioctl_readmem(ec, (void __user *)arg);
+ }
+
+ return -ENOTTY;
+}
+
+/* Module initialization */
+static const struct file_operations fops = {
+ .open = ec_device_open,
+ .release = ec_device_release,
+ .read = ec_device_read,
+ .unlocked_ioctl = ec_device_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = ec_device_ioctl,
+#endif
+};
+
+static void __remove(struct device *dev)
+{
+ struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
+ class_dev);
+ kfree(ec);
+}
+
+static void cros_ec_sensors_register(struct cros_ec_dev *ec)
+{
+ /*
+ * Issue a command to get the number of sensor reported.
+ * Build an array of sensors driver and register them all.
+ */
+ int ret, i, id, sensor_num;
+ struct mfd_cell *sensor_cells;
+ struct cros_ec_sensor_platform *sensor_platforms;
+ int sensor_type[MOTIONSENSE_TYPE_MAX];
+ struct ec_params_motion_sense *params;
+ struct ec_response_motion_sense *resp;
+ struct cros_ec_command *msg;
+
+ msg = kzalloc(sizeof(struct cros_ec_command) +
+ max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
+ if (msg == NULL)
+ return;
+
+ msg->version = 2;
+ msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
+ msg->outsize = sizeof(*params);
+ msg->insize = sizeof(*resp);
+
+ params = (struct ec_params_motion_sense *)msg->data;
+ params->cmd = MOTIONSENSE_CMD_DUMP;
+
+ ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+ if (ret < 0 || msg->result != EC_RES_SUCCESS) {
+ dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
+ ret, msg->result);
+ goto error;
+ }
+
+ resp = (struct ec_response_motion_sense *)msg->data;
+ sensor_num = resp->dump.sensor_count;
+ /* Allocate 2 extra sensors in case lid angle or FIFO are needed */
+ sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2),
+ GFP_KERNEL);
+ if (sensor_cells == NULL)
+ goto error;
+
+ sensor_platforms = kzalloc(sizeof(struct cros_ec_sensor_platform) *
+ (sensor_num + 1), GFP_KERNEL);
+ if (sensor_platforms == NULL)
+ goto error_platforms;
+
+ memset(sensor_type, 0, sizeof(sensor_type));
+ id = 0;
+ for (i = 0; i < sensor_num; i++) {
+ params->cmd = MOTIONSENSE_CMD_INFO;
+ params->info.sensor_num = i;
+ ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+ if (ret < 0 || msg->result != EC_RES_SUCCESS) {
+ dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
+ i, ret, msg->result);
+ continue;
+ }
+ switch (resp->info.type) {
+ case MOTIONSENSE_TYPE_ACCEL:
+ sensor_cells[id].name = "cros-ec-accel";
+ break;
+ case MOTIONSENSE_TYPE_BARO:
+ sensor_cells[id].name = "cros-ec-baro";
+ break;
+ case MOTIONSENSE_TYPE_GYRO:
+ sensor_cells[id].name = "cros-ec-gyro";
+ break;
+ case MOTIONSENSE_TYPE_MAG:
+ sensor_cells[id].name = "cros-ec-mag";
+ break;
+ case MOTIONSENSE_TYPE_PROX:
+ sensor_cells[id].name = "cros-ec-prox";
+ break;
+ case MOTIONSENSE_TYPE_LIGHT:
+ sensor_cells[id].name = "cros-ec-light";
+ break;
+ case MOTIONSENSE_TYPE_ACTIVITY:
+ sensor_cells[id].name = "cros-ec-activity";
+ break;
+ default:
+ dev_warn(ec->dev, "unknown type %d\n", resp->info.type);
+ continue;
+ }
+ sensor_platforms[id].sensor_num = i;
+ sensor_cells[id].id = sensor_type[resp->info.type];
+ sensor_cells[id].platform_data = &sensor_platforms[id];
+ sensor_cells[id].pdata_size =
+ sizeof(struct cros_ec_sensor_platform);
+
+ sensor_type[resp->info.type]++;
+ id++;
+ }
+ if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) {
+ sensor_platforms[id].sensor_num = sensor_num;
+
+ sensor_cells[id].name = "cros-ec-angle";
+ sensor_cells[id].id = 0;
+ sensor_cells[id].platform_data = &sensor_platforms[id];
+ sensor_cells[id].pdata_size =
+ sizeof(struct cros_ec_sensor_platform);
+ id++;
+ }
+ if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
+ sensor_cells[id].name = "cros-ec-ring";
+ id++;
+ }
+
+ ret = mfd_add_devices(ec->dev, 0, sensor_cells, id,
+ NULL, 0, NULL);
+ if (ret)
+ dev_err(ec->dev, "failed to add EC sensors\n");
+
+ kfree(sensor_platforms);
+error_platforms:
+ kfree(sensor_cells);
+error:
+ kfree(msg);
+}
+
+static int ec_device_probe(struct platform_device *pdev)
+{
+ int retval = -ENOMEM;
+ struct device *dev = &pdev->dev;
+ struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
+ struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
+
+ if (!ec)
+ return retval;
+
+ dev_set_drvdata(dev, ec);
+ ec->ec_dev = dev_get_drvdata(dev->parent);
+ ec->dev = dev;
+ ec->cmd_offset = ec_platform->cmd_offset;
+ ec->features[0] = -1U; /* Not cached yet */
+ ec->features[1] = -1U; /* Not cached yet */
+ device_initialize(&ec->class_dev);
+ cdev_init(&ec->cdev, &fops);
+
+ /*
+ * Add the class device
+ * Link to the character device for creating the /dev entry
+ * in devtmpfs.
+ */
+ ec->class_dev.devt = MKDEV(ec_major, pdev->id);
+ ec->class_dev.class = &cros_class;
+ ec->class_dev.parent = dev;
+ ec->class_dev.release = __remove;
+
+ retval = dev_set_name(&ec->class_dev, "%s", ec_platform->ec_name);
+ if (retval) {
+ dev_err(dev, "dev_set_name failed => %d\n", retval);
+ goto failed;
+ }
+
+ retval = cdev_device_add(&ec->cdev, &ec->class_dev);
+ if (retval) {
+ dev_err(dev, "cdev_device_add failed => %d\n", retval);
+ goto failed;
+ }
+
+ if (cros_ec_debugfs_init(ec))
+ dev_warn(dev, "failed to create debugfs directory\n");
+
+ /* check whether this EC is a sensor hub. */
+ if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
+ cros_ec_sensors_register(ec);
+
+ /* Take control of the lightbar from the EC. */
+ lb_manual_suspend_ctrl(ec, 1);
+
+ return 0;
+
+failed:
+ put_device(&ec->class_dev);
+ return retval;
+}
+
+static int ec_device_remove(struct platform_device *pdev)
+{
+ struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
+
+ /* Let the EC take over the lightbar again. */
+ lb_manual_suspend_ctrl(ec, 0);
+
+ cros_ec_debugfs_remove(ec);
+
+ cdev_del(&ec->cdev);
+ device_unregister(&ec->class_dev);
+ return 0;
+}
+
+static const struct platform_device_id cros_ec_id[] = {
+ { DRV_NAME, 0 },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(platform, cros_ec_id);
+
+static __maybe_unused int ec_device_suspend(struct device *dev)
+{
+ struct cros_ec_dev *ec = dev_get_drvdata(dev);
+
+ lb_suspend(ec);
+
+ return 0;
+}
+
+static __maybe_unused int ec_device_resume(struct device *dev)
+{
+ struct cros_ec_dev *ec = dev_get_drvdata(dev);
+
+ lb_resume(ec);
+
+ return 0;
+}
+
+static const struct dev_pm_ops cros_ec_dev_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+ .suspend = ec_device_suspend,
+ .resume = ec_device_resume,
+#endif
+};
+
+static struct platform_driver cros_ec_dev_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .pm = &cros_ec_dev_pm_ops,
+ },
+ .probe = ec_device_probe,
+ .remove = ec_device_remove,
+};
+
+static int __init cros_ec_dev_init(void)
+{
+ int ret;
+ dev_t dev = 0;
+
+ ret = class_register(&cros_class);
+ if (ret) {
+ pr_err(CROS_EC_DEV_NAME ": failed to register device class\n");
+ return ret;
+ }
+
+ /* Get a range of minor numbers (starting with 0) to work with */
+ ret = alloc_chrdev_region(&dev, 0, CROS_MAX_DEV, CROS_EC_DEV_NAME);
+ if (ret < 0) {
+ pr_err(CROS_EC_DEV_NAME ": alloc_chrdev_region() failed\n");
+ goto failed_chrdevreg;
+ }
+ ec_major = MAJOR(dev);
+
+ /* Register the driver */
+ ret = platform_driver_register(&cros_ec_dev_driver);
+ if (ret < 0) {
+ pr_warn(CROS_EC_DEV_NAME ": can't register driver: %d\n", ret);
+ goto failed_devreg;
+ }
+ return 0;
+
+failed_devreg:
+ unregister_chrdev_region(MKDEV(ec_major, 0), CROS_MAX_DEV);
+failed_chrdevreg:
+ class_unregister(&cros_class);
+ return ret;
+}
+
+static void __exit cros_ec_dev_exit(void)
+{
+ platform_driver_unregister(&cros_ec_dev_driver);
+ unregister_chrdev(ec_major, CROS_EC_DEV_NAME);
+ class_unregister(&cros_class);
+}
+
+module_init(cros_ec_dev_init);
+module_exit(cros_ec_dev_exit);
+
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_AUTHOR("Bill Richardson <wfrichar@chromium.org>");
+MODULE_DESCRIPTION("Userspace interface to the Chrome OS Embedded Controller");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/cros_ec_dev.h b/drivers/mfd/cros_ec_dev.h
new file mode 100644
index 000000000000..45e9453608c5
--- /dev/null
+++ b/drivers/mfd/cros_ec_dev.h
@@ -0,0 +1,52 @@
+/*
+ * cros_ec_dev - expose the Chrome OS Embedded Controller to userspace
+ *
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CROS_EC_DEV_H_
+#define _CROS_EC_DEV_H_
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#include <linux/mfd/cros_ec.h>
+
+#define CROS_EC_DEV_VERSION "1.0.0"
+
+/*
+ * @offset: within EC_LPC_ADDR_MEMMAP region
+ * @bytes: number of bytes to read. zero means "read a string" (including '\0')
+ * (at most only EC_MEMMAP_SIZE bytes can be read)
+ * @buffer: where to store the result
+ * ioctl returns the number of bytes read, negative on error
+ */
+struct cros_ec_readmem {
+ uint32_t offset;
+ uint32_t bytes;
+ uint8_t buffer[EC_MEMMAP_SIZE];
+};
+
+#define CROS_EC_DEV_IOC 0xEC
+#define CROS_EC_DEV_IOCXCMD _IOWR(CROS_EC_DEV_IOC, 0, struct cros_ec_command)
+#define CROS_EC_DEV_IOCRDMEM _IOWR(CROS_EC_DEV_IOC, 1, struct cros_ec_readmem)
+
+/* Lightbar utilities */
+extern bool ec_has_lightbar(struct cros_ec_dev *ec);
+extern int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable);
+extern int lb_suspend(struct cros_ec_dev *ec);
+extern int lb_resume(struct cros_ec_dev *ec);
+
+#endif /* _CROS_EC_DEV_H_ */
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 59c82cdcf48d..1b52b8557034 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -72,8 +72,7 @@
* struct cros_ec_spi - information about a SPI-connected EC
*
* @spi: SPI device we are connected to
- * @last_transfer_ns: time that we last finished a transfer, or 0 if there
- * if no record
+ * @last_transfer_ns: time that we last finished a transfer.
* @start_of_msg_delay: used to set the delay_usecs on the spi_transfer that
* is sent when we want to turn on CS at the start of a transaction.
* @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that
@@ -379,18 +378,15 @@ static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev,
u8 sum;
u8 rx_byte;
int ret = 0, final_ret;
+ unsigned long delay;
len = cros_ec_prepare_tx(ec_dev, ec_msg);
dev_dbg(ec_dev->dev, "prepared, len=%d\n", len);
/* If it's too soon to do another transaction, wait */
- if (ec_spi->last_transfer_ns) {
- unsigned long delay; /* The delay completed so far */
-
- delay = ktime_get_ns() - ec_spi->last_transfer_ns;
- if (delay < EC_SPI_RECOVERY_TIME_NS)
- ndelay(EC_SPI_RECOVERY_TIME_NS - delay);
- }
+ delay = ktime_get_ns() - ec_spi->last_transfer_ns;
+ if (delay < EC_SPI_RECOVERY_TIME_NS)
+ ndelay(EC_SPI_RECOVERY_TIME_NS - delay);
rx_buf = kzalloc(len, GFP_KERNEL);
if (!rx_buf)
@@ -509,18 +505,15 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
u8 rx_byte;
int sum;
int ret = 0, final_ret;
+ unsigned long delay;
len = cros_ec_prepare_tx(ec_dev, ec_msg);
dev_dbg(ec_dev->dev, "prepared, len=%d\n", len);
/* If it's too soon to do another transaction, wait */
- if (ec_spi->last_transfer_ns) {
- unsigned long delay; /* The delay completed so far */
-
- delay = ktime_get_ns() - ec_spi->last_transfer_ns;
- if (delay < EC_SPI_RECOVERY_TIME_NS)
- ndelay(EC_SPI_RECOVERY_TIME_NS - delay);
- }
+ delay = ktime_get_ns() - ec_spi->last_transfer_ns;
+ if (delay < EC_SPI_RECOVERY_TIME_NS)
+ ndelay(EC_SPI_RECOVERY_TIME_NS - delay);
rx_buf = kzalloc(len, GFP_KERNEL);
if (!rx_buf)
diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c
index 36adf9e8153e..274306d98ac1 100644
--- a/drivers/mfd/intel_soc_pmic_core.c
+++ b/drivers/mfd/intel_soc_pmic_core.c
@@ -16,7 +16,6 @@
* Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
*/
-#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/mfd/core.h>
#include <linux/i2c.h>
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c
index 55d824b3a808..390b27cb2c2e 100644
--- a/drivers/mfd/kempld-core.c
+++ b/drivers/mfd/kempld-core.c
@@ -458,7 +458,7 @@ static int kempld_probe(struct platform_device *pdev)
return -EINVAL;
pld->io_base = devm_ioport_map(dev, ioport->start,
- ioport->end - ioport->start);
+ resource_size(ioport));
if (!pld->io_base)
return -ENOMEM;
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index cf1120abbf52..53dc1a43472c 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -1143,11 +1143,6 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
res->end = res->start + SPIBASE_APL_SZ - 1;
pci_bus_read_config_dword(bus, spi, BCR, &bcr);
- if (!(bcr & BCR_WPD)) {
- bcr |= BCR_WPD;
- pci_bus_write_config_dword(bus, spi, BCR, bcr);
- pci_bus_read_config_dword(bus, spi, BCR, &bcr);
- }
info->writeable = !!(bcr & BCR_WPD);
}
diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c
index dc5caeaaa6a1..da9612dbb222 100644
--- a/drivers/mfd/max77843.c
+++ b/drivers/mfd/max77843.c
@@ -15,7 +15,6 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/init.h>
#include <linux/mfd/core.h>
#include <linux/mfd/max77693-common.h>
#include <linux/mfd/max77843-private.h>
diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
index 3922a93f9f92..663a2398b6b1 100644
--- a/drivers/mfd/palmas.c
+++ b/drivers/mfd/palmas.c
@@ -430,6 +430,7 @@ static void palmas_power_off(void)
{
unsigned int addr;
int ret, slave;
+ u8 powerhold_mask;
struct device_node *np = palmas_dev->dev->of_node;
if (of_property_read_bool(np, "ti,palmas-override-powerhold")) {
@@ -437,8 +438,15 @@ static void palmas_power_off(void)
PALMAS_PRIMARY_SECONDARY_PAD2);
slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE);
+ if (of_device_is_compatible(np, "ti,tps65917"))
+ powerhold_mask =
+ TPS65917_PRIMARY_SECONDARY_PAD2_GPIO_5_MASK;
+ else
+ powerhold_mask =
+ PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_MASK;
+
ret = regmap_update_bits(palmas_dev->regmap[slave], addr,
- PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_MASK, 0);
+ powerhold_mask, 0);
if (ret)
dev_err(palmas_dev->dev,
"Unable to write PRIMARY_SECONDARY_PAD2 %d\n",
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 6155d123a84e..f952dff6765f 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -149,7 +149,7 @@ pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name,
*pdev = platform_device_alloc(name, -1);
if (!*pdev) {
- dev_err(pcf->dev, "Falied to allocate %s\n", name);
+ dev_err(pcf->dev, "Failed to allocate %s\n", name);
return;
}
diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c
new file mode 100644
index 000000000000..5c858e784a89
--- /dev/null
+++ b/drivers/mfd/rave-sp.c
@@ -0,0 +1,710 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Multifunction core driver for Zodiac Inflight Innovations RAVE
+ * Supervisory Processor(SP) MCU that is connected via dedicated UART
+ * port
+ *
+ * Copyright (C) 2017 Zodiac Inflight Innovations
+ */
+
+#include <linux/atomic.h>
+#include <linux/crc-ccitt.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/mfd/rave-sp.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/sched.h>
+#include <linux/serdev.h>
+#include <asm/unaligned.h>
+
+/*
+ * UART protocol using following entities:
+ * - message to MCU => ACK response
+ * - event from MCU => event ACK
+ *
+ * Frame structure:
+ * <STX> <DATA> <CHECKSUM> <ETX>
+ * Where:
+ * - STX - is start of transmission character
+ * - ETX - end of transmission
+ * - DATA - payload
+ * - CHECKSUM - checksum calculated on <DATA>
+ *
+ * If <DATA> or <CHECKSUM> contain one of control characters, then it is
+ * escaped using <DLE> control code. Added <DLE> does not participate in
+ * checksum calculation.
+ */
+#define RAVE_SP_STX 0x02
+#define RAVE_SP_ETX 0x03
+#define RAVE_SP_DLE 0x10
+
+#define RAVE_SP_MAX_DATA_SIZE 64
+#define RAVE_SP_CHECKSUM_SIZE 2 /* Worst case scenario on RDU2 */
+/*
+ * We don't store STX, ETX and unescaped bytes, so Rx is only
+ * DATA + CSUM
+ */
+#define RAVE_SP_RX_BUFFER_SIZE \
+ (RAVE_SP_MAX_DATA_SIZE + RAVE_SP_CHECKSUM_SIZE)
+
+#define RAVE_SP_STX_ETX_SIZE 2
+/*
+ * For Tx we have to have space for everything, STX, EXT and
+ * potentially stuffed DATA + CSUM data + csum
+ */
+#define RAVE_SP_TX_BUFFER_SIZE \
+ (RAVE_SP_STX_ETX_SIZE + 2 * RAVE_SP_RX_BUFFER_SIZE)
+
+#define RAVE_SP_BOOT_SOURCE_GET 0
+#define RAVE_SP_BOOT_SOURCE_SET 1
+
+#define RAVE_SP_RDU2_BOARD_TYPE_RMB 0
+#define RAVE_SP_RDU2_BOARD_TYPE_DEB 1
+
+#define RAVE_SP_BOOT_SOURCE_SD 0
+#define RAVE_SP_BOOT_SOURCE_EMMC 1
+#define RAVE_SP_BOOT_SOURCE_NOR 2
+
+/**
+ * enum rave_sp_deframer_state - Possible state for de-framer
+ *
+ * @RAVE_SP_EXPECT_SOF: Scanning input for start-of-frame marker
+ * @RAVE_SP_EXPECT_DATA: Got start of frame marker, collecting frame
+ * @RAVE_SP_EXPECT_ESCAPED_DATA: Got escape character, collecting escaped byte
+ */
+enum rave_sp_deframer_state {
+ RAVE_SP_EXPECT_SOF,
+ RAVE_SP_EXPECT_DATA,
+ RAVE_SP_EXPECT_ESCAPED_DATA,
+};
+
+/**
+ * struct rave_sp_deframer - Device protocol deframer
+ *
+ * @state: Current state of the deframer
+ * @data: Buffer used to collect deframed data
+ * @length: Number of bytes de-framed so far
+ */
+struct rave_sp_deframer {
+ enum rave_sp_deframer_state state;
+ unsigned char data[RAVE_SP_RX_BUFFER_SIZE];
+ size_t length;
+};
+
+/**
+ * struct rave_sp_reply - Reply as per RAVE device protocol
+ *
+ * @length: Expected reply length
+ * @data: Buffer to store reply payload in
+ * @code: Expected reply code
+ * @ackid: Expected reply ACK ID
+ * @completion: Successful reply reception completion
+ */
+struct rave_sp_reply {
+ size_t length;
+ void *data;
+ u8 code;
+ u8 ackid;
+ struct completion received;
+};
+
+/**
+ * struct rave_sp_checksum - Variant specific checksum implementation details
+ *
+ * @length: Caculated checksum length
+ * @subroutine: Utilized checksum algorithm implementation
+ */
+struct rave_sp_checksum {
+ size_t length;
+ void (*subroutine)(const u8 *, size_t, u8 *);
+};
+
+/**
+ * struct rave_sp_variant_cmds - Variant specific command routines
+ *
+ * @translate: Generic to variant specific command mapping routine
+ *
+ */
+struct rave_sp_variant_cmds {
+ int (*translate)(enum rave_sp_command);
+};
+
+/**
+ * struct rave_sp_variant - RAVE supervisory processor core variant
+ *
+ * @checksum: Variant specific checksum implementation
+ * @cmd: Variant specific command pointer table
+ *
+ */
+struct rave_sp_variant {
+ const struct rave_sp_checksum *checksum;
+ struct rave_sp_variant_cmds cmd;
+};
+
+/**
+ * struct rave_sp - RAVE supervisory processor core
+ *
+ * @serdev: Pointer to underlying serdev
+ * @deframer: Stored state of the protocol deframer
+ * @ackid: ACK ID used in last reply sent to the device
+ * @bus_lock: Lock to serialize access to the device
+ * @reply_lock: Lock protecting @reply
+ * @reply: Pointer to memory to store reply payload
+ *
+ * @variant: Device variant specific information
+ * @event_notifier_list: Input event notification chain
+ *
+ */
+struct rave_sp {
+ struct serdev_device *serdev;
+ struct rave_sp_deframer deframer;
+ atomic_t ackid;
+ struct mutex bus_lock;
+ struct mutex reply_lock;
+ struct rave_sp_reply *reply;
+
+ const struct rave_sp_variant *variant;
+ struct blocking_notifier_head event_notifier_list;
+};
+
+static bool rave_sp_id_is_event(u8 code)
+{
+ return (code & 0xF0) == RAVE_SP_EVNT_BASE;
+}
+
+static void rave_sp_unregister_event_notifier(struct device *dev, void *res)
+{
+ struct rave_sp *sp = dev_get_drvdata(dev->parent);
+ struct notifier_block *nb = *(struct notifier_block **)res;
+ struct blocking_notifier_head *bnh = &sp->event_notifier_list;
+
+ WARN_ON(blocking_notifier_chain_unregister(bnh, nb));
+}
+
+int devm_rave_sp_register_event_notifier(struct device *dev,
+ struct notifier_block *nb)
+{
+ struct rave_sp *sp = dev_get_drvdata(dev->parent);
+ struct notifier_block **rcnb;
+ int ret;
+
+ rcnb = devres_alloc(rave_sp_unregister_event_notifier,
+ sizeof(*rcnb), GFP_KERNEL);
+ if (!rcnb)
+ return -ENOMEM;
+
+ ret = blocking_notifier_chain_register(&sp->event_notifier_list, nb);
+ if (!ret) {
+ *rcnb = nb;
+ devres_add(dev, rcnb);
+ } else {
+ devres_free(rcnb);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(devm_rave_sp_register_event_notifier);
+
+static void csum_8b2c(const u8 *buf, size_t size, u8 *crc)
+{
+ *crc = *buf++;
+ size--;
+
+ while (size--)
+ *crc += *buf++;
+
+ *crc = 1 + ~(*crc);
+}
+
+static void csum_ccitt(const u8 *buf, size_t size, u8 *crc)
+{
+ const u16 calculated = crc_ccitt_false(0xffff, buf, size);
+
+ /*
+ * While the rest of the wire protocol is little-endian,
+ * CCITT-16 CRC in RDU2 device is sent out in big-endian order.
+ */
+ put_unaligned_be16(calculated, crc);
+}
+
+static void *stuff(unsigned char *dest, const unsigned char *src, size_t n)
+{
+ while (n--) {
+ const unsigned char byte = *src++;
+
+ switch (byte) {
+ case RAVE_SP_STX:
+ case RAVE_SP_ETX:
+ case RAVE_SP_DLE:
+ *dest++ = RAVE_SP_DLE;
+ /* FALLTHROUGH */
+ default:
+ *dest++ = byte;
+ }
+ }
+
+ return dest;
+}
+
+static int rave_sp_write(struct rave_sp *sp, const u8 *data, u8 data_size)
+{
+ const size_t checksum_length = sp->variant->checksum->length;
+ unsigned char frame[RAVE_SP_TX_BUFFER_SIZE];
+ unsigned char crc[RAVE_SP_CHECKSUM_SIZE];
+ unsigned char *dest = frame;
+ size_t length;
+
+ if (WARN_ON(checksum_length > sizeof(crc)))
+ return -ENOMEM;
+
+ if (WARN_ON(data_size > sizeof(frame)))
+ return -ENOMEM;
+
+ sp->variant->checksum->subroutine(data, data_size, crc);
+
+ *dest++ = RAVE_SP_STX;
+ dest = stuff(dest, data, data_size);
+ dest = stuff(dest, crc, checksum_length);
+ *dest++ = RAVE_SP_ETX;
+
+ length = dest - frame;
+
+ print_hex_dump(KERN_DEBUG, "rave-sp tx: ", DUMP_PREFIX_NONE,
+ 16, 1, frame, length, false);
+
+ return serdev_device_write(sp->serdev, frame, length, HZ);
+}
+
+static u8 rave_sp_reply_code(u8 command)
+{
+ /*
+ * There isn't a single rule that describes command code ->
+ * ACK code transformation, but, going through various
+ * versions of ICDs, there appear to be three distinct groups
+ * that can be described by simple transformation.
+ */
+ switch (command) {
+ case 0xA0 ... 0xBE:
+ /*
+ * Commands implemented by firmware found in RDU1 and
+ * older devices all seem to obey the following rule
+ */
+ return command + 0x20;
+ case 0xE0 ... 0xEF:
+ /*
+ * Events emitted by all versions of the firmare use
+ * least significant bit to get an ACK code
+ */
+ return command | 0x01;
+ default:
+ /*
+ * Commands implemented by firmware found in RDU2 are
+ * similar to "old" commands, but they use slightly
+ * different offset
+ */
+ return command + 0x40;
+ }
+}
+
+int rave_sp_exec(struct rave_sp *sp,
+ void *__data, size_t data_size,
+ void *reply_data, size_t reply_data_size)
+{
+ struct rave_sp_reply reply = {
+ .data = reply_data,
+ .length = reply_data_size,
+ .received = COMPLETION_INITIALIZER_ONSTACK(reply.received),
+ };
+ unsigned char *data = __data;
+ int command, ret = 0;
+ u8 ackid;
+
+ command = sp->variant->cmd.translate(data[0]);
+ if (command < 0)
+ return command;
+
+ ackid = atomic_inc_return(&sp->ackid);
+ reply.ackid = ackid;
+ reply.code = rave_sp_reply_code((u8)command),
+
+ mutex_lock(&sp->bus_lock);
+
+ mutex_lock(&sp->reply_lock);
+ sp->reply = &reply;
+ mutex_unlock(&sp->reply_lock);
+
+ data[0] = command;
+ data[1] = ackid;
+
+ rave_sp_write(sp, data, data_size);
+
+ if (!wait_for_completion_timeout(&reply.received, HZ)) {
+ dev_err(&sp->serdev->dev, "Command timeout\n");
+ ret = -ETIMEDOUT;
+
+ mutex_lock(&sp->reply_lock);
+ sp->reply = NULL;
+ mutex_unlock(&sp->reply_lock);
+ }
+
+ mutex_unlock(&sp->bus_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rave_sp_exec);
+
+static void rave_sp_receive_event(struct rave_sp *sp,
+ const unsigned char *data, size_t length)
+{
+ u8 cmd[] = {
+ [0] = rave_sp_reply_code(data[0]),
+ [1] = data[1],
+ };
+
+ rave_sp_write(sp, cmd, sizeof(cmd));
+
+ blocking_notifier_call_chain(&sp->event_notifier_list,
+ rave_sp_action_pack(data[0], data[2]),
+ NULL);
+}
+
+static void rave_sp_receive_reply(struct rave_sp *sp,
+ const unsigned char *data, size_t length)
+{
+ struct device *dev = &sp->serdev->dev;
+ struct rave_sp_reply *reply;
+ const size_t payload_length = length - 2;
+
+ mutex_lock(&sp->reply_lock);
+ reply = sp->reply;
+
+ if (reply) {
+ if (reply->code == data[0] && reply->ackid == data[1] &&
+ payload_length >= reply->length) {
+ /*
+ * We are relying on memcpy(dst, src, 0) to be a no-op
+ * when handling commands that have a no-payload reply
+ */
+ memcpy(reply->data, &data[2], reply->length);
+ complete(&reply->received);
+ sp->reply = NULL;
+ } else {
+ dev_err(dev, "Ignoring incorrect reply\n");
+ dev_dbg(dev, "Code: expected = 0x%08x received = 0x%08x\n",
+ reply->code, data[0]);
+ dev_dbg(dev, "ACK ID: expected = 0x%08x received = 0x%08x\n",
+ reply->ackid, data[1]);
+ dev_dbg(dev, "Length: expected = %zu received = %zu\n",
+ reply->length, payload_length);
+ }
+ }
+
+ mutex_unlock(&sp->reply_lock);
+}
+
+static void rave_sp_receive_frame(struct rave_sp *sp,
+ const unsigned char *data,
+ size_t length)
+{
+ const size_t checksum_length = sp->variant->checksum->length;
+ const size_t payload_length = length - checksum_length;
+ const u8 *crc_reported = &data[payload_length];
+ struct device *dev = &sp->serdev->dev;
+ u8 crc_calculated[checksum_length];
+
+ print_hex_dump(KERN_DEBUG, "rave-sp rx: ", DUMP_PREFIX_NONE,
+ 16, 1, data, length, false);
+
+ if (unlikely(length <= checksum_length)) {
+ dev_warn(dev, "Dropping short frame\n");
+ return;
+ }
+
+ sp->variant->checksum->subroutine(data, payload_length,
+ crc_calculated);
+
+ if (memcmp(crc_calculated, crc_reported, checksum_length)) {
+ dev_warn(dev, "Dropping bad frame\n");
+ return;
+ }
+
+ if (rave_sp_id_is_event(data[0]))
+ rave_sp_receive_event(sp, data, length);
+ else
+ rave_sp_receive_reply(sp, data, length);
+}
+
+static int rave_sp_receive_buf(struct serdev_device *serdev,
+ const unsigned char *buf, size_t size)
+{
+ struct device *dev = &serdev->dev;
+ struct rave_sp *sp = dev_get_drvdata(dev);
+ struct rave_sp_deframer *deframer = &sp->deframer;
+ const unsigned char *src = buf;
+ const unsigned char *end = buf + size;
+
+ while (src < end) {
+ const unsigned char byte = *src++;
+
+ switch (deframer->state) {
+ case RAVE_SP_EXPECT_SOF:
+ if (byte == RAVE_SP_STX)
+ deframer->state = RAVE_SP_EXPECT_DATA;
+ break;
+
+ case RAVE_SP_EXPECT_DATA:
+ /*
+ * Treat special byte values first
+ */
+ switch (byte) {
+ case RAVE_SP_ETX:
+ rave_sp_receive_frame(sp,
+ deframer->data,
+ deframer->length);
+ /*
+ * Once we extracted a complete frame
+ * out of a stream, we call it done
+ * and proceed to bailing out while
+ * resetting the framer to initial
+ * state, regardless if we've consumed
+ * all of the stream or not.
+ */
+ goto reset_framer;
+ case RAVE_SP_STX:
+ dev_warn(dev, "Bad frame: STX before ETX\n");
+ /*
+ * If we encounter second "start of
+ * the frame" marker before seeing
+ * corresponding "end of frame", we
+ * reset the framer and ignore both:
+ * frame started by first SOF and
+ * frame started by current SOF.
+ *
+ * NOTE: The above means that only the
+ * frame started by third SOF, sent
+ * after this one will have a chance
+ * to get throught.
+ */
+ goto reset_framer;
+ case RAVE_SP_DLE:
+ deframer->state = RAVE_SP_EXPECT_ESCAPED_DATA;
+ /*
+ * If we encounter escape sequence we
+ * need to skip it and collect the
+ * byte that follows. We do it by
+ * forcing the next iteration of the
+ * encompassing while loop.
+ */
+ continue;
+ }
+ /*
+ * For the rest of the bytes, that are not
+ * speical snoflakes, we do the same thing
+ * that we do to escaped data - collect it in
+ * deframer buffer
+ */
+
+ /* FALLTHROUGH */
+
+ case RAVE_SP_EXPECT_ESCAPED_DATA:
+ deframer->data[deframer->length++] = byte;
+
+ if (deframer->length == sizeof(deframer->data)) {
+ dev_warn(dev, "Bad frame: Too long\n");
+ /*
+ * If the amount of data we've
+ * accumulated for current frame so
+ * far starts to exceed the capacity
+ * of deframer's buffer, there's
+ * nothing else we can do but to
+ * discard that data and start
+ * assemblying a new frame again
+ */
+ goto reset_framer;
+ }
+
+ /*
+ * We've extracted out special byte, now we
+ * can go back to regular data collecting
+ */
+ deframer->state = RAVE_SP_EXPECT_DATA;
+ break;
+ }
+ }
+
+ /*
+ * The only way to get out of the above loop and end up here
+ * is throught consuming all of the supplied data, so here we
+ * report that we processed it all.
+ */
+ return size;
+
+reset_framer:
+ /*
+ * NOTE: A number of codepaths that will drop us here will do
+ * so before consuming all 'size' bytes of the data passed by
+ * serdev layer. We rely on the fact that serdev layer will
+ * re-execute this handler with the remainder of the Rx bytes
+ * once we report actual number of bytes that we processed.
+ */
+ deframer->state = RAVE_SP_EXPECT_SOF;
+ deframer->length = 0;
+
+ return src - buf;
+}
+
+static int rave_sp_rdu1_cmd_translate(enum rave_sp_command command)
+{
+ if (command >= RAVE_SP_CMD_STATUS &&
+ command <= RAVE_SP_CMD_CONTROL_EVENTS)
+ return command;
+
+ return -EINVAL;
+}
+
+static int rave_sp_rdu2_cmd_translate(enum rave_sp_command command)
+{
+ if (command >= RAVE_SP_CMD_GET_FIRMWARE_VERSION &&
+ command <= RAVE_SP_CMD_GET_GPIO_STATE)
+ return command;
+
+ if (command == RAVE_SP_CMD_REQ_COPPER_REV) {
+ /*
+ * As per RDU2 ICD 3.4.47 CMD_GET_COPPER_REV code is
+ * different from that for RDU1 and it is set to 0x28.
+ */
+ return 0x28;
+ }
+
+ return rave_sp_rdu1_cmd_translate(command);
+}
+
+static int rave_sp_default_cmd_translate(enum rave_sp_command command)
+{
+ /*
+ * All of the following command codes were taken from "Table :
+ * Communications Protocol Message Types" in section 3.3
+ * "MESSAGE TYPES" of Rave PIC24 ICD.
+ */
+ switch (command) {
+ case RAVE_SP_CMD_GET_FIRMWARE_VERSION:
+ return 0x11;
+ case RAVE_SP_CMD_GET_BOOTLOADER_VERSION:
+ return 0x12;
+ case RAVE_SP_CMD_BOOT_SOURCE:
+ return 0x14;
+ case RAVE_SP_CMD_SW_WDT:
+ return 0x1C;
+ case RAVE_SP_CMD_RESET:
+ return 0x1E;
+ case RAVE_SP_CMD_RESET_REASON:
+ return 0x1F;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct rave_sp_checksum rave_sp_checksum_8b2c = {
+ .length = 1,
+ .subroutine = csum_8b2c,
+};
+
+static const struct rave_sp_checksum rave_sp_checksum_ccitt = {
+ .length = 2,
+ .subroutine = csum_ccitt,
+};
+
+static const struct rave_sp_variant rave_sp_legacy = {
+ .checksum = &rave_sp_checksum_8b2c,
+ .cmd = {
+ .translate = rave_sp_default_cmd_translate,
+ },
+};
+
+static const struct rave_sp_variant rave_sp_rdu1 = {
+ .checksum = &rave_sp_checksum_8b2c,
+ .cmd = {
+ .translate = rave_sp_rdu1_cmd_translate,
+ },
+};
+
+static const struct rave_sp_variant rave_sp_rdu2 = {
+ .checksum = &rave_sp_checksum_ccitt,
+ .cmd = {
+ .translate = rave_sp_rdu2_cmd_translate,
+ },
+};
+
+static const struct of_device_id rave_sp_dt_ids[] = {
+ { .compatible = "zii,rave-sp-niu", .data = &rave_sp_legacy },
+ { .compatible = "zii,rave-sp-mezz", .data = &rave_sp_legacy },
+ { .compatible = "zii,rave-sp-esb", .data = &rave_sp_legacy },
+ { .compatible = "zii,rave-sp-rdu1", .data = &rave_sp_rdu1 },
+ { .compatible = "zii,rave-sp-rdu2", .data = &rave_sp_rdu2 },
+ { /* sentinel */ }
+};
+
+static const struct serdev_device_ops rave_sp_serdev_device_ops = {
+ .receive_buf = rave_sp_receive_buf,
+ .write_wakeup = serdev_device_write_wakeup,
+};
+
+static int rave_sp_probe(struct serdev_device *serdev)
+{
+ struct device *dev = &serdev->dev;
+ struct rave_sp *sp;
+ u32 baud;
+ int ret;
+
+ if (of_property_read_u32(dev->of_node, "current-speed", &baud)) {
+ dev_err(dev,
+ "'current-speed' is not specified in device node\n");
+ return -EINVAL;
+ }
+
+ sp = devm_kzalloc(dev, sizeof(*sp), GFP_KERNEL);
+ if (!sp)
+ return -ENOMEM;
+
+ sp->serdev = serdev;
+ dev_set_drvdata(dev, sp);
+
+ sp->variant = of_device_get_match_data(dev);
+ if (!sp->variant)
+ return -ENODEV;
+
+ mutex_init(&sp->bus_lock);
+ mutex_init(&sp->reply_lock);
+ BLOCKING_INIT_NOTIFIER_HEAD(&sp->event_notifier_list);
+
+ serdev_device_set_client_ops(serdev, &rave_sp_serdev_device_ops);
+ ret = devm_serdev_device_open(dev, serdev);
+ if (ret)
+ return ret;
+
+ serdev_device_set_baudrate(serdev, baud);
+
+ return devm_of_platform_populate(dev);
+}
+
+MODULE_DEVICE_TABLE(of, rave_sp_dt_ids);
+
+static struct serdev_device_driver rave_sp_drv = {
+ .probe = rave_sp_probe,
+ .driver = {
+ .name = "rave-sp",
+ .of_match_table = rave_sp_dt_ids,
+ },
+};
+module_serdev_device_driver(rave_sp_drv);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>");
+MODULE_AUTHOR("Nikita Yushchenko <nikita.yoush@cogentembedded.com>");
+MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
+MODULE_DESCRIPTION("RAVE SP core driver");
diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c
deleted file mode 100644
index b3ae6592014a..000000000000
--- a/drivers/mfd/rtl8411.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * 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
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- * Wei WANG <wei_wang@realsil.com.cn>
- * Roger Tseng <rogerable@realtek.com>
- */
-
-#include <linux/module.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/mfd/rtsx_pci.h>
-
-#include "rtsx_pcr.h"
-
-static u8 rtl8411_get_ic_version(struct rtsx_pcr *pcr)
-{
- u8 val;
-
- rtsx_pci_read_register(pcr, SYS_VER, &val);
- return val & 0x0F;
-}
-
-static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr)
-{
- u8 val = 0;
-
- rtsx_pci_read_register(pcr, RTL8411B_PACKAGE_MODE, &val);
-
- if (val & 0x2)
- return 1;
- else
- return 0;
-}
-
-static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
-{
- u32 reg1 = 0;
- u8 reg3 = 0;
-
- rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg1);
- pcr_dbg(pcr, "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);
- pcr_dbg(pcr, "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 = 0;
-
- rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
- pcr_dbg(pcr, "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)
-{
- 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)
-{
- rtsx_pci_init_cmd(pcr);
-
- 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)
-{
- return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
-}
-
-static int rtl8411_turn_off_led(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01);
-}
-
-static int rtl8411_enable_auto_blink(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D);
-}
-
-static int rtl8411_disable_auto_blink(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00);
-}
-
-static int rtl8411_card_power_on(struct rtsx_pcr *pcr, int card)
-{
- int err;
-
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
- BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_CTL,
- BPP_LDO_POWB, BPP_LDO_SUSPEND);
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- /* To avoid too large in-rush current */
- udelay(150);
-
- err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
- BPP_POWER_MASK, BPP_POWER_10_PERCENT_ON);
- if (err < 0)
- return err;
-
- udelay(150);
-
- err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
- BPP_POWER_MASK, BPP_POWER_15_PERCENT_ON);
- if (err < 0)
- return err;
-
- udelay(150);
-
- err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
- BPP_POWER_MASK, BPP_POWER_ON);
- if (err < 0)
- return err;
-
- return rtsx_pci_write_register(pcr, LDO_CTL, BPP_LDO_POWB, BPP_LDO_ON);
-}
-
-static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card)
-{
- int err;
-
- err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
- BPP_POWER_MASK, BPP_POWER_OFF);
- if (err < 0)
- return err;
-
- return rtsx_pci_write_register(pcr, LDO_CTL,
- BPP_LDO_POWB, BPP_LDO_SUSPEND);
-}
-
-static int rtl8411_do_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage,
- int bpp_tuned18_shift, int bpp_asic_1v8)
-{
- u8 mask, val;
- int err;
-
- mask = (BPP_REG_TUNED18 << bpp_tuned18_shift) | BPP_PAD_MASK;
- if (voltage == OUTPUT_3V3) {
- err = rtsx_pci_write_register(pcr,
- SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
- if (err < 0)
- return err;
- val = (BPP_ASIC_3V3 << bpp_tuned18_shift) | BPP_PAD_3V3;
- } else if (voltage == OUTPUT_1V8) {
- err = rtsx_pci_write_register(pcr,
- SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
- if (err < 0)
- return err;
- val = (bpp_asic_1v8 << bpp_tuned18_shift) | BPP_PAD_1V8;
- } else {
- return -EINVAL;
- }
-
- return rtsx_pci_write_register(pcr, LDO_CTL, mask, val);
-}
-
-static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
- return rtl8411_do_switch_output_voltage(pcr, voltage,
- BPP_TUNED18_SHIFT_8411, BPP_ASIC_1V8);
-}
-
-static int rtl8402_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
- return rtl8411_do_switch_output_voltage(pcr, voltage,
- BPP_TUNED18_SHIFT_8402, BPP_ASIC_2V0);
-}
-
-static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
-{
- unsigned int card_exist;
-
- card_exist = rtsx_pci_readl(pcr, RTSX_BIPR);
- card_exist &= CARD_EXIST;
- if (!card_exist) {
- /* Enable card CD */
- rtsx_pci_write_register(pcr, CD_PAD_CTL,
- CD_DISABLE_MASK, CD_ENABLE);
- /* Enable card interrupt */
- rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x00);
- return 0;
- }
-
- if (hweight32(card_exist) > 1) {
- rtsx_pci_write_register(pcr, CARD_PWR_CTL,
- BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON);
- msleep(100);
-
- card_exist = rtsx_pci_readl(pcr, RTSX_BIPR);
- if (card_exist & MS_EXIST)
- card_exist = MS_EXIST;
- else if (card_exist & SD_EXIST)
- card_exist = SD_EXIST;
- else
- card_exist = 0;
-
- rtsx_pci_write_register(pcr, CARD_PWR_CTL,
- BPP_POWER_MASK, BPP_POWER_OFF);
-
- pcr_dbg(pcr, "After CD deglitch, card_exist = 0x%x\n",
- card_exist);
- }
-
- if (card_exist & MS_EXIST) {
- /* Disable SD interrupt */
- rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x40);
- rtsx_pci_write_register(pcr, CD_PAD_CTL,
- CD_DISABLE_MASK, MS_CD_EN_ONLY);
- } else if (card_exist & SD_EXIST) {
- /* Disable MS interrupt */
- rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x80);
- rtsx_pci_write_register(pcr, CD_PAD_CTL,
- CD_DISABLE_MASK, SD_CD_EN_ONLY);
- }
-
- return card_exist;
-}
-
-static int rtl8411_conv_clk_and_div_n(int input, int dir)
-{
- int output;
-
- if (dir == CLK_TO_DIV_N)
- output = input * 4 / 5 - 2;
- else
- output = (input + 2) * 5 / 4;
-
- return output;
-}
-
-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,
- .turn_off_led = rtl8411_turn_off_led,
- .enable_auto_blink = rtl8411_enable_auto_blink,
- .disable_auto_blink = rtl8411_disable_auto_blink,
- .card_power_on = rtl8411_card_power_on,
- .card_power_off = rtl8411_card_power_off,
- .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 rtl8402_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,
- .turn_off_led = rtl8411_turn_off_led,
- .enable_auto_blink = rtl8411_enable_auto_blink,
- .disable_auto_blink = rtl8411_disable_auto_blink,
- .card_power_on = rtl8411_card_power_on,
- .card_power_off = rtl8411_card_power_off,
- .switch_output_voltage = rtl8402_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,
- .turn_off_led = rtl8411_turn_off_led,
- .enable_auto_blink = rtl8411_enable_auto_blink,
- .disable_auto_blink = rtl8411_disable_auto_blink,
- .card_power_on = rtl8411_card_power_on,
- .card_power_off = rtl8411_card_power_off,
- .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:
- * SD_DAT[3:0] ==> pull up
- * SD_CD ==> pull up
- * SD_WP ==> pull up
- * SD_CMD ==> pull up
- * SD_CLK ==> pull down
- */
-static const u32 rtl8411_sd_pull_ctl_enable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0xA9),
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x09),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
- 0,
-};
-
-/* SD Pull Control Disable:
- * SD_DAT[3:0] ==> pull down
- * SD_CD ==> pull up
- * SD_WP ==> pull down
- * SD_CMD ==> pull down
- * SD_CLK ==> pull down
- */
-static const u32 rtl8411_sd_pull_ctl_disable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
- 0,
-};
-
-/* MS Pull Control Enable:
- * MS CD ==> pull up
- * others ==> pull down
- */
-static const u32 rtl8411_ms_pull_ctl_enable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05),
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
- 0,
-};
-
-/* MS Pull Control Disable:
- * MS CD ==> pull up
- * others ==> pull down
- */
-static const u32 rtl8411_ms_pull_ctl_disable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
- 0,
-};
-
-static const u32 rtl8411b_qfn64_sd_pull_ctl_enable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0x09 | 0xD0),
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
- 0,
-};
-
-static const u32 rtl8411b_qfn48_sd_pull_ctl_enable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0x69 | 0x90),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x08 | 0x11),
- 0,
-};
-
-static const u32 rtl8411b_qfn64_sd_pull_ctl_disable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
- 0,
-};
-
-static const u32 rtl8411b_qfn48_sd_pull_ctl_disable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
- 0,
-};
-
-static const u32 rtl8411b_qfn64_ms_pull_ctl_enable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05 | 0x50),
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
- 0,
-};
-
-static const u32 rtl8411b_qfn48_ms_pull_ctl_enable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
- 0,
-};
-
-static const u32 rtl8411b_qfn64_ms_pull_ctl_disable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
- 0,
-};
-
-static const u32 rtl8411b_qfn48_ms_pull_ctl_disable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
- 0,
-};
-
-static void rtl8411_init_common_params(struct rtsx_pcr *pcr)
-{
- pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
- pcr->num_slots = 2;
- 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);
-}
-
-void rtl8411_init_params(struct rtsx_pcr *pcr)
-{
- rtl8411_init_common_params(pcr);
- pcr->ops = &rtl8411_pcr_ops;
- set_pull_ctrl_tables(pcr, rtl8411);
-}
-
-void rtl8411b_init_params(struct rtsx_pcr *pcr)
-{
- rtl8411_init_common_params(pcr);
- pcr->ops = &rtl8411b_pcr_ops;
- if (rtl8411b_is_qfn48(pcr))
- set_pull_ctrl_tables(pcr, rtl8411b_qfn48);
- else
- set_pull_ctrl_tables(pcr, rtl8411b_qfn64);
-}
-
-void rtl8402_init_params(struct rtsx_pcr *pcr)
-{
- rtl8411_init_common_params(pcr);
- pcr->ops = &rtl8402_pcr_ops;
- set_pull_ctrl_tables(pcr, rtl8411);
-}
diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c
deleted file mode 100644
index b95beecf767f..000000000000
--- a/drivers/mfd/rts5209.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * 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
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- * Wei WANG <wei_wang@realsil.com.cn>
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/mfd/rtsx_pci.h>
-
-#include "rtsx_pcr.h"
-
-static u8 rts5209_get_ic_version(struct rtsx_pcr *pcr)
-{
- u8 val;
-
- val = rtsx_pci_readb(pcr, 0x1C);
- return val & 0x0F;
-}
-
-static void rts5209_fetch_vendor_settings(struct rtsx_pcr *pcr)
-{
- u32 reg;
-
- rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
- pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
-
- 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);
- pcr_dbg(pcr, "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)
-{
- rtsx_pci_init_cmd(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);
-}
-
-static int rts5209_optimize_phy(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_phy_register(pcr, 0x00, 0xB966);
-}
-
-static int rts5209_turn_on_led(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
-}
-
-static int rts5209_turn_off_led(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01);
-}
-
-static int rts5209_enable_auto_blink(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D);
-}
-
-static int rts5209_disable_auto_blink(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00);
-}
-
-static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card)
-{
- int err;
- u8 pwr_mask, partial_pwr_on, pwr_on;
-
- pwr_mask = SD_POWER_MASK;
- partial_pwr_on = SD_PARTIAL_POWER_ON;
- pwr_on = SD_POWER_ON;
-
- 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;
- }
-
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
- pwr_mask, partial_pwr_on);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, 0x04);
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- /* To avoid too large in-rush current */
- udelay(150);
-
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, 0x00);
- return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
-{
- u8 pwr_mask, pwr_off;
-
- pwr_mask = SD_POWER_MASK;
- pwr_off = SD_POWER_OFF;
-
- if ((pcr->flags & PCR_MS_PMOS) && (card == RTSX_MS_CARD)) {
- pwr_mask = MS_POWER_MASK;
- pwr_off = MS_POWER_OFF;
- }
-
- rtsx_pci_init_cmd(pcr);
- 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);
- return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
- int err;
-
- if (voltage == OUTPUT_3V3) {
- err = rtsx_pci_write_register(pcr,
- SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
- if (err < 0)
- return err;
- err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
- if (err < 0)
- return err;
- } else if (voltage == OUTPUT_1V8) {
- err = rtsx_pci_write_register(pcr,
- SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
- if (err < 0)
- return err;
- err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
- if (err < 0)
- return err;
- } else {
- return -EINVAL;
- }
-
- return 0;
-}
-
-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,
- .turn_off_led = rts5209_turn_off_led,
- .enable_auto_blink = rts5209_enable_auto_blink,
- .disable_auto_blink = rts5209_disable_auto_blink,
- .card_power_on = rts5209_card_power_on,
- .card_power_off = rts5209_card_power_off,
- .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:
- * SD_DAT[3:0] ==> pull up
- * SD_CD ==> pull up
- * SD_WP ==> pull up
- * SD_CMD ==> pull up
- * SD_CLK ==> pull down
- */
-static const u32 rts5209_sd_pull_ctl_enable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
- 0,
-};
-
-/* SD Pull Control Disable:
- * SD_DAT[3:0] ==> pull down
- * SD_CD ==> pull up
- * SD_WP ==> pull down
- * SD_CMD ==> pull down
- * SD_CLK ==> pull down
- */
-static const u32 rts5209_sd_pull_ctl_disable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL1, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
- 0,
-};
-
-/* MS Pull Control Enable:
- * MS CD ==> pull up
- * others ==> pull down
- */
-static const u32 rts5209_ms_pull_ctl_enable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
- 0,
-};
-
-/* MS Pull Control Disable:
- * MS CD ==> pull up
- * others ==> pull down
- */
-static const u32 rts5209_ms_pull_ctl_disable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
- 0,
-};
-
-void rts5209_init_params(struct rtsx_pcr *pcr)
-{
- pcr->extra_caps = EXTRA_CAPS_SD_SDR50 |
- EXTRA_CAPS_SD_SDR104 | EXTRA_CAPS_MMC_8BIT;
- pcr->num_slots = 2;
- pcr->ops = &rts5209_pcr_ops;
-
- 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;
- pcr->sd_pull_ctl_disable_tbl = rts5209_sd_pull_ctl_disable_tbl;
- pcr->ms_pull_ctl_enable_tbl = rts5209_ms_pull_ctl_enable_tbl;
- pcr->ms_pull_ctl_disable_tbl = rts5209_ms_pull_ctl_disable_tbl;
-}
diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c
deleted file mode 100644
index ff296a4bf3d2..000000000000
--- a/drivers/mfd/rts5227.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * 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
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- * Wei WANG <wei_wang@realsil.com.cn>
- * Roger Tseng <rogerable@realtek.com>
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/mfd/rtsx_pci.h>
-
-#include "rtsx_pcr.h"
-
-static u8 rts5227_get_ic_version(struct rtsx_pcr *pcr)
-{
- u8 val;
-
- rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
- return val & 0x0F;
-}
-
-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);
- pcr_dbg(pcr, "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);
- pcr_dbg(pcr, "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, pcr->reg_pm_ctrl3, 0x10, 0x10);
-
- rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
-}
-
-static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
-{
- u16 cap;
-
- 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);
- /* Configure LTR */
- pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &cap);
- if (cap & PCI_EXP_DEVCTL2_LTR_EN)
- 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 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, PETXCFG, 0xB8, 0xB8);
- else
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0x88);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, pcr->reg_pm_ctrl3, 0x10, 0x00);
-
- return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5227_optimize_phy(struct rtsx_pcr *pcr)
-{
- int err;
-
- err = rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
- if (err < 0)
- return err;
-
- /* Optimize RX sensitivity */
- return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42);
-}
-
-static int rts5227_turn_on_led(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
-}
-
-static int rts5227_turn_off_led(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
-}
-
-static int rts5227_enable_auto_blink(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
-}
-
-static int rts5227_disable_auto_blink(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
-}
-
-static int rts5227_card_power_on(struct rtsx_pcr *pcr, int card)
-{
- int err;
-
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
- SD_POWER_MASK, SD_PARTIAL_POWER_ON);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, 0x02);
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- /* To avoid too large in-rush current */
- udelay(150);
-
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
- SD_POWER_MASK, SD_POWER_ON);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, 0x06);
- return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card)
-{
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
- 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);
- return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
- int err;
-
- if (voltage == OUTPUT_3V3) {
- err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
- if (err < 0)
- return err;
- } else if (voltage == OUTPUT_1V8) {
- err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02);
- if (err < 0)
- return err;
- err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C80 | 0x24);
- if (err < 0)
- return err;
- } else {
- return -EINVAL;
- }
-
- /* set pad drive */
- rtsx_pci_init_cmd(pcr);
- 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,
- .turn_off_led = rts5227_turn_off_led,
- .enable_auto_blink = rts5227_enable_auto_blink,
- .disable_auto_blink = rts5227_disable_auto_blink,
- .card_power_on = rts5227_card_power_on,
- .card_power_off = rts5227_card_power_off,
- .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:
- * SD_DAT[3:0] ==> pull up
- * SD_CD ==> pull up
- * SD_WP ==> pull up
- * SD_CMD ==> pull up
- * SD_CLK ==> pull down
- */
-static const u32 rts5227_sd_pull_ctl_enable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
- 0,
-};
-
-/* SD Pull Control Disable:
- * SD_DAT[3:0] ==> pull down
- * SD_CD ==> pull up
- * SD_WP ==> pull down
- * SD_CMD ==> pull down
- * SD_CLK ==> pull down
- */
-static const u32 rts5227_sd_pull_ctl_disable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
- 0,
-};
-
-/* MS Pull Control Enable:
- * MS CD ==> pull up
- * others ==> pull down
- */
-static const u32 rts5227_ms_pull_ctl_enable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
- 0,
-};
-
-/* MS Pull Control Disable:
- * MS CD ==> pull up
- * others ==> pull down
- */
-static const u32 rts5227_ms_pull_ctl_disable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
- 0,
-};
-
-void rts5227_init_params(struct rtsx_pcr *pcr)
-{
- pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
- 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->ic_version = rts5227_get_ic_version(pcr);
- 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;
- pcr->ms_pull_ctl_disable_tbl = rts5227_ms_pull_ctl_disable_tbl;
-
- pcr->reg_pm_ctrl3 = PM_CTRL3;
-}
-
-static int rts522a_optimize_phy(struct rtsx_pcr *pcr)
-{
- int err;
-
- err = rtsx_pci_write_register(pcr, RTS522A_PM_CTRL3, D3_DELINK_MODE_EN,
- 0x00);
- if (err < 0)
- return err;
-
- if (is_version(pcr, 0x522A, IC_VER_A)) {
- err = rtsx_pci_write_phy_register(pcr, PHY_RCR2,
- PHY_RCR2_INIT_27S);
- if (err)
- return err;
-
- rtsx_pci_write_phy_register(pcr, PHY_RCR1, PHY_RCR1_INIT_27S);
- rtsx_pci_write_phy_register(pcr, PHY_FLD0, PHY_FLD0_INIT_27S);
- rtsx_pci_write_phy_register(pcr, PHY_FLD3, PHY_FLD3_INIT_27S);
- rtsx_pci_write_phy_register(pcr, PHY_FLD4, PHY_FLD4_INIT_27S);
- }
-
- return 0;
-}
-
-static int rts522a_extra_init_hw(struct rtsx_pcr *pcr)
-{
- rts5227_extra_init_hw(pcr);
-
- rtsx_pci_write_register(pcr, FUNC_FORCE_CTL, FUNC_FORCE_UPME_XMT_DBG,
- FUNC_FORCE_UPME_XMT_DBG);
- rtsx_pci_write_register(pcr, PCLK_CTL, 0x04, 0x04);
- rtsx_pci_write_register(pcr, PM_EVENT_DEBUG, PME_DEBUG_0, PME_DEBUG_0);
- rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 0xFF, 0x11);
-
- return 0;
-}
-
-/* rts522a operations mainly derived from rts5227, except phy/hw init setting.
- */
-static const struct pcr_ops rts522a_pcr_ops = {
- .fetch_vendor_settings = rts5227_fetch_vendor_settings,
- .extra_init_hw = rts522a_extra_init_hw,
- .optimize_phy = rts522a_optimize_phy,
- .turn_on_led = rts5227_turn_on_led,
- .turn_off_led = rts5227_turn_off_led,
- .enable_auto_blink = rts5227_enable_auto_blink,
- .disable_auto_blink = rts5227_disable_auto_blink,
- .card_power_on = rts5227_card_power_on,
- .card_power_off = rts5227_card_power_off,
- .switch_output_voltage = rts5227_switch_output_voltage,
- .cd_deglitch = NULL,
- .conv_clk_and_div_n = NULL,
- .force_power_down = rts5227_force_power_down,
-};
-
-void rts522a_init_params(struct rtsx_pcr *pcr)
-{
- rts5227_init_params(pcr);
-
- pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3;
-}
diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c
deleted file mode 100644
index 9ed9dc84eac8..000000000000
--- a/drivers/mfd/rts5229.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * 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
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- * Wei WANG <wei_wang@realsil.com.cn>
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/mfd/rtsx_pci.h>
-
-#include "rtsx_pcr.h"
-
-static u8 rts5229_get_ic_version(struct rtsx_pcr *pcr)
-{
- u8 val;
-
- rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
- 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);
- pcr_dbg(pcr, "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);
- pcr_dbg(pcr, "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);
-}
-
-static int rts5229_optimize_phy(struct rtsx_pcr *pcr)
-{
- /* Optimize RX sensitivity */
- return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42);
-}
-
-static int rts5229_turn_on_led(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
-}
-
-static int rts5229_turn_off_led(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
-}
-
-static int rts5229_enable_auto_blink(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
-}
-
-static int rts5229_disable_auto_blink(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
-}
-
-static int rts5229_card_power_on(struct rtsx_pcr *pcr, int card)
-{
- int err;
-
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
- SD_POWER_MASK, SD_PARTIAL_POWER_ON);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, 0x02);
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- /* To avoid too large in-rush current */
- udelay(150);
-
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
- SD_POWER_MASK, SD_POWER_ON);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, 0x06);
- return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
-{
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
- 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);
- return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
- int err;
-
- if (voltage == OUTPUT_3V3) {
- err = rtsx_pci_write_register(pcr,
- SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
- if (err < 0)
- return err;
- err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
- if (err < 0)
- return err;
- } else if (voltage == OUTPUT_1V8) {
- err = rtsx_pci_write_register(pcr,
- SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
- if (err < 0)
- return err;
- err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
- if (err < 0)
- return err;
- } else {
- return -EINVAL;
- }
-
- return 0;
-}
-
-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,
- .turn_off_led = rts5229_turn_off_led,
- .enable_auto_blink = rts5229_enable_auto_blink,
- .disable_auto_blink = rts5229_disable_auto_blink,
- .card_power_on = rts5229_card_power_on,
- .card_power_off = rts5229_card_power_off,
- .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:
- * SD_DAT[3:0] ==> pull up
- * SD_CD ==> pull up
- * SD_WP ==> pull up
- * SD_CMD ==> pull up
- * SD_CLK ==> pull down
- */
-static const u32 rts5229_sd_pull_ctl_enable_tbl1[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
- 0,
-};
-
-/* For RTS5229 version C */
-static const u32 rts5229_sd_pull_ctl_enable_tbl2[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD9),
- 0,
-};
-
-/* SD Pull Control Disable:
- * SD_DAT[3:0] ==> pull down
- * SD_CD ==> pull up
- * SD_WP ==> pull down
- * SD_CMD ==> pull down
- * SD_CLK ==> pull down
- */
-static const u32 rts5229_sd_pull_ctl_disable_tbl1[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
- 0,
-};
-
-/* For RTS5229 version C */
-static const u32 rts5229_sd_pull_ctl_disable_tbl2[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE5),
- 0,
-};
-
-/* MS Pull Control Enable:
- * MS CD ==> pull up
- * others ==> pull down
- */
-static const u32 rts5229_ms_pull_ctl_enable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
- 0,
-};
-
-/* MS Pull Control Disable:
- * MS CD ==> pull up
- * others ==> pull down
- */
-static const u32 rts5229_ms_pull_ctl_disable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
- 0,
-};
-
-void rts5229_init_params(struct rtsx_pcr *pcr)
-{
- pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
- 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;
- pcr->sd_pull_ctl_disable_tbl = rts5229_sd_pull_ctl_disable_tbl2;
- } else {
- pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl1;
- pcr->sd_pull_ctl_disable_tbl = rts5229_sd_pull_ctl_disable_tbl1;
- }
- pcr->ms_pull_ctl_enable_tbl = rts5229_ms_pull_ctl_enable_tbl;
- pcr->ms_pull_ctl_disable_tbl = rts5229_ms_pull_ctl_disable_tbl;
-}
diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c
deleted file mode 100644
index 7fcf37ba922c..000000000000
--- a/drivers/mfd/rts5249.c
+++ /dev/null
@@ -1,741 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * 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
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- * Wei WANG <wei_wang@realsil.com.cn>
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/mfd/rtsx_pci.h>
-
-#include "rtsx_pcr.h"
-
-static u8 rts5249_get_ic_version(struct rtsx_pcr *pcr)
-{
- u8 val;
-
- rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
- return val & 0x0F;
-}
-
-static void rts5249_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
-{
- u8 driving_3v3[4][3] = {
- {0x11, 0x11, 0x18},
- {0x55, 0x55, 0x5C},
- {0xFF, 0xFF, 0xFF},
- {0x96, 0x96, 0x96},
- };
- u8 driving_1v8[4][3] = {
- {0xC4, 0xC4, 0xC4},
- {0x3C, 0x3C, 0x3C},
- {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 rtsx_base_fetch_vendor_settings(struct rtsx_pcr *pcr)
-{
- u32 reg;
-
- rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
- pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
-
- if (!rtsx_vendor_setting_valid(reg)) {
- pcr_dbg(pcr, "skip fetch vendor setting\n");
- 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);
- pcr_dbg(pcr, "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 rtsx_base_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, pcr->reg_pm_ctrl3,
- D3_DELINK_MODE_EN, D3_DELINK_MODE_EN);
-
- rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
-}
-
-static void rts5249_init_from_cfg(struct rtsx_pcr *pcr)
-{
- struct rtsx_cr_option *option = &(pcr->option);
- u32 lval;
-
- if (CHK_PCI_PID(pcr, PID_524A))
- rtsx_pci_read_config_dword(pcr,
- PCR_ASPM_SETTING_REG1, &lval);
- else
- rtsx_pci_read_config_dword(pcr,
- PCR_ASPM_SETTING_REG2, &lval);
-
- if (lval & ASPM_L1_1_EN_MASK)
- rtsx_set_dev_flag(pcr, ASPM_L1_1_EN);
-
- if (lval & ASPM_L1_2_EN_MASK)
- rtsx_set_dev_flag(pcr, ASPM_L1_2_EN);
-
- if (lval & PM_L1_1_EN_MASK)
- rtsx_set_dev_flag(pcr, PM_L1_1_EN);
-
- if (lval & PM_L1_2_EN_MASK)
- rtsx_set_dev_flag(pcr, PM_L1_2_EN);
-
- if (option->ltr_en) {
- u16 val;
-
- pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &val);
- if (val & PCI_EXP_DEVCTL2_LTR_EN) {
- option->ltr_enabled = true;
- option->ltr_active = true;
- rtsx_set_ltr_latency(pcr, option->ltr_active_latency);
- } else {
- option->ltr_enabled = false;
- }
- }
-}
-
-static int rts5249_init_from_hw(struct rtsx_pcr *pcr)
-{
- struct rtsx_cr_option *option = &(pcr->option);
-
- if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN
- | PM_L1_1_EN | PM_L1_2_EN))
- option->force_clkreq_0 = false;
- else
- option->force_clkreq_0 = true;
-
- return 0;
-}
-
-static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
-{
- struct rtsx_cr_option *option = &(pcr->option);
-
- rts5249_init_from_cfg(pcr);
- rts5249_init_from_hw(pcr);
-
- rtsx_pci_init_cmd(pcr);
-
- /* Rest L1SUB Config */
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, L1SUB_CONFIG3, 0xFF, 0x00);
- /* 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);
- /* Configure driving */
- rts5249_fill_driving(pcr, OUTPUT_3V3);
- if (pcr->flags & PCR_REVERSE_SOCKET)
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0xB0);
- else
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0x80);
-
- /*
- * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
- * to drive low, and we forcibly request clock.
- */
- if (option->force_clkreq_0)
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,
- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
- else
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,
- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
-
- return rtsx_pci_send_cmd(pcr, CMD_TIMEOUT_DEF);
-}
-
-static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
-{
- int err;
-
- err = rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
- if (err < 0)
- return err;
-
- err = rtsx_pci_write_phy_register(pcr, PHY_REV,
- PHY_REV_RESV | PHY_REV_RXIDLE_LATCHED |
- PHY_REV_P1_EN | PHY_REV_RXIDLE_EN |
- PHY_REV_CLKREQ_TX_EN | PHY_REV_RX_PWST |
- PHY_REV_CLKREQ_DT_1_0 | PHY_REV_STOP_CLKRD |
- PHY_REV_STOP_CLKWR);
- if (err < 0)
- return err;
-
- msleep(1);
-
- err = rtsx_pci_write_phy_register(pcr, PHY_BPCR,
- PHY_BPCR_IBRXSEL | PHY_BPCR_IBTXSEL |
- PHY_BPCR_IB_FILTER | PHY_BPCR_CMIRROR_EN);
- if (err < 0)
- return err;
-
- err = rtsx_pci_write_phy_register(pcr, PHY_PCR,
- PHY_PCR_FORCE_CODE | PHY_PCR_OOBS_CALI_50 |
- PHY_PCR_OOBS_VCM_08 | PHY_PCR_OOBS_SEN_90 |
- PHY_PCR_RSSI_EN | PHY_PCR_RX10K);
- if (err < 0)
- return err;
-
- err = rtsx_pci_write_phy_register(pcr, PHY_RCR2,
- PHY_RCR2_EMPHASE_EN | PHY_RCR2_NADJR |
- PHY_RCR2_CDR_SR_2 | PHY_RCR2_FREQSEL_12 |
- PHY_RCR2_CDR_SC_12P | PHY_RCR2_CALIB_LATE);
- if (err < 0)
- return err;
-
- err = rtsx_pci_write_phy_register(pcr, PHY_FLD4,
- PHY_FLD4_FLDEN_SEL | PHY_FLD4_REQ_REF |
- PHY_FLD4_RXAMP_OFF | PHY_FLD4_REQ_ADDA |
- PHY_FLD4_BER_COUNT | PHY_FLD4_BER_TIMER |
- PHY_FLD4_BER_CHK_EN);
- if (err < 0)
- return err;
- err = rtsx_pci_write_phy_register(pcr, PHY_RDR,
- PHY_RDR_RXDSEL_1_9 | PHY_SSC_AUTO_PWD);
- if (err < 0)
- return err;
- err = rtsx_pci_write_phy_register(pcr, PHY_RCR1,
- PHY_RCR1_ADP_TIME_4 | PHY_RCR1_VCO_COARSE);
- if (err < 0)
- return err;
- err = rtsx_pci_write_phy_register(pcr, PHY_FLD3,
- PHY_FLD3_TIMER_4 | PHY_FLD3_TIMER_6 |
- PHY_FLD3_RXDELINK);
- if (err < 0)
- return err;
-
- return rtsx_pci_write_phy_register(pcr, PHY_TUNE,
- PHY_TUNE_TUNEREF_1_0 | PHY_TUNE_VBGSEL_1252 |
- PHY_TUNE_SDBUS_33 | PHY_TUNE_TUNED18 |
- PHY_TUNE_TUNED12 | PHY_TUNE_TUNEA12);
-}
-
-static int rtsx_base_turn_on_led(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
-}
-
-static int rtsx_base_turn_off_led(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
-}
-
-static int rtsx_base_enable_auto_blink(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
-}
-
-static int rtsx_base_disable_auto_blink(struct rtsx_pcr *pcr)
-{
- return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
-}
-
-static int rtsx_base_card_power_on(struct rtsx_pcr *pcr, int card)
-{
- int err;
-
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
- SD_POWER_MASK, SD_VCC_PARTIAL_POWER_ON);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, 0x02);
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- msleep(5);
-
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
- SD_POWER_MASK, SD_VCC_POWER_ON);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, 0x06);
- return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rtsx_base_card_power_off(struct rtsx_pcr *pcr, int card)
-{
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
- SD_POWER_MASK, SD_POWER_OFF);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, 0x00);
- return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rtsx_base_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
- int err;
- u16 append;
-
- switch (voltage) {
- case OUTPUT_3V3:
- err = rtsx_pci_update_phy(pcr, PHY_TUNE, PHY_TUNE_VOLTAGE_MASK,
- PHY_TUNE_VOLTAGE_3V3);
- if (err < 0)
- return err;
- break;
- case OUTPUT_1V8:
- append = PHY_TUNE_D18_1V8;
- if (CHK_PCI_PID(pcr, 0x5249)) {
- err = rtsx_pci_update_phy(pcr, PHY_BACR,
- PHY_BACR_BASIC_MASK, 0);
- if (err < 0)
- return err;
- append = PHY_TUNE_D18_1V7;
- }
-
- err = rtsx_pci_update_phy(pcr, PHY_TUNE, PHY_TUNE_VOLTAGE_MASK,
- append);
- if (err < 0)
- return err;
- break;
- default:
- pcr_dbg(pcr, "unknown output voltage %d\n", voltage);
- return -EINVAL;
- }
-
- /* set pad drive */
- rtsx_pci_init_cmd(pcr);
- rts5249_fill_driving(pcr, voltage);
- return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static void rts5249_set_aspm(struct rtsx_pcr *pcr, bool enable)
-{
- struct rtsx_cr_option *option = &pcr->option;
- u8 val = 0;
-
- if (pcr->aspm_enabled == enable)
- return;
-
- if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) {
- if (enable)
- val = pcr->aspm_en;
- rtsx_pci_update_cfg_byte(pcr,
- pcr->pcie_cap + PCI_EXP_LNKCTL,
- ASPM_MASK_NEG, val);
- } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) {
- u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0;
-
- if (!enable)
- val = FORCE_ASPM_CTL0;
- rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val);
- }
-
- pcr->aspm_enabled = enable;
-}
-
-static const struct pcr_ops rts5249_pcr_ops = {
- .fetch_vendor_settings = rtsx_base_fetch_vendor_settings,
- .extra_init_hw = rts5249_extra_init_hw,
- .optimize_phy = rts5249_optimize_phy,
- .turn_on_led = rtsx_base_turn_on_led,
- .turn_off_led = rtsx_base_turn_off_led,
- .enable_auto_blink = rtsx_base_enable_auto_blink,
- .disable_auto_blink = rtsx_base_disable_auto_blink,
- .card_power_on = rtsx_base_card_power_on,
- .card_power_off = rtsx_base_card_power_off,
- .switch_output_voltage = rtsx_base_switch_output_voltage,
- .force_power_down = rtsx_base_force_power_down,
- .set_aspm = rts5249_set_aspm,
-};
-
-/* SD Pull Control Enable:
- * SD_DAT[3:0] ==> pull up
- * SD_CD ==> pull up
- * SD_WP ==> pull up
- * SD_CMD ==> pull up
- * SD_CLK ==> pull down
- */
-static const u32 rts5249_sd_pull_ctl_enable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66),
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0xAA),
- 0,
-};
-
-/* SD Pull Control Disable:
- * SD_DAT[3:0] ==> pull down
- * SD_CD ==> pull up
- * SD_WP ==> pull down
- * SD_CMD ==> pull down
- * SD_CLK ==> pull down
- */
-static const u32 rts5249_sd_pull_ctl_disable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66),
- RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
- 0,
-};
-
-/* MS Pull Control Enable:
- * MS CD ==> pull up
- * others ==> pull down
- */
-static const u32 rts5249_ms_pull_ctl_enable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
- 0,
-};
-
-/* MS Pull Control Disable:
- * MS CD ==> pull up
- * others ==> pull down
- */
-static const u32 rts5249_ms_pull_ctl_disable_tbl[] = {
- RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
- RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
- 0,
-};
-
-void rts5249_init_params(struct rtsx_pcr *pcr)
-{
- struct rtsx_cr_option *option = &(pcr->option);
-
- pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
- 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_B;
- 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;
- pcr->ms_pull_ctl_enable_tbl = rts5249_ms_pull_ctl_enable_tbl;
- pcr->ms_pull_ctl_disable_tbl = rts5249_ms_pull_ctl_disable_tbl;
-
- pcr->reg_pm_ctrl3 = PM_CTRL3;
-
- option->dev_flags = (LTR_L1SS_PWR_GATE_CHECK_CARD_EN
- | LTR_L1SS_PWR_GATE_EN);
- option->ltr_en = true;
-
- /* Init latency of active, idle, L1OFF to 60us, 300us, 3ms */
- option->ltr_active_latency = LTR_ACTIVE_LATENCY_DEF;
- option->ltr_idle_latency = LTR_IDLE_LATENCY_DEF;
- option->ltr_l1off_latency = LTR_L1OFF_LATENCY_DEF;
- option->dev_aspm_mode = DEV_ASPM_DYNAMIC;
- option->l1_snooze_delay = L1_SNOOZE_DELAY_DEF;
- option->ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5249_DEF;
- option->ltr_l1off_snooze_sspwrgate =
- LTR_L1OFF_SNOOZE_SSPWRGATE_5249_DEF;
-}
-
-static int rts524a_write_phy(struct rtsx_pcr *pcr, u8 addr, u16 val)
-{
- addr = addr & 0x80 ? (addr & 0x7F) | 0x40 : addr;
-
- return __rtsx_pci_write_phy_register(pcr, addr, val);
-}
-
-static int rts524a_read_phy(struct rtsx_pcr *pcr, u8 addr, u16 *val)
-{
- addr = addr & 0x80 ? (addr & 0x7F) | 0x40 : addr;
-
- return __rtsx_pci_read_phy_register(pcr, addr, val);
-}
-
-static int rts524a_optimize_phy(struct rtsx_pcr *pcr)
-{
- int err;
-
- err = rtsx_pci_write_register(pcr, RTS524A_PM_CTRL3,
- D3_DELINK_MODE_EN, 0x00);
- if (err < 0)
- return err;
-
- rtsx_pci_write_phy_register(pcr, PHY_PCR,
- PHY_PCR_FORCE_CODE | PHY_PCR_OOBS_CALI_50 |
- PHY_PCR_OOBS_VCM_08 | PHY_PCR_OOBS_SEN_90 | PHY_PCR_RSSI_EN);
- rtsx_pci_write_phy_register(pcr, PHY_SSCCR3,
- PHY_SSCCR3_STEP_IN | PHY_SSCCR3_CHECK_DELAY);
-
- if (is_version(pcr, 0x524A, IC_VER_A)) {
- rtsx_pci_write_phy_register(pcr, PHY_SSCCR3,
- PHY_SSCCR3_STEP_IN | PHY_SSCCR3_CHECK_DELAY);
- rtsx_pci_write_phy_register(pcr, PHY_SSCCR2,
- PHY_SSCCR2_PLL_NCODE | PHY_SSCCR2_TIME0 |
- PHY_SSCCR2_TIME2_WIDTH);
- rtsx_pci_write_phy_register(pcr, PHY_ANA1A,
- PHY_ANA1A_TXR_LOOPBACK | PHY_ANA1A_RXT_BIST |
- PHY_ANA1A_TXR_BIST | PHY_ANA1A_REV);
- rtsx_pci_write_phy_register(pcr, PHY_ANA1D,
- PHY_ANA1D_DEBUG_ADDR);
- rtsx_pci_write_phy_register(pcr, PHY_DIG1E,
- PHY_DIG1E_REV | PHY_DIG1E_D0_X_D1 |
- PHY_DIG1E_RX_ON_HOST | PHY_DIG1E_RCLK_REF_HOST |
- PHY_DIG1E_RCLK_TX_EN_KEEP |
- PHY_DIG1E_RCLK_TX_TERM_KEEP |
- PHY_DIG1E_RCLK_RX_EIDLE_ON | PHY_DIG1E_TX_TERM_KEEP |
- PHY_DIG1E_RX_TERM_KEEP | PHY_DIG1E_TX_EN_KEEP |
- PHY_DIG1E_RX_EN_KEEP);
- }
-
- rtsx_pci_write_phy_register(pcr, PHY_ANA08,
- PHY_ANA08_RX_EQ_DCGAIN | PHY_ANA08_SEL_RX_EN |
- PHY_ANA08_RX_EQ_VAL | PHY_ANA08_SCP | PHY_ANA08_SEL_IPI);
-
- return 0;
-}
-
-static int rts524a_extra_init_hw(struct rtsx_pcr *pcr)
-{
- rts5249_extra_init_hw(pcr);
-
- rtsx_pci_write_register(pcr, FUNC_FORCE_CTL,
- FORCE_ASPM_L1_EN, FORCE_ASPM_L1_EN);
- rtsx_pci_write_register(pcr, PM_EVENT_DEBUG, PME_DEBUG_0, PME_DEBUG_0);
- rtsx_pci_write_register(pcr, LDO_VCC_CFG1, LDO_VCC_LMT_EN,
- LDO_VCC_LMT_EN);
- rtsx_pci_write_register(pcr, PCLK_CTL, PCLK_MODE_SEL, PCLK_MODE_SEL);
- if (is_version(pcr, 0x524A, IC_VER_A)) {
- rtsx_pci_write_register(pcr, LDO_DV18_CFG,
- LDO_DV18_SR_MASK, LDO_DV18_SR_DF);
- rtsx_pci_write_register(pcr, LDO_VCC_CFG1,
- LDO_VCC_REF_TUNE_MASK, LDO_VCC_REF_1V2);
- rtsx_pci_write_register(pcr, LDO_VIO_CFG,
- LDO_VIO_REF_TUNE_MASK, LDO_VIO_REF_1V2);
- rtsx_pci_write_register(pcr, LDO_VIO_CFG,
- LDO_VIO_SR_MASK, LDO_VIO_SR_DF);
- rtsx_pci_write_register(pcr, LDO_DV12S_CFG,
- LDO_REF12_TUNE_MASK, LDO_REF12_TUNE_DF);
- rtsx_pci_write_register(pcr, SD40_LDO_CTL1,
- SD40_VIO_TUNE_MASK, SD40_VIO_TUNE_1V7);
- }
-
- return 0;
-}
-
-static void rts5250_set_l1off_cfg_sub_d0(struct rtsx_pcr *pcr, int active)
-{
- struct rtsx_cr_option *option = &(pcr->option);
-
- u32 interrupt = rtsx_pci_readl(pcr, RTSX_BIPR);
- int card_exist = (interrupt & SD_EXIST) | (interrupt & MS_EXIST);
- int aspm_L1_1, aspm_L1_2;
- u8 val = 0;
-
- aspm_L1_1 = rtsx_check_dev_flag(pcr, ASPM_L1_1_EN);
- aspm_L1_2 = rtsx_check_dev_flag(pcr, ASPM_L1_2_EN);
-
- if (active) {
- /* Run, latency: 60us */
- if (aspm_L1_1)
- val = option->ltr_l1off_snooze_sspwrgate;
- } else {
- /* L1off, latency: 300us */
- if (aspm_L1_2)
- val = option->ltr_l1off_sspwrgate;
- }
-
- if (aspm_L1_1 || aspm_L1_2) {
- if (rtsx_check_dev_flag(pcr,
- LTR_L1SS_PWR_GATE_CHECK_CARD_EN)) {
- if (card_exist)
- val &= ~L1OFF_MBIAS2_EN_5250;
- else
- val |= L1OFF_MBIAS2_EN_5250;
- }
- }
- rtsx_set_l1off_sub(pcr, val);
-}
-
-static const struct pcr_ops rts524a_pcr_ops = {
- .write_phy = rts524a_write_phy,
- .read_phy = rts524a_read_phy,
- .fetch_vendor_settings = rtsx_base_fetch_vendor_settings,
- .extra_init_hw = rts524a_extra_init_hw,
- .optimize_phy = rts524a_optimize_phy,
- .turn_on_led = rtsx_base_turn_on_led,
- .turn_off_led = rtsx_base_turn_off_led,
- .enable_auto_blink = rtsx_base_enable_auto_blink,
- .disable_auto_blink = rtsx_base_disable_auto_blink,
- .card_power_on = rtsx_base_card_power_on,
- .card_power_off = rtsx_base_card_power_off,
- .switch_output_voltage = rtsx_base_switch_output_voltage,
- .force_power_down = rtsx_base_force_power_down,
- .set_l1off_cfg_sub_d0 = rts5250_set_l1off_cfg_sub_d0,
- .set_aspm = rts5249_set_aspm,
-};
-
-void rts524a_init_params(struct rtsx_pcr *pcr)
-{
- rts5249_init_params(pcr);
- pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF;
- pcr->option.ltr_l1off_snooze_sspwrgate =
- LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF;
-
- pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3;
- pcr->ops = &rts524a_pcr_ops;
-}
-
-static int rts525a_card_power_on(struct rtsx_pcr *pcr, int card)
-{
- rtsx_pci_write_register(pcr, LDO_VCC_CFG1,
- LDO_VCC_TUNE_MASK, LDO_VCC_3V3);
- return rtsx_base_card_power_on(pcr, card);
-}
-
-static int rts525a_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
- switch (voltage) {
- case OUTPUT_3V3:
- rtsx_pci_write_register(pcr, LDO_CONFIG2,
- LDO_D3318_MASK, LDO_D3318_33V);
- rtsx_pci_write_register(pcr, SD_PAD_CTL, SD_IO_USING_1V8, 0);
- break;
- case OUTPUT_1V8:
- rtsx_pci_write_register(pcr, LDO_CONFIG2,
- LDO_D3318_MASK, LDO_D3318_18V);
- rtsx_pci_write_register(pcr, SD_PAD_CTL, SD_IO_USING_1V8,
- SD_IO_USING_1V8);
- break;
- default:
- return -EINVAL;
- }
-
- rtsx_pci_init_cmd(pcr);
- rts5249_fill_driving(pcr, voltage);
- return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts525a_optimize_phy(struct rtsx_pcr *pcr)
-{
- int err;
-
- err = rtsx_pci_write_register(pcr, RTS524A_PM_CTRL3,
- D3_DELINK_MODE_EN, 0x00);
- if (err < 0)
- return err;
-
- rtsx_pci_write_phy_register(pcr, _PHY_FLD0,
- _PHY_FLD0_CLK_REQ_20C | _PHY_FLD0_RX_IDLE_EN |
- _PHY_FLD0_BIT_ERR_RSTN | _PHY_FLD0_BER_COUNT |
- _PHY_FLD0_BER_TIMER | _PHY_FLD0_CHECK_EN);
-
- rtsx_pci_write_phy_register(pcr, _PHY_ANA03,
- _PHY_ANA03_TIMER_MAX | _PHY_ANA03_OOBS_DEB_EN |
- _PHY_CMU_DEBUG_EN);
-
- if (is_version(pcr, 0x525A, IC_VER_A))
- rtsx_pci_write_phy_register(pcr, _PHY_REV0,
- _PHY_REV0_FILTER_OUT | _PHY_REV0_CDR_BYPASS_PFD |
- _PHY_REV0_CDR_RX_IDLE_BYPASS);
-
- return 0;
-}
-
-static int rts525a_extra_init_hw(struct rtsx_pcr *pcr)
-{
- rts5249_extra_init_hw(pcr);
-
- rtsx_pci_write_register(pcr, PCLK_CTL, PCLK_MODE_SEL, PCLK_MODE_SEL);
- if (is_version(pcr, 0x525A, IC_VER_A)) {
- rtsx_pci_write_register(pcr, L1SUB_CONFIG2,
- L1SUB_AUTO_CFG, L1SUB_AUTO_CFG);
- rtsx_pci_write_register(pcr, RREF_CFG,
- RREF_VBGSEL_MASK, RREF_VBGSEL_1V25);
- rtsx_pci_write_register(pcr, LDO_VIO_CFG,
- LDO_VIO_TUNE_MASK, LDO_VIO_1V7);
- rtsx_pci_write_register(pcr, LDO_DV12S_CFG,
- LDO_D12_TUNE_MASK, LDO_D12_TUNE_DF);
- rtsx_pci_write_register(pcr, LDO_AV12S_CFG,
- LDO_AV12S_TUNE_MASK, LDO_AV12S_TUNE_DF);
- rtsx_pci_write_register(pcr, LDO_VCC_CFG0,
- LDO_VCC_LMTVTH_MASK, LDO_VCC_LMTVTH_2A);
- rtsx_pci_write_register(pcr, OOBS_CONFIG,
- OOBS_AUTOK_DIS | OOBS_VAL_MASK, 0x89);
- }
-
- return 0;
-}
-
-static const struct pcr_ops rts525a_pcr_ops = {
- .fetch_vendor_settings = rtsx_base_fetch_vendor_settings,
- .extra_init_hw = rts525a_extra_init_hw,
- .optimize_phy = rts525a_optimize_phy,
- .turn_on_led = rtsx_base_turn_on_led,
- .turn_off_led = rtsx_base_turn_off_led,
- .enable_auto_blink = rtsx_base_enable_auto_blink,
- .disable_auto_blink = rtsx_base_disable_auto_blink,
- .card_power_on = rts525a_card_power_on,
- .card_power_off = rtsx_base_card_power_off,
- .switch_output_voltage = rts525a_switch_output_voltage,
- .force_power_down = rtsx_base_force_power_down,
- .set_l1off_cfg_sub_d0 = rts5250_set_l1off_cfg_sub_d0,
- .set_aspm = rts5249_set_aspm,
-};
-
-void rts525a_init_params(struct rtsx_pcr *pcr)
-{
- rts5249_init_params(pcr);
- pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF;
- pcr->option.ltr_l1off_snooze_sspwrgate =
- LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF;
-
- pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3;
- pcr->ops = &rts525a_pcr_ops;
-}
-
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
deleted file mode 100644
index c3ed885c155c..000000000000
--- a/drivers/mfd/rtsx_pcr.c
+++ /dev/null
@@ -1,1572 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * 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
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- * Wei WANG <wei_wang@realsil.com.cn>
- */
-
-#include <linux/pci.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/highmem.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/idr.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/rtsx_pci.h>
-#include <linux/mmc/card.h>
-#include <asm/unaligned.h>
-
-#include "rtsx_pcr.h"
-
-static bool msi_en = true;
-module_param(msi_en, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(msi_en, "Enable MSI");
-
-static DEFINE_IDR(rtsx_pci_idr);
-static DEFINE_SPINLOCK(rtsx_pci_lock);
-
-static struct mfd_cell rtsx_pcr_cells[] = {
- [RTSX_SD_CARD] = {
- .name = DRV_NAME_RTSX_PCI_SDMMC,
- },
- [RTSX_MS_CARD] = {
- .name = DRV_NAME_RTSX_PCI_MS,
- },
-};
-
-static const struct pci_device_id rtsx_pci_ids[] = {
- { PCI_DEVICE(0x10EC, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { PCI_DEVICE(0x10EC, 0x522A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { PCI_DEVICE(0x10EC, 0x524A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { PCI_DEVICE(0x10EC, 0x525A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, rtsx_pci_ids);
-
-static inline void rtsx_pci_enable_aspm(struct rtsx_pcr *pcr)
-{
- rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL,
- 0xFC, pcr->aspm_en);
-}
-
-static inline void rtsx_pci_disable_aspm(struct rtsx_pcr *pcr)
-{
- rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL,
- 0xFC, 0);
-}
-
-int rtsx_comm_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency)
-{
- rtsx_pci_write_register(pcr, MSGTXDATA0,
- MASK_8_BIT_DEF, (u8) (latency & 0xFF));
- rtsx_pci_write_register(pcr, MSGTXDATA1,
- MASK_8_BIT_DEF, (u8)((latency >> 8) & 0xFF));
- rtsx_pci_write_register(pcr, MSGTXDATA2,
- MASK_8_BIT_DEF, (u8)((latency >> 16) & 0xFF));
- rtsx_pci_write_register(pcr, MSGTXDATA3,
- MASK_8_BIT_DEF, (u8)((latency >> 24) & 0xFF));
- rtsx_pci_write_register(pcr, LTR_CTL, LTR_TX_EN_MASK |
- LTR_LATENCY_MODE_MASK, LTR_TX_EN_1 | LTR_LATENCY_MODE_SW);
-
- return 0;
-}
-
-int rtsx_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency)
-{
- if (pcr->ops->set_ltr_latency)
- return pcr->ops->set_ltr_latency(pcr, latency);
- else
- return rtsx_comm_set_ltr_latency(pcr, latency);
-}
-
-static void rtsx_comm_set_aspm(struct rtsx_pcr *pcr, bool enable)
-{
- struct rtsx_cr_option *option = &pcr->option;
-
- if (pcr->aspm_enabled == enable)
- return;
-
- if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) {
- if (enable)
- rtsx_pci_enable_aspm(pcr);
- else
- rtsx_pci_disable_aspm(pcr);
- } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) {
- u8 mask = FORCE_ASPM_VAL_MASK;
- u8 val = 0;
-
- if (enable)
- val = pcr->aspm_en;
- rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val);
- }
-
- pcr->aspm_enabled = enable;
-}
-
-static void rtsx_disable_aspm(struct rtsx_pcr *pcr)
-{
- if (pcr->ops->set_aspm)
- pcr->ops->set_aspm(pcr, false);
- else
- rtsx_comm_set_aspm(pcr, false);
-}
-
-int rtsx_set_l1off_sub(struct rtsx_pcr *pcr, u8 val)
-{
- rtsx_pci_write_register(pcr, L1SUB_CONFIG3, 0xFF, val);
-
- return 0;
-}
-
-void rtsx_set_l1off_sub_cfg_d0(struct rtsx_pcr *pcr, int active)
-{
- if (pcr->ops->set_l1off_cfg_sub_d0)
- pcr->ops->set_l1off_cfg_sub_d0(pcr, active);
-}
-
-static void rtsx_comm_pm_full_on(struct rtsx_pcr *pcr)
-{
- struct rtsx_cr_option *option = &pcr->option;
-
- rtsx_disable_aspm(pcr);
-
- if (option->ltr_enabled)
- rtsx_set_ltr_latency(pcr, option->ltr_active_latency);
-
- if (rtsx_check_dev_flag(pcr, LTR_L1SS_PWR_GATE_EN))
- rtsx_set_l1off_sub_cfg_d0(pcr, 1);
-}
-
-void rtsx_pm_full_on(struct rtsx_pcr *pcr)
-{
- if (pcr->ops->full_on)
- pcr->ops->full_on(pcr);
- else
- rtsx_comm_pm_full_on(pcr);
-}
-
-void rtsx_pci_start_run(struct rtsx_pcr *pcr)
-{
- /* If pci device removed, don't queue idle work any more */
- if (pcr->remove_pci)
- return;
-
- if (pcr->state != PDEV_STAT_RUN) {
- pcr->state = PDEV_STAT_RUN;
- if (pcr->ops->enable_auto_blink)
- pcr->ops->enable_auto_blink(pcr);
- rtsx_pm_full_on(pcr);
- }
-
- mod_delayed_work(system_wq, &pcr->idle_work, msecs_to_jiffies(200));
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_start_run);
-
-int rtsx_pci_write_register(struct rtsx_pcr *pcr, u16 addr, u8 mask, u8 data)
-{
- int i;
- u32 val = HAIMR_WRITE_START;
-
- val |= (u32)(addr & 0x3FFF) << 16;
- val |= (u32)mask << 8;
- val |= (u32)data;
-
- rtsx_pci_writel(pcr, RTSX_HAIMR, val);
-
- for (i = 0; i < MAX_RW_REG_CNT; i++) {
- val = rtsx_pci_readl(pcr, RTSX_HAIMR);
- if ((val & HAIMR_TRANS_END) == 0) {
- if (data != (u8)val)
- return -EIO;
- return 0;
- }
- }
-
- return -ETIMEDOUT;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_write_register);
-
-int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data)
-{
- u32 val = HAIMR_READ_START;
- int i;
-
- val |= (u32)(addr & 0x3FFF) << 16;
- rtsx_pci_writel(pcr, RTSX_HAIMR, val);
-
- for (i = 0; i < MAX_RW_REG_CNT; i++) {
- val = rtsx_pci_readl(pcr, RTSX_HAIMR);
- if ((val & HAIMR_TRANS_END) == 0)
- break;
- }
-
- if (i >= MAX_RW_REG_CNT)
- return -ETIMEDOUT;
-
- if (data)
- *data = (u8)(val & 0xFF);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_read_register);
-
-int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
-{
- int err, i, finished = 0;
- u8 tmp;
-
- rtsx_pci_init_cmd(pcr);
-
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA0, 0xFF, (u8)val);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA1, 0xFF, (u8)(val >> 8));
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x81);
-
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- for (i = 0; i < 100000; i++) {
- err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp);
- if (err < 0)
- return err;
-
- if (!(tmp & 0x80)) {
- finished = 1;
- break;
- }
- }
-
- if (!finished)
- return -ETIMEDOUT;
-
- return 0;
-}
-
-int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
-{
- if (pcr->ops->write_phy)
- return pcr->ops->write_phy(pcr, addr, val);
-
- return __rtsx_pci_write_phy_register(pcr, addr, val);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_write_phy_register);
-
-int __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
-{
- int err, i, finished = 0;
- u16 data;
- u8 *ptr, tmp;
-
- rtsx_pci_init_cmd(pcr);
-
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x80);
-
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- for (i = 0; i < 100000; i++) {
- err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp);
- if (err < 0)
- return err;
-
- if (!(tmp & 0x80)) {
- finished = 1;
- break;
- }
- }
-
- if (!finished)
- return -ETIMEDOUT;
-
- rtsx_pci_init_cmd(pcr);
-
- rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA0, 0, 0);
- rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA1, 0, 0);
-
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- ptr = rtsx_pci_get_cmd_data(pcr);
- data = ((u16)ptr[1] << 8) | ptr[0];
-
- if (val)
- *val = data;
-
- return 0;
-}
-
-int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
-{
- if (pcr->ops->read_phy)
- return pcr->ops->read_phy(pcr, addr, val);
-
- return __rtsx_pci_read_phy_register(pcr, addr, val);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_read_phy_register);
-
-void rtsx_pci_stop_cmd(struct rtsx_pcr *pcr)
-{
- rtsx_pci_writel(pcr, RTSX_HCBCTLR, STOP_CMD);
- rtsx_pci_writel(pcr, RTSX_HDBCTLR, STOP_DMA);
-
- rtsx_pci_write_register(pcr, DMACTL, 0x80, 0x80);
- rtsx_pci_write_register(pcr, RBCTL, 0x80, 0x80);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_stop_cmd);
-
-void rtsx_pci_add_cmd(struct rtsx_pcr *pcr,
- u8 cmd_type, u16 reg_addr, u8 mask, u8 data)
-{
- unsigned long flags;
- u32 val = 0;
- u32 *ptr = (u32 *)(pcr->host_cmds_ptr);
-
- val |= (u32)(cmd_type & 0x03) << 30;
- val |= (u32)(reg_addr & 0x3FFF) << 16;
- val |= (u32)mask << 8;
- val |= (u32)data;
-
- spin_lock_irqsave(&pcr->lock, flags);
- ptr += pcr->ci;
- if (pcr->ci < (HOST_CMDS_BUF_LEN / 4)) {
- put_unaligned_le32(val, ptr);
- ptr++;
- pcr->ci++;
- }
- spin_unlock_irqrestore(&pcr->lock, flags);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_add_cmd);
-
-void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr)
-{
- u32 val = 1 << 31;
-
- rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
-
- val |= (u32)(pcr->ci * 4) & 0x00FFFFFF;
- /* Hardware Auto Response */
- val |= 0x40000000;
- rtsx_pci_writel(pcr, RTSX_HCBCTLR, val);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_send_cmd_no_wait);
-
-int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout)
-{
- struct completion trans_done;
- u32 val = 1 << 31;
- long timeleft;
- unsigned long flags;
- int err = 0;
-
- spin_lock_irqsave(&pcr->lock, flags);
-
- /* set up data structures for the wakeup system */
- pcr->done = &trans_done;
- pcr->trans_result = TRANS_NOT_READY;
- init_completion(&trans_done);
-
- rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
-
- val |= (u32)(pcr->ci * 4) & 0x00FFFFFF;
- /* Hardware Auto Response */
- val |= 0x40000000;
- rtsx_pci_writel(pcr, RTSX_HCBCTLR, val);
-
- spin_unlock_irqrestore(&pcr->lock, flags);
-
- /* Wait for TRANS_OK_INT */
- timeleft = wait_for_completion_interruptible_timeout(
- &trans_done, msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- pcr_dbg(pcr, "Timeout (%s %d)\n", __func__, __LINE__);
- err = -ETIMEDOUT;
- goto finish_send_cmd;
- }
-
- spin_lock_irqsave(&pcr->lock, flags);
- if (pcr->trans_result == TRANS_RESULT_FAIL)
- err = -EINVAL;
- else if (pcr->trans_result == TRANS_RESULT_OK)
- err = 0;
- else if (pcr->trans_result == TRANS_NO_DEVICE)
- err = -ENODEV;
- spin_unlock_irqrestore(&pcr->lock, flags);
-
-finish_send_cmd:
- spin_lock_irqsave(&pcr->lock, flags);
- pcr->done = NULL;
- spin_unlock_irqrestore(&pcr->lock, flags);
-
- if ((err < 0) && (err != -ENODEV))
- rtsx_pci_stop_cmd(pcr);
-
- if (pcr->finish_me)
- complete(pcr->finish_me);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_send_cmd);
-
-static void rtsx_pci_add_sg_tbl(struct rtsx_pcr *pcr,
- dma_addr_t addr, unsigned int len, int end)
-{
- u64 *ptr = (u64 *)(pcr->host_sg_tbl_ptr) + pcr->sgi;
- u64 val;
- u8 option = SG_VALID | SG_TRANS_DATA;
-
- pcr_dbg(pcr, "DMA addr: 0x%x, Len: 0x%x\n", (unsigned int)addr, len);
-
- if (end)
- option |= SG_END;
- val = ((u64)addr << 32) | ((u64)len << 12) | option;
-
- put_unaligned_le64(val, ptr);
- pcr->sgi++;
-}
-
-int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
- int num_sg, bool read, int timeout)
-{
- int err = 0, count;
-
- pcr_dbg(pcr, "--> %s: num_sg = %d\n", __func__, num_sg);
- count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read);
- if (count < 1)
- return -EINVAL;
- pcr_dbg(pcr, "DMA mapping count: %d\n", count);
-
- err = rtsx_pci_dma_transfer(pcr, sglist, count, read, timeout);
-
- rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
-
-int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
- int num_sg, bool read)
-{
- enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
- if (pcr->remove_pci)
- return -EINVAL;
-
- if ((sglist == NULL) || (num_sg <= 0))
- return -EINVAL;
-
- return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg);
-
-void rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
- int num_sg, bool read)
-{
- enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
- dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg);
-
-int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
- int count, bool read, int timeout)
-{
- struct completion trans_done;
- struct scatterlist *sg;
- dma_addr_t addr;
- long timeleft;
- unsigned long flags;
- unsigned int len;
- int i, err = 0;
- u32 val;
- u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE;
-
- if (pcr->remove_pci)
- return -ENODEV;
-
- if ((sglist == NULL) || (count < 1))
- return -EINVAL;
-
- val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
- pcr->sgi = 0;
- for_each_sg(sglist, sg, count, i) {
- addr = sg_dma_address(sg);
- len = sg_dma_len(sg);
- rtsx_pci_add_sg_tbl(pcr, addr, len, i == count - 1);
- }
-
- spin_lock_irqsave(&pcr->lock, flags);
-
- pcr->done = &trans_done;
- pcr->trans_result = TRANS_NOT_READY;
- init_completion(&trans_done);
- rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr);
- rtsx_pci_writel(pcr, RTSX_HDBCTLR, val);
-
- spin_unlock_irqrestore(&pcr->lock, flags);
-
- timeleft = wait_for_completion_interruptible_timeout(
- &trans_done, msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- pcr_dbg(pcr, "Timeout (%s %d)\n", __func__, __LINE__);
- err = -ETIMEDOUT;
- goto out;
- }
-
- spin_lock_irqsave(&pcr->lock, flags);
- if (pcr->trans_result == TRANS_RESULT_FAIL) {
- err = -EILSEQ;
- if (pcr->dma_error_count < RTS_MAX_TIMES_FREQ_REDUCTION)
- pcr->dma_error_count++;
- }
-
- else if (pcr->trans_result == TRANS_NO_DEVICE)
- err = -ENODEV;
- spin_unlock_irqrestore(&pcr->lock, flags);
-
-out:
- spin_lock_irqsave(&pcr->lock, flags);
- pcr->done = NULL;
- spin_unlock_irqrestore(&pcr->lock, flags);
-
- if ((err < 0) && (err != -ENODEV))
- rtsx_pci_stop_cmd(pcr);
-
- if (pcr->finish_me)
- complete(pcr->finish_me);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer);
-
-int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
-{
- int err;
- int i, j;
- u16 reg;
- u8 *ptr;
-
- if (buf_len > 512)
- buf_len = 512;
-
- ptr = buf;
- reg = PPBUF_BASE2;
- for (i = 0; i < buf_len / 256; i++) {
- rtsx_pci_init_cmd(pcr);
-
- for (j = 0; j < 256; j++)
- rtsx_pci_add_cmd(pcr, READ_REG_CMD, reg++, 0, 0);
-
- err = rtsx_pci_send_cmd(pcr, 250);
- if (err < 0)
- return err;
-
- memcpy(ptr, rtsx_pci_get_cmd_data(pcr), 256);
- ptr += 256;
- }
-
- if (buf_len % 256) {
- rtsx_pci_init_cmd(pcr);
-
- for (j = 0; j < buf_len % 256; j++)
- rtsx_pci_add_cmd(pcr, READ_REG_CMD, reg++, 0, 0);
-
- err = rtsx_pci_send_cmd(pcr, 250);
- if (err < 0)
- return err;
- }
-
- memcpy(ptr, rtsx_pci_get_cmd_data(pcr), buf_len % 256);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_read_ppbuf);
-
-int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
-{
- int err;
- int i, j;
- u16 reg;
- u8 *ptr;
-
- if (buf_len > 512)
- buf_len = 512;
-
- ptr = buf;
- reg = PPBUF_BASE2;
- for (i = 0; i < buf_len / 256; i++) {
- rtsx_pci_init_cmd(pcr);
-
- for (j = 0; j < 256; j++) {
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
- reg++, 0xFF, *ptr);
- ptr++;
- }
-
- err = rtsx_pci_send_cmd(pcr, 250);
- if (err < 0)
- return err;
- }
-
- if (buf_len % 256) {
- rtsx_pci_init_cmd(pcr);
-
- for (j = 0; j < buf_len % 256; j++) {
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
- reg++, 0xFF, *ptr);
- ptr++;
- }
-
- err = rtsx_pci_send_cmd(pcr, 250);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_write_ppbuf);
-
-static int rtsx_pci_set_pull_ctl(struct rtsx_pcr *pcr, const u32 *tbl)
-{
- rtsx_pci_init_cmd(pcr);
-
- while (*tbl & 0xFFFF0000) {
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
- (u16)(*tbl >> 16), 0xFF, (u8)(*tbl));
- tbl++;
- }
-
- return rtsx_pci_send_cmd(pcr, 100);
-}
-
-int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card)
-{
- const u32 *tbl;
-
- if (card == RTSX_SD_CARD)
- tbl = pcr->sd_pull_ctl_enable_tbl;
- else if (card == RTSX_MS_CARD)
- tbl = pcr->ms_pull_ctl_enable_tbl;
- else
- return -EINVAL;
-
- return rtsx_pci_set_pull_ctl(pcr, tbl);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_card_pull_ctl_enable);
-
-int rtsx_pci_card_pull_ctl_disable(struct rtsx_pcr *pcr, int card)
-{
- const u32 *tbl;
-
- if (card == RTSX_SD_CARD)
- tbl = pcr->sd_pull_ctl_disable_tbl;
- else if (card == RTSX_MS_CARD)
- tbl = pcr->ms_pull_ctl_disable_tbl;
- else
- return -EINVAL;
-
-
- return rtsx_pci_set_pull_ctl(pcr, tbl);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_card_pull_ctl_disable);
-
-static void rtsx_pci_enable_bus_int(struct rtsx_pcr *pcr)
-{
- pcr->bier = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN | SD_INT_EN;
-
- if (pcr->num_slots > 1)
- pcr->bier |= MS_INT_EN;
-
- /* Enable Bus Interrupt */
- rtsx_pci_writel(pcr, RTSX_BIER, pcr->bier);
-
- pcr_dbg(pcr, "RTSX_BIER: 0x%08x\n", pcr->bier);
-}
-
-static inline u8 double_ssc_depth(u8 depth)
-{
- return ((depth > 1) ? (depth - 1) : depth);
-}
-
-static u8 revise_ssc_depth(u8 ssc_depth, u8 div)
-{
- if (div > CLK_DIV_1) {
- if (ssc_depth > (div - 1))
- ssc_depth -= (div - 1);
- else
- ssc_depth = SSC_DEPTH_4M;
- }
-
- return ssc_depth;
-}
-
-int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
- u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk)
-{
- int err, clk;
- u8 n, clk_divider, mcu_cnt, div;
- static const u8 depth[] = {
- [RTSX_SSC_DEPTH_4M] = SSC_DEPTH_4M,
- [RTSX_SSC_DEPTH_2M] = SSC_DEPTH_2M,
- [RTSX_SSC_DEPTH_1M] = SSC_DEPTH_1M,
- [RTSX_SSC_DEPTH_500K] = SSC_DEPTH_500K,
- [RTSX_SSC_DEPTH_250K] = SSC_DEPTH_250K,
- };
-
- if (initial_mode) {
- /* We use 250k(around) here, in initial stage */
- clk_divider = SD_CLK_DIVIDE_128;
- card_clock = 30000000;
- } else {
- clk_divider = SD_CLK_DIVIDE_0;
- }
- err = rtsx_pci_write_register(pcr, SD_CFG1,
- SD_CLK_DIVIDE_MASK, clk_divider);
- if (err < 0)
- return err;
-
- /* Reduce card clock by 20MHz each time a DMA transfer error occurs */
- if (card_clock == UHS_SDR104_MAX_DTR &&
- pcr->dma_error_count &&
- PCI_PID(pcr) == RTS5227_DEVICE_ID)
- card_clock = UHS_SDR104_MAX_DTR -
- (pcr->dma_error_count * 20000000);
-
- card_clock /= 1000000;
- pcr_dbg(pcr, "Switch card clock to %dMHz\n", card_clock);
-
- clk = card_clock;
- if (!initial_mode && double_clk)
- clk = card_clock * 2;
- pcr_dbg(pcr, "Internal SSC clock: %dMHz (cur_clock = %d)\n",
- clk, pcr->cur_clock);
-
- if (clk == pcr->cur_clock)
- return 0;
-
- if (pcr->ops->conv_clk_and_div_n)
- n = (u8)pcr->ops->conv_clk_and_div_n(clk, CLK_TO_DIV_N);
- else
- n = (u8)(clk - 2);
- if ((clk <= 2) || (n > MAX_DIV_N_PCR))
- return -EINVAL;
-
- mcu_cnt = (u8)(125/clk + 3);
- if (mcu_cnt > 15)
- mcu_cnt = 15;
-
- /* Make sure that the SSC clock div_n is not less than MIN_DIV_N_PCR */
- div = CLK_DIV_1;
- while ((n < MIN_DIV_N_PCR) && (div < CLK_DIV_8)) {
- if (pcr->ops->conv_clk_and_div_n) {
- int dbl_clk = pcr->ops->conv_clk_and_div_n(n,
- DIV_N_TO_CLK) * 2;
- n = (u8)pcr->ops->conv_clk_and_div_n(dbl_clk,
- CLK_TO_DIV_N);
- } else {
- n = (n + 2) * 2 - 2;
- }
- div++;
- }
- pcr_dbg(pcr, "n = %d, div = %d\n", n, div);
-
- ssc_depth = depth[ssc_depth];
- if (double_clk)
- ssc_depth = double_ssc_depth(ssc_depth);
-
- ssc_depth = revise_ssc_depth(ssc_depth, div);
- pcr_dbg(pcr, "ssc_depth = %d\n", ssc_depth);
-
- rtsx_pci_init_cmd(pcr);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
- CLK_LOW_FREQ, CLK_LOW_FREQ);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_DIV,
- 0xFF, (div << 4) | mcu_cnt);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2,
- SSC_DEPTH_MASK, ssc_depth);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
- if (vpclk) {
- 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);
- }
-
- err = rtsx_pci_send_cmd(pcr, 2000);
- if (err < 0)
- return err;
-
- /* Wait SSC clock stable */
- udelay(10);
- err = rtsx_pci_write_register(pcr, CLK_CTL, CLK_LOW_FREQ, 0);
- if (err < 0)
- return err;
-
- pcr->cur_clock = clk;
- return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_switch_clock);
-
-int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card)
-{
- if (pcr->ops->card_power_on)
- return pcr->ops->card_power_on(pcr, card);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_card_power_on);
-
-int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card)
-{
- if (pcr->ops->card_power_off)
- return pcr->ops->card_power_off(pcr, card);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off);
-
-int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card)
-{
- static const unsigned int cd_mask[] = {
- [RTSX_SD_CARD] = SD_EXIST,
- [RTSX_MS_CARD] = MS_EXIST
- };
-
- if (!(pcr->flags & PCR_MS_PMOS)) {
- /* When using single PMOS, accessing card is not permitted
- * if the existing card is not the designated one.
- */
- if (pcr->card_exist & (~cd_mask[card]))
- return -EIO;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_card_exclusive_check);
-
-int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
- if (pcr->ops->switch_output_voltage)
- return pcr->ops->switch_output_voltage(pcr, voltage);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_switch_output_voltage);
-
-unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr)
-{
- unsigned int val;
-
- val = rtsx_pci_readl(pcr, RTSX_BIPR);
- if (pcr->ops->cd_deglitch)
- val = pcr->ops->cd_deglitch(pcr);
-
- return val;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_card_exist);
-
-void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr)
-{
- struct completion finish;
-
- pcr->finish_me = &finish;
- init_completion(&finish);
-
- if (pcr->done)
- complete(pcr->done);
-
- if (!pcr->remove_pci)
- rtsx_pci_stop_cmd(pcr);
-
- wait_for_completion_interruptible_timeout(&finish,
- msecs_to_jiffies(2));
- pcr->finish_me = NULL;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_complete_unfinished_transfer);
-
-static void rtsx_pci_card_detect(struct work_struct *work)
-{
- struct delayed_work *dwork;
- struct rtsx_pcr *pcr;
- unsigned long flags;
- unsigned int card_detect = 0, card_inserted, card_removed;
- u32 irq_status;
-
- dwork = to_delayed_work(work);
- pcr = container_of(dwork, struct rtsx_pcr, carddet_work);
-
- pcr_dbg(pcr, "--> %s\n", __func__);
-
- mutex_lock(&pcr->pcr_mutex);
- spin_lock_irqsave(&pcr->lock, flags);
-
- irq_status = rtsx_pci_readl(pcr, RTSX_BIPR);
- pcr_dbg(pcr, "irq_status: 0x%08x\n", irq_status);
-
- irq_status &= CARD_EXIST;
- card_inserted = pcr->card_inserted & irq_status;
- card_removed = pcr->card_removed;
- pcr->card_inserted = 0;
- pcr->card_removed = 0;
-
- spin_unlock_irqrestore(&pcr->lock, flags);
-
- if (card_inserted || card_removed) {
- pcr_dbg(pcr, "card_inserted: 0x%x, card_removed: 0x%x\n",
- card_inserted, card_removed);
-
- if (pcr->ops->cd_deglitch)
- card_inserted = pcr->ops->cd_deglitch(pcr);
-
- card_detect = card_inserted | card_removed;
-
- pcr->card_exist |= card_inserted;
- pcr->card_exist &= ~card_removed;
- }
-
- mutex_unlock(&pcr->pcr_mutex);
-
- if ((card_detect & SD_EXIST) && pcr->slots[RTSX_SD_CARD].card_event)
- pcr->slots[RTSX_SD_CARD].card_event(
- pcr->slots[RTSX_SD_CARD].p_dev);
- if ((card_detect & MS_EXIST) && pcr->slots[RTSX_MS_CARD].card_event)
- pcr->slots[RTSX_MS_CARD].card_event(
- pcr->slots[RTSX_MS_CARD].p_dev);
-}
-
-static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
-{
- struct rtsx_pcr *pcr = dev_id;
- u32 int_reg;
-
- if (!pcr)
- return IRQ_NONE;
-
- spin_lock(&pcr->lock);
-
- int_reg = rtsx_pci_readl(pcr, RTSX_BIPR);
- /* Clear interrupt flag */
- rtsx_pci_writel(pcr, RTSX_BIPR, int_reg);
- if ((int_reg & pcr->bier) == 0) {
- spin_unlock(&pcr->lock);
- return IRQ_NONE;
- }
- if (int_reg == 0xFFFFFFFF) {
- spin_unlock(&pcr->lock);
- return IRQ_HANDLED;
- }
-
- int_reg &= (pcr->bier | 0x7FFFFF);
-
- if (int_reg & SD_INT) {
- if (int_reg & SD_EXIST) {
- pcr->card_inserted |= SD_EXIST;
- } else {
- pcr->card_removed |= SD_EXIST;
- pcr->card_inserted &= ~SD_EXIST;
- }
- pcr->dma_error_count = 0;
- }
-
- if (int_reg & MS_INT) {
- if (int_reg & MS_EXIST) {
- pcr->card_inserted |= MS_EXIST;
- } else {
- pcr->card_removed |= MS_EXIST;
- pcr->card_inserted &= ~MS_EXIST;
- }
- }
-
- if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) {
- if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) {
- pcr->trans_result = TRANS_RESULT_FAIL;
- if (pcr->done)
- complete(pcr->done);
- } else if (int_reg & TRANS_OK_INT) {
- pcr->trans_result = TRANS_RESULT_OK;
- if (pcr->done)
- complete(pcr->done);
- }
- }
-
- if (pcr->card_inserted || pcr->card_removed)
- schedule_delayed_work(&pcr->carddet_work,
- msecs_to_jiffies(200));
-
- spin_unlock(&pcr->lock);
- return IRQ_HANDLED;
-}
-
-static int rtsx_pci_acquire_irq(struct rtsx_pcr *pcr)
-{
- pcr_dbg(pcr, "%s: pcr->msi_en = %d, pci->irq = %d\n",
- __func__, pcr->msi_en, pcr->pci->irq);
-
- if (request_irq(pcr->pci->irq, rtsx_pci_isr,
- pcr->msi_en ? 0 : IRQF_SHARED,
- DRV_NAME_RTSX_PCI, pcr)) {
- dev_err(&(pcr->pci->dev),
- "rtsx_sdmmc: unable to grab IRQ %d, disabling device\n",
- pcr->pci->irq);
- return -1;
- }
-
- pcr->irq = pcr->pci->irq;
- pci_intx(pcr->pci, !pcr->msi_en);
-
- return 0;
-}
-
-static void rtsx_enable_aspm(struct rtsx_pcr *pcr)
-{
- if (pcr->ops->set_aspm)
- pcr->ops->set_aspm(pcr, true);
- else
- rtsx_comm_set_aspm(pcr, true);
-}
-
-static void rtsx_comm_pm_power_saving(struct rtsx_pcr *pcr)
-{
- struct rtsx_cr_option *option = &pcr->option;
-
- if (option->ltr_enabled) {
- u32 latency = option->ltr_l1off_latency;
-
- if (rtsx_check_dev_flag(pcr, L1_SNOOZE_TEST_EN))
- mdelay(option->l1_snooze_delay);
-
- rtsx_set_ltr_latency(pcr, latency);
- }
-
- if (rtsx_check_dev_flag(pcr, LTR_L1SS_PWR_GATE_EN))
- rtsx_set_l1off_sub_cfg_d0(pcr, 0);
-
- rtsx_enable_aspm(pcr);
-}
-
-void rtsx_pm_power_saving(struct rtsx_pcr *pcr)
-{
- if (pcr->ops->power_saving)
- pcr->ops->power_saving(pcr);
- else
- rtsx_comm_pm_power_saving(pcr);
-}
-
-static void rtsx_pci_idle_work(struct work_struct *work)
-{
- struct delayed_work *dwork = to_delayed_work(work);
- struct rtsx_pcr *pcr = container_of(dwork, struct rtsx_pcr, idle_work);
-
- pcr_dbg(pcr, "--> %s\n", __func__);
-
- mutex_lock(&pcr->pcr_mutex);
-
- pcr->state = PDEV_STAT_IDLE;
-
- if (pcr->ops->disable_auto_blink)
- pcr->ops->disable_auto_blink(pcr);
- if (pcr->ops->turn_off_led)
- pcr->ops->turn_off_led(pcr);
-
- rtsx_pm_power_saving(pcr);
-
- mutex_unlock(&pcr->pcr_mutex);
-}
-
-#ifdef CONFIG_PM
-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);
-}
-#endif
-
-static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
-{
- int err;
-
- pcr->pcie_cap = pci_find_capability(pcr->pci, PCI_CAP_ID_EXP);
- rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
-
- rtsx_pci_enable_bus_int(pcr);
-
- /* Power on SSC */
- err = rtsx_pci_write_register(pcr, FPDCTL, SSC_POWER_DOWN, 0);
- if (err < 0)
- return err;
-
- /* Wait SSC power stable */
- udelay(200);
-
- rtsx_pci_disable_aspm(pcr);
- if (pcr->ops->optimize_phy) {
- err = pcr->ops->optimize_phy(pcr);
- if (err < 0)
- return err;
- }
-
- rtsx_pci_init_cmd(pcr);
-
- /* Set mcu_cnt to 7 to ensure data can be sampled properly */
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_DIV, 0x07, 0x07);
-
- 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 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, 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);
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2, 0xFF, 0x12);
- /* Disable cd_pwr_save */
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CHANGE_LINK_STATE, 0x16, 0x10);
- /* Clear Link Ready Interrupt */
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
- LINK_RDY_INT, LINK_RDY_INT);
- /* Enlarge the estimation window of PERST# glitch
- * to reduce the chance of invalid card interrupt
- */
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PERST_GLITCH_WIDTH, 0xFF, 0x80);
- /* Update RC oscillator to 400k
- * bit[0] F_HIGH: for RC oscillator, Rst_value is 1'b1
- * 1: 2M 0: 400k
- */
- rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RCCTL, 0x01, 0x00);
- /* Set interrupt write clear
- * bit 1: U_elbi_if_rd_clr_en
- * 1: Enable ELBI interrupt[31:22] & [7:0] flag read clear
- * 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);
-
- err = rtsx_pci_send_cmd(pcr, 100);
- if (err < 0)
- return err;
-
- switch (PCI_PID(pcr)) {
- case PID_5250:
- case PID_524A:
- case PID_525A:
- rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 1, 1);
- break;
- default:
- break;
- }
-
- /* Enable clk_request_n to enable clock power management */
- rtsx_pci_write_config_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL + 1, 1);
- /* Enter L1 when host tx idle */
- rtsx_pci_write_config_byte(pcr, 0x70F, 0x5B);
-
- if (pcr->ops->extra_init_hw) {
- err = pcr->ops->extra_init_hw(pcr);
- if (err < 0)
- return err;
- }
-
- /* No CD interrupt if probing driver with card inserted.
- * So we need to initialize pcr->card_exist here.
- */
- if (pcr->ops->cd_deglitch)
- pcr->card_exist = pcr->ops->cd_deglitch(pcr);
- else
- pcr->card_exist = rtsx_pci_readl(pcr, RTSX_BIPR) & CARD_EXIST;
-
- return 0;
-}
-
-static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
-{
- int err;
-
- spin_lock_init(&pcr->lock);
- mutex_init(&pcr->pcr_mutex);
-
- switch (PCI_PID(pcr)) {
- default:
- case 0x5209:
- rts5209_init_params(pcr);
- break;
-
- case 0x5229:
- rts5229_init_params(pcr);
- break;
-
- case 0x5289:
- rtl8411_init_params(pcr);
- break;
-
- case 0x5227:
- rts5227_init_params(pcr);
- break;
-
- case 0x522A:
- rts522a_init_params(pcr);
- break;
-
- case 0x5249:
- rts5249_init_params(pcr);
- break;
-
- case 0x524A:
- rts524a_init_params(pcr);
- break;
-
- case 0x525A:
- rts525a_init_params(pcr);
- break;
-
- case 0x5287:
- rtl8411b_init_params(pcr);
- break;
-
- case 0x5286:
- rtl8402_init_params(pcr);
- break;
- }
-
- pcr_dbg(pcr, "PID: 0x%04x, IC version: 0x%02x\n",
- PCI_PID(pcr), pcr->ic_version);
-
- pcr->slots = kcalloc(pcr->num_slots, sizeof(struct rtsx_slot),
- GFP_KERNEL);
- if (!pcr->slots)
- return -ENOMEM;
-
- if (pcr->ops->fetch_vendor_settings)
- pcr->ops->fetch_vendor_settings(pcr);
-
- pcr_dbg(pcr, "pcr->aspm_en = 0x%x\n", pcr->aspm_en);
- pcr_dbg(pcr, "pcr->sd30_drive_sel_1v8 = 0x%x\n",
- pcr->sd30_drive_sel_1v8);
- pcr_dbg(pcr, "pcr->sd30_drive_sel_3v3 = 0x%x\n",
- pcr->sd30_drive_sel_3v3);
- pcr_dbg(pcr, "pcr->card_drive_sel = 0x%x\n",
- pcr->card_drive_sel);
- pcr_dbg(pcr, "pcr->flags = 0x%x\n", pcr->flags);
-
- pcr->state = PDEV_STAT_IDLE;
- err = rtsx_pci_init_hw(pcr);
- if (err < 0) {
- kfree(pcr->slots);
- return err;
- }
-
- return 0;
-}
-
-static int rtsx_pci_probe(struct pci_dev *pcidev,
- const struct pci_device_id *id)
-{
- struct rtsx_pcr *pcr;
- struct pcr_handle *handle;
- u32 base, len;
- int ret, i, bar = 0;
-
- dev_dbg(&(pcidev->dev),
- ": Realtek PCI-E Card Reader found at %s [%04x:%04x] (rev %x)\n",
- pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device,
- (int)pcidev->revision);
-
- ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32));
- if (ret < 0)
- return ret;
-
- ret = pci_enable_device(pcidev);
- if (ret)
- return ret;
-
- ret = pci_request_regions(pcidev, DRV_NAME_RTSX_PCI);
- if (ret)
- goto disable;
-
- pcr = kzalloc(sizeof(*pcr), GFP_KERNEL);
- if (!pcr) {
- ret = -ENOMEM;
- goto release_pci;
- }
-
- handle = kzalloc(sizeof(*handle), GFP_KERNEL);
- if (!handle) {
- ret = -ENOMEM;
- goto free_pcr;
- }
- handle->pcr = pcr;
-
- idr_preload(GFP_KERNEL);
- spin_lock(&rtsx_pci_lock);
- ret = idr_alloc(&rtsx_pci_idr, pcr, 0, 0, GFP_NOWAIT);
- if (ret >= 0)
- pcr->id = ret;
- spin_unlock(&rtsx_pci_lock);
- idr_preload_end();
- if (ret < 0)
- goto free_handle;
-
- pcr->pci = pcidev;
- dev_set_drvdata(&pcidev->dev, handle);
-
- if (CHK_PCI_PID(pcr, 0x525A))
- bar = 1;
- len = pci_resource_len(pcidev, bar);
- base = pci_resource_start(pcidev, bar);
- pcr->remap_addr = ioremap_nocache(base, len);
- if (!pcr->remap_addr) {
- ret = -ENOMEM;
- goto free_handle;
- }
-
- pcr->rtsx_resv_buf = dma_alloc_coherent(&(pcidev->dev),
- RTSX_RESV_BUF_LEN, &(pcr->rtsx_resv_buf_addr),
- GFP_KERNEL);
- if (pcr->rtsx_resv_buf == NULL) {
- ret = -ENXIO;
- goto unmap;
- }
- pcr->host_cmds_ptr = pcr->rtsx_resv_buf;
- pcr->host_cmds_addr = pcr->rtsx_resv_buf_addr;
- pcr->host_sg_tbl_ptr = pcr->rtsx_resv_buf + HOST_CMDS_BUF_LEN;
- pcr->host_sg_tbl_addr = pcr->rtsx_resv_buf_addr + HOST_CMDS_BUF_LEN;
-
- pcr->card_inserted = 0;
- pcr->card_removed = 0;
- INIT_DELAYED_WORK(&pcr->carddet_work, rtsx_pci_card_detect);
- INIT_DELAYED_WORK(&pcr->idle_work, rtsx_pci_idle_work);
-
- pcr->msi_en = msi_en;
- if (pcr->msi_en) {
- ret = pci_enable_msi(pcidev);
- if (ret)
- pcr->msi_en = false;
- }
-
- ret = rtsx_pci_acquire_irq(pcr);
- if (ret < 0)
- goto disable_msi;
-
- pci_set_master(pcidev);
- synchronize_irq(pcr->irq);
-
- ret = rtsx_pci_init_chip(pcr);
- if (ret < 0)
- goto disable_irq;
-
- for (i = 0; i < ARRAY_SIZE(rtsx_pcr_cells); i++) {
- rtsx_pcr_cells[i].platform_data = handle;
- rtsx_pcr_cells[i].pdata_size = sizeof(*handle);
- }
- ret = mfd_add_devices(&pcidev->dev, pcr->id, rtsx_pcr_cells,
- ARRAY_SIZE(rtsx_pcr_cells), NULL, 0, NULL);
- if (ret < 0)
- goto disable_irq;
-
- schedule_delayed_work(&pcr->idle_work, msecs_to_jiffies(200));
-
- return 0;
-
-disable_irq:
- free_irq(pcr->irq, (void *)pcr);
-disable_msi:
- if (pcr->msi_en)
- pci_disable_msi(pcr->pci);
- dma_free_coherent(&(pcr->pci->dev), RTSX_RESV_BUF_LEN,
- pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr);
-unmap:
- iounmap(pcr->remap_addr);
-free_handle:
- kfree(handle);
-free_pcr:
- kfree(pcr);
-release_pci:
- pci_release_regions(pcidev);
-disable:
- pci_disable_device(pcidev);
-
- return ret;
-}
-
-static void rtsx_pci_remove(struct pci_dev *pcidev)
-{
- struct pcr_handle *handle = pci_get_drvdata(pcidev);
- struct rtsx_pcr *pcr = handle->pcr;
-
- pcr->remove_pci = true;
-
- /* Disable interrupts at the pcr level */
- spin_lock_irq(&pcr->lock);
- rtsx_pci_writel(pcr, RTSX_BIER, 0);
- pcr->bier = 0;
- spin_unlock_irq(&pcr->lock);
-
- cancel_delayed_work_sync(&pcr->carddet_work);
- cancel_delayed_work_sync(&pcr->idle_work);
-
- mfd_remove_devices(&pcidev->dev);
-
- dma_free_coherent(&(pcr->pci->dev), RTSX_RESV_BUF_LEN,
- pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr);
- free_irq(pcr->irq, (void *)pcr);
- if (pcr->msi_en)
- pci_disable_msi(pcr->pci);
- iounmap(pcr->remap_addr);
-
- pci_release_regions(pcidev);
- pci_disable_device(pcidev);
-
- spin_lock(&rtsx_pci_lock);
- idr_remove(&rtsx_pci_idr, pcr->id);
- spin_unlock(&rtsx_pci_lock);
-
- kfree(pcr->slots);
- kfree(pcr);
- kfree(handle);
-
- dev_dbg(&(pcidev->dev),
- ": Realtek PCI-E Card Reader at %s [%04x:%04x] has been removed\n",
- pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device);
-}
-
-#ifdef CONFIG_PM
-
-static int rtsx_pci_suspend(struct pci_dev *pcidev, pm_message_t state)
-{
- struct pcr_handle *handle;
- struct rtsx_pcr *pcr;
-
- dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
-
- handle = pci_get_drvdata(pcidev);
- pcr = handle->pcr;
-
- cancel_delayed_work(&pcr->carddet_work);
- cancel_delayed_work(&pcr->idle_work);
-
- mutex_lock(&pcr->pcr_mutex);
-
- rtsx_pci_power_off(pcr, HOST_ENTER_S3);
-
- pci_save_state(pcidev);
- pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0);
- pci_disable_device(pcidev);
- pci_set_power_state(pcidev, pci_choose_state(pcidev, state));
-
- mutex_unlock(&pcr->pcr_mutex);
- return 0;
-}
-
-static int rtsx_pci_resume(struct pci_dev *pcidev)
-{
- struct pcr_handle *handle;
- struct rtsx_pcr *pcr;
- int ret = 0;
-
- dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
-
- handle = pci_get_drvdata(pcidev);
- pcr = handle->pcr;
-
- mutex_lock(&pcr->pcr_mutex);
-
- pci_set_power_state(pcidev, PCI_D0);
- pci_restore_state(pcidev);
- ret = pci_enable_device(pcidev);
- if (ret)
- goto out;
- pci_set_master(pcidev);
-
- ret = rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, 0x00);
- if (ret)
- goto out;
-
- ret = rtsx_pci_init_hw(pcr);
- if (ret)
- goto out;
-
- schedule_delayed_work(&pcr->idle_work, msecs_to_jiffies(200));
-
-out:
- mutex_unlock(&pcr->pcr_mutex);
- 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);
- free_irq(pcr->irq, (void *)pcr);
- if (pcr->msi_en)
- pci_disable_msi(pcr->pci);
-}
-
-#else /* CONFIG_PM */
-
-#define rtsx_pci_suspend NULL
-#define rtsx_pci_resume NULL
-#define rtsx_pci_shutdown NULL
-
-#endif /* CONFIG_PM */
-
-static struct pci_driver rtsx_pci_driver = {
- .name = DRV_NAME_RTSX_PCI,
- .id_table = rtsx_pci_ids,
- .probe = rtsx_pci_probe,
- .remove = rtsx_pci_remove,
- .suspend = rtsx_pci_suspend,
- .resume = rtsx_pci_resume,
- .shutdown = rtsx_pci_shutdown,
-};
-module_pci_driver(rtsx_pci_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
-MODULE_DESCRIPTION("Realtek PCI-E Card Reader Driver");
diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h
deleted file mode 100644
index ec784e04fe20..000000000000
--- a/drivers/mfd/rtsx_pcr.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * 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
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- * Wei WANG <wei_wang@realsil.com.cn>
- */
-
-#ifndef __RTSX_PCR_H
-#define __RTSX_PCR_H
-
-#include <linux/mfd/rtsx_pci.h>
-
-#define MIN_DIV_N_PCR 80
-#define MAX_DIV_N_PCR 208
-
-#define RTS522A_PM_CTRL3 0xFF7E
-
-#define RTS524A_PME_FORCE_CTL 0xFF78
-#define RTS524A_PM_CTRL3 0xFF7E
-
-#define LTR_ACTIVE_LATENCY_DEF 0x883C
-#define LTR_IDLE_LATENCY_DEF 0x892C
-#define LTR_L1OFF_LATENCY_DEF 0x9003
-#define L1_SNOOZE_DELAY_DEF 1
-#define LTR_L1OFF_SSPWRGATE_5249_DEF 0xAF
-#define LTR_L1OFF_SSPWRGATE_5250_DEF 0xFF
-#define LTR_L1OFF_SNOOZE_SSPWRGATE_5249_DEF 0xAC
-#define LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF 0xF8
-#define CMD_TIMEOUT_DEF 100
-#define ASPM_MASK_NEG 0xFC
-#define MASK_8_BIT_DEF 0xFF
-
-int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val);
-int __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val);
-
-void rts5209_init_params(struct rtsx_pcr *pcr);
-void rts5229_init_params(struct rtsx_pcr *pcr);
-void rtl8411_init_params(struct rtsx_pcr *pcr);
-void rtl8402_init_params(struct rtsx_pcr *pcr);
-void rts5227_init_params(struct rtsx_pcr *pcr);
-void rts522a_init_params(struct rtsx_pcr *pcr);
-void rts5249_init_params(struct rtsx_pcr *pcr);
-void rts524a_init_params(struct rtsx_pcr *pcr);
-void rts525a_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)
-
-#define set_pull_ctrl_tables(pcr, __device) \
-do { \
- pcr->sd_pull_ctl_enable_tbl = __device##_sd_pull_ctl_enable_tbl; \
- pcr->sd_pull_ctl_disable_tbl = __device##_sd_pull_ctl_disable_tbl; \
- pcr->ms_pull_ctl_enable_tbl = __device##_ms_pull_ctl_enable_tbl; \
- pcr->ms_pull_ctl_disable_tbl = __device##_ms_pull_ctl_disable_tbl; \
-} while (0)
-
-/* generic operations */
-int rtsx_gops_pm_reset(struct rtsx_pcr *pcr);
-int rtsx_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency);
-int rtsx_set_l1off_sub(struct rtsx_pcr *pcr, u8 val);
-
-#endif
diff --git a/drivers/mfd/rtsx_usb.c b/drivers/mfd/rtsx_usb.c
deleted file mode 100644
index 59d61b04c197..000000000000
--- a/drivers/mfd/rtsx_usb.c
+++ /dev/null
@@ -1,791 +0,0 @@
-/* Driver for Realtek USB card reader
- *
- * 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 version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- * Roger Tseng <rogerable@realtek.com>
- */
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/usb.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/rtsx_usb.h>
-
-static int polling_pipe = 1;
-module_param(polling_pipe, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(polling_pipe, "polling pipe (0: ctl, 1: bulk)");
-
-static const struct mfd_cell rtsx_usb_cells[] = {
- [RTSX_USB_SD_CARD] = {
- .name = "rtsx_usb_sdmmc",
- .pdata_size = 0,
- },
- [RTSX_USB_MS_CARD] = {
- .name = "rtsx_usb_ms",
- .pdata_size = 0,
- },
-};
-
-static void rtsx_usb_sg_timed_out(struct timer_list *t)
-{
- struct rtsx_ucr *ucr = from_timer(ucr, t, sg_timer);
-
- dev_dbg(&ucr->pusb_intf->dev, "%s: sg transfer timed out", __func__);
- usb_sg_cancel(&ucr->current_sg);
-}
-
-static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr,
- unsigned int pipe, struct scatterlist *sg, int num_sg,
- unsigned int length, unsigned int *act_len, int timeout)
-{
- int ret;
-
- dev_dbg(&ucr->pusb_intf->dev, "%s: xfer %u bytes, %d entries\n",
- __func__, length, num_sg);
- ret = usb_sg_init(&ucr->current_sg, ucr->pusb_dev, pipe, 0,
- sg, num_sg, length, GFP_NOIO);
- if (ret)
- return ret;
-
- ucr->sg_timer.expires = jiffies + msecs_to_jiffies(timeout);
- add_timer(&ucr->sg_timer);
- usb_sg_wait(&ucr->current_sg);
- if (!del_timer_sync(&ucr->sg_timer))
- ret = -ETIMEDOUT;
- else
- ret = ucr->current_sg.status;
-
- if (act_len)
- *act_len = ucr->current_sg.bytes;
-
- return ret;
-}
-
-int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe,
- void *buf, unsigned int len, int num_sg,
- unsigned int *act_len, int timeout)
-{
- if (timeout < 600)
- timeout = 600;
-
- if (num_sg)
- return rtsx_usb_bulk_transfer_sglist(ucr, pipe,
- (struct scatterlist *)buf, num_sg, len, act_len,
- timeout);
- else
- return usb_bulk_msg(ucr->pusb_dev, pipe, buf, len, act_len,
- timeout);
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_transfer_data);
-
-static inline void rtsx_usb_seq_cmd_hdr(struct rtsx_ucr *ucr,
- u16 addr, u16 len, u8 seq_type)
-{
- rtsx_usb_cmd_hdr_tag(ucr);
-
- ucr->cmd_buf[PACKET_TYPE] = seq_type;
- ucr->cmd_buf[5] = (u8)(len >> 8);
- ucr->cmd_buf[6] = (u8)len;
- ucr->cmd_buf[8] = (u8)(addr >> 8);
- ucr->cmd_buf[9] = (u8)addr;
-
- if (seq_type == SEQ_WRITE)
- ucr->cmd_buf[STAGE_FLAG] = 0;
- else
- ucr->cmd_buf[STAGE_FLAG] = STAGE_R;
-}
-
-static int rtsx_usb_seq_write_register(struct rtsx_ucr *ucr,
- u16 addr, u16 len, u8 *data)
-{
- u16 cmd_len = ALIGN(SEQ_WRITE_DATA_OFFSET + len, 4);
-
- if (!data)
- return -EINVAL;
-
- if (cmd_len > IOBUF_SIZE)
- return -EINVAL;
-
- rtsx_usb_seq_cmd_hdr(ucr, addr, len, SEQ_WRITE);
- memcpy(ucr->cmd_buf + SEQ_WRITE_DATA_OFFSET, data, len);
-
- return rtsx_usb_transfer_data(ucr,
- usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
- ucr->cmd_buf, cmd_len, 0, NULL, 100);
-}
-
-static int rtsx_usb_seq_read_register(struct rtsx_ucr *ucr,
- u16 addr, u16 len, u8 *data)
-{
- int i, ret;
- u16 rsp_len = round_down(len, 4);
- u16 res_len = len - rsp_len;
-
- if (!data)
- return -EINVAL;
-
- /* 4-byte aligned part */
- if (rsp_len) {
- rtsx_usb_seq_cmd_hdr(ucr, addr, len, SEQ_READ);
- ret = rtsx_usb_transfer_data(ucr,
- usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
- ucr->cmd_buf, 12, 0, NULL, 100);
- if (ret)
- return ret;
-
- ret = rtsx_usb_transfer_data(ucr,
- usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN),
- data, rsp_len, 0, NULL, 100);
- if (ret)
- return ret;
- }
-
- /* unaligned part */
- for (i = 0; i < res_len; i++) {
- ret = rtsx_usb_read_register(ucr, addr + rsp_len + i,
- data + rsp_len + i);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-int rtsx_usb_read_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len)
-{
- return rtsx_usb_seq_read_register(ucr, PPBUF_BASE2, (u16)buf_len, buf);
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_read_ppbuf);
-
-int rtsx_usb_write_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len)
-{
- return rtsx_usb_seq_write_register(ucr, PPBUF_BASE2, (u16)buf_len, buf);
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_write_ppbuf);
-
-int rtsx_usb_ep0_write_register(struct rtsx_ucr *ucr, u16 addr,
- u8 mask, u8 data)
-{
- u16 value, index;
-
- addr |= EP0_WRITE_REG_CMD << EP0_OP_SHIFT;
- value = swab16(addr);
- index = mask | data << 8;
-
- return usb_control_msg(ucr->pusb_dev,
- usb_sndctrlpipe(ucr->pusb_dev, 0), RTSX_USB_REQ_REG_OP,
- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value, index, NULL, 0, 100);
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_ep0_write_register);
-
-int rtsx_usb_ep0_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data)
-{
- u16 value;
- u8 *buf;
- int ret;
-
- if (!data)
- return -EINVAL;
-
- buf = kzalloc(sizeof(u8), GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- addr |= EP0_READ_REG_CMD << EP0_OP_SHIFT;
- value = swab16(addr);
-
- ret = usb_control_msg(ucr->pusb_dev,
- usb_rcvctrlpipe(ucr->pusb_dev, 0), RTSX_USB_REQ_REG_OP,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- value, 0, buf, 1, 100);
- *data = *buf;
-
- kfree(buf);
- return ret;
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_ep0_read_register);
-
-void rtsx_usb_add_cmd(struct rtsx_ucr *ucr, u8 cmd_type, u16 reg_addr,
- u8 mask, u8 data)
-{
- int i;
-
- if (ucr->cmd_idx < (IOBUF_SIZE - CMD_OFFSET) / 4) {
- i = CMD_OFFSET + ucr->cmd_idx * 4;
-
- ucr->cmd_buf[i++] = ((cmd_type & 0x03) << 6) |
- (u8)((reg_addr >> 8) & 0x3F);
- ucr->cmd_buf[i++] = (u8)reg_addr;
- ucr->cmd_buf[i++] = mask;
- ucr->cmd_buf[i++] = data;
-
- ucr->cmd_idx++;
- }
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_add_cmd);
-
-int rtsx_usb_send_cmd(struct rtsx_ucr *ucr, u8 flag, int timeout)
-{
- int ret;
-
- ucr->cmd_buf[CNT_H] = (u8)(ucr->cmd_idx >> 8);
- ucr->cmd_buf[CNT_L] = (u8)(ucr->cmd_idx);
- ucr->cmd_buf[STAGE_FLAG] = flag;
-
- ret = rtsx_usb_transfer_data(ucr,
- usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
- ucr->cmd_buf, ucr->cmd_idx * 4 + CMD_OFFSET,
- 0, NULL, timeout);
- if (ret) {
- rtsx_usb_clear_fsm_err(ucr);
- return ret;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_send_cmd);
-
-int rtsx_usb_get_rsp(struct rtsx_ucr *ucr, int rsp_len, int timeout)
-{
- if (rsp_len <= 0)
- return -EINVAL;
-
- rsp_len = ALIGN(rsp_len, 4);
-
- return rtsx_usb_transfer_data(ucr,
- usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN),
- ucr->rsp_buf, rsp_len, 0, NULL, timeout);
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_get_rsp);
-
-static int rtsx_usb_get_status_with_bulk(struct rtsx_ucr *ucr, u16 *status)
-{
- int ret;
-
- rtsx_usb_init_cmd(ucr);
- rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_EXIST, 0x00, 0x00);
- rtsx_usb_add_cmd(ucr, READ_REG_CMD, OCPSTAT, 0x00, 0x00);
- ret = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
- if (ret)
- return ret;
-
- ret = rtsx_usb_get_rsp(ucr, 2, 100);
- if (ret)
- return ret;
-
- *status = ((ucr->rsp_buf[0] >> 2) & 0x0f) |
- ((ucr->rsp_buf[1] & 0x03) << 4);
-
- return 0;
-}
-
-int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status)
-{
- int ret;
- u16 *buf;
-
- if (!status)
- return -EINVAL;
-
- if (polling_pipe == 0) {
- buf = kzalloc(sizeof(u16), GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- ret = usb_control_msg(ucr->pusb_dev,
- usb_rcvctrlpipe(ucr->pusb_dev, 0),
- RTSX_USB_REQ_POLL,
- USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, 0, buf, 2, 100);
- *status = *buf;
-
- kfree(buf);
- } else {
- ret = rtsx_usb_get_status_with_bulk(ucr, status);
- }
-
- /* usb_control_msg may return positive when success */
- if (ret < 0)
- return ret;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_get_card_status);
-
-static int rtsx_usb_write_phy_register(struct rtsx_ucr *ucr, u8 addr, u8 val)
-{
- dev_dbg(&ucr->pusb_intf->dev, "Write 0x%x to phy register 0x%x\n",
- val, addr);
-
- rtsx_usb_init_cmd(ucr);
-
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VSTAIN, 0xFF, val);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VCONTROL, 0xFF, addr & 0x0F);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VCONTROL,
- 0xFF, (addr >> 4) & 0x0F);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01);
-
- return rtsx_usb_send_cmd(ucr, MODE_C, 100);
-}
-
-int rtsx_usb_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask, u8 data)
-{
- rtsx_usb_init_cmd(ucr);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, addr, mask, data);
- return rtsx_usb_send_cmd(ucr, MODE_C, 100);
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_write_register);
-
-int rtsx_usb_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data)
-{
- int ret;
-
- if (data != NULL)
- *data = 0;
-
- rtsx_usb_init_cmd(ucr);
- rtsx_usb_add_cmd(ucr, READ_REG_CMD, addr, 0, 0);
- ret = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
- if (ret)
- return ret;
-
- ret = rtsx_usb_get_rsp(ucr, 1, 100);
- if (ret)
- return ret;
-
- if (data != NULL)
- *data = ucr->rsp_buf[0];
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_read_register);
-
-static inline u8 double_ssc_depth(u8 depth)
-{
- return (depth > 1) ? (depth - 1) : depth;
-}
-
-static u8 revise_ssc_depth(u8 ssc_depth, u8 div)
-{
- if (div > CLK_DIV_1) {
- if (ssc_depth > div - 1)
- ssc_depth -= (div - 1);
- else
- ssc_depth = SSC_DEPTH_2M;
- }
-
- return ssc_depth;
-}
-
-int rtsx_usb_switch_clock(struct rtsx_ucr *ucr, unsigned int card_clock,
- u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk)
-{
- int ret;
- u8 n, clk_divider, mcu_cnt, div;
-
- if (!card_clock) {
- ucr->cur_clk = 0;
- return 0;
- }
-
- if (initial_mode) {
- /* We use 250k(around) here, in initial stage */
- clk_divider = SD_CLK_DIVIDE_128;
- card_clock = 30000000;
- } else {
- clk_divider = SD_CLK_DIVIDE_0;
- }
-
- ret = rtsx_usb_write_register(ucr, SD_CFG1,
- SD_CLK_DIVIDE_MASK, clk_divider);
- if (ret < 0)
- return ret;
-
- card_clock /= 1000000;
- dev_dbg(&ucr->pusb_intf->dev,
- "Switch card clock to %dMHz\n", card_clock);
-
- if (!initial_mode && double_clk)
- card_clock *= 2;
- dev_dbg(&ucr->pusb_intf->dev,
- "Internal SSC clock: %dMHz (cur_clk = %d)\n",
- card_clock, ucr->cur_clk);
-
- if (card_clock == ucr->cur_clk)
- return 0;
-
- /* Converting clock value into internal settings: n and div */
- n = card_clock - 2;
- if ((card_clock <= 2) || (n > MAX_DIV_N))
- return -EINVAL;
-
- mcu_cnt = 60/card_clock + 3;
- if (mcu_cnt > 15)
- mcu_cnt = 15;
-
- /* Make sure that the SSC clock div_n is not less than MIN_DIV_N */
-
- div = CLK_DIV_1;
- while (n < MIN_DIV_N && div < CLK_DIV_4) {
- n = (n + 2) * 2 - 2;
- div++;
- }
- dev_dbg(&ucr->pusb_intf->dev, "n = %d, div = %d\n", n, div);
-
- if (double_clk)
- ssc_depth = double_ssc_depth(ssc_depth);
-
- ssc_depth = revise_ssc_depth(ssc_depth, div);
- dev_dbg(&ucr->pusb_intf->dev, "ssc_depth = %d\n", ssc_depth);
-
- rtsx_usb_init_cmd(ucr);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, CLK_CHANGE);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV,
- 0x3F, (div << 4) | mcu_cnt);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL2,
- SSC_DEPTH_MASK, ssc_depth);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
- if (vpclk) {
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, 0);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, PHASE_NOT_RESET);
- }
-
- ret = rtsx_usb_send_cmd(ucr, MODE_C, 2000);
- if (ret < 0)
- return ret;
-
- ret = rtsx_usb_write_register(ucr, SSC_CTL1, 0xff,
- SSC_RSTB | SSC_8X_EN | SSC_SEL_4M);
- if (ret < 0)
- return ret;
-
- /* Wait SSC clock stable */
- usleep_range(100, 1000);
-
- ret = rtsx_usb_write_register(ucr, CLK_DIV, CLK_CHANGE, 0);
- if (ret < 0)
- return ret;
-
- ucr->cur_clk = card_clock;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_switch_clock);
-
-int rtsx_usb_card_exclusive_check(struct rtsx_ucr *ucr, int card)
-{
- int ret;
- u16 val;
- u16 cd_mask[] = {
- [RTSX_USB_SD_CARD] = (CD_MASK & ~SD_CD),
- [RTSX_USB_MS_CARD] = (CD_MASK & ~MS_CD)
- };
-
- ret = rtsx_usb_get_card_status(ucr, &val);
- /*
- * If get status fails, return 0 (ok) for the exclusive check
- * and let the flow fail at somewhere else.
- */
- if (ret)
- return 0;
-
- if (val & cd_mask[card])
- return -EIO;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_card_exclusive_check);
-
-static int rtsx_usb_reset_chip(struct rtsx_ucr *ucr)
-{
- int ret;
- u8 val;
-
- rtsx_usb_init_cmd(ucr);
-
- if (CHECK_PKG(ucr, LQFP48)) {
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
- LDO3318_PWR_MASK, LDO_SUSPEND);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
- FORCE_LDO_POWERB, FORCE_LDO_POWERB);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1,
- 0x30, 0x10);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5,
- 0x03, 0x01);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6,
- 0x0C, 0x04);
- }
-
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SYS_DUMMY0, NYET_MSAK, NYET_EN);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CD_DEGLITCH_WIDTH, 0xFF, 0x08);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
- CD_DEGLITCH_EN, XD_CD_DEGLITCH_EN, 0x0);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD30_DRIVE_SEL,
- SD30_DRIVE_MASK, DRIVER_TYPE_D);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
- CARD_DRIVE_SEL, SD20_DRIVE_MASK, 0x0);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, 0xE0, 0x0);
-
- if (ucr->is_rts5179)
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
- CARD_PULL_CTL5, 0x03, 0x01);
-
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DMA1_CTL,
- EXTEND_DMA1_ASYNC_SIGNAL, EXTEND_DMA1_ASYNC_SIGNAL);
- rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_INT_PEND,
- XD_INT | MS_INT | SD_INT,
- XD_INT | MS_INT | SD_INT);
-
- ret = rtsx_usb_send_cmd(ucr, MODE_C, 100);
- if (ret)
- return ret;
-
- /* config non-crystal mode */
- rtsx_usb_read_register(ucr, CFG_MODE, &val);
- if ((val & XTAL_FREE) || ((val & CLK_MODE_MASK) == CLK_MODE_NON_XTAL)) {
- ret = rtsx_usb_write_phy_register(ucr, 0xC2, 0x7C);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-static int rtsx_usb_init_chip(struct rtsx_ucr *ucr)
-{
- int ret;
- u8 val;
-
- rtsx_usb_clear_fsm_err(ucr);
-
- /* power on SSC */
- ret = rtsx_usb_write_register(ucr,
- FPDCTL, SSC_POWER_MASK, SSC_POWER_ON);
- if (ret)
- return ret;
-
- usleep_range(100, 1000);
- ret = rtsx_usb_write_register(ucr, CLK_DIV, CLK_CHANGE, 0x00);
- if (ret)
- return ret;
-
- /* determine IC version */
- ret = rtsx_usb_read_register(ucr, HW_VERSION, &val);
- if (ret)
- return ret;
-
- ucr->ic_version = val & HW_VER_MASK;
-
- /* determine package */
- ret = rtsx_usb_read_register(ucr, CARD_SHARE_MODE, &val);
- if (ret)
- return ret;
-
- if (val & CARD_SHARE_LQFP_SEL) {
- ucr->package = LQFP48;
- dev_dbg(&ucr->pusb_intf->dev, "Package: LQFP48\n");
- } else {
- ucr->package = QFN24;
- dev_dbg(&ucr->pusb_intf->dev, "Package: QFN24\n");
- }
-
- /* determine IC variations */
- rtsx_usb_read_register(ucr, CFG_MODE_1, &val);
- if (val & RTS5179) {
- ucr->is_rts5179 = true;
- dev_dbg(&ucr->pusb_intf->dev, "Device is rts5179\n");
- } else {
- ucr->is_rts5179 = false;
- }
-
- return rtsx_usb_reset_chip(ucr);
-}
-
-static int rtsx_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *usb_dev = interface_to_usbdev(intf);
- struct rtsx_ucr *ucr;
- int ret;
-
- dev_dbg(&intf->dev,
- ": Realtek USB Card Reader found at bus %03d address %03d\n",
- usb_dev->bus->busnum, usb_dev->devnum);
-
- ucr = devm_kzalloc(&intf->dev, sizeof(*ucr), GFP_KERNEL);
- if (!ucr)
- return -ENOMEM;
-
- ucr->pusb_dev = usb_dev;
-
- ucr->iobuf = usb_alloc_coherent(ucr->pusb_dev, IOBUF_SIZE,
- GFP_KERNEL, &ucr->iobuf_dma);
- if (!ucr->iobuf)
- return -ENOMEM;
-
- usb_set_intfdata(intf, ucr);
-
- ucr->vendor_id = id->idVendor;
- ucr->product_id = id->idProduct;
- ucr->cmd_buf = ucr->rsp_buf = ucr->iobuf;
-
- mutex_init(&ucr->dev_mutex);
-
- ucr->pusb_intf = intf;
-
- /* initialize */
- ret = rtsx_usb_init_chip(ucr);
- if (ret)
- goto out_init_fail;
-
- /* initialize USB SG transfer timer */
- timer_setup(&ucr->sg_timer, rtsx_usb_sg_timed_out, 0);
-
- ret = mfd_add_hotplug_devices(&intf->dev, rtsx_usb_cells,
- ARRAY_SIZE(rtsx_usb_cells));
- if (ret)
- goto out_init_fail;
-
-#ifdef CONFIG_PM
- intf->needs_remote_wakeup = 1;
- usb_enable_autosuspend(usb_dev);
-#endif
-
- return 0;
-
-out_init_fail:
- usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
- ucr->iobuf_dma);
- return ret;
-}
-
-static void rtsx_usb_disconnect(struct usb_interface *intf)
-{
- struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
-
- dev_dbg(&intf->dev, "%s called\n", __func__);
-
- mfd_remove_devices(&intf->dev);
-
- usb_set_intfdata(ucr->pusb_intf, NULL);
- usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
- ucr->iobuf_dma);
-}
-
-#ifdef CONFIG_PM
-static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)
-{
- struct rtsx_ucr *ucr =
- (struct rtsx_ucr *)usb_get_intfdata(intf);
- u16 val = 0;
-
- dev_dbg(&intf->dev, "%s called with pm message 0x%04x\n",
- __func__, message.event);
-
- if (PMSG_IS_AUTO(message)) {
- if (mutex_trylock(&ucr->dev_mutex)) {
- rtsx_usb_get_card_status(ucr, &val);
- mutex_unlock(&ucr->dev_mutex);
-
- /* Defer the autosuspend if card exists */
- if (val & (SD_CD | MS_CD))
- return -EAGAIN;
- } else {
- /* There is an ongoing operation*/
- return -EAGAIN;
- }
- }
-
- return 0;
-}
-
-static int rtsx_usb_resume(struct usb_interface *intf)
-{
- return 0;
-}
-
-static int rtsx_usb_reset_resume(struct usb_interface *intf)
-{
- struct rtsx_ucr *ucr =
- (struct rtsx_ucr *)usb_get_intfdata(intf);
-
- rtsx_usb_reset_chip(ucr);
- return 0;
-}
-
-#else /* CONFIG_PM */
-
-#define rtsx_usb_suspend NULL
-#define rtsx_usb_resume NULL
-#define rtsx_usb_reset_resume NULL
-
-#endif /* CONFIG_PM */
-
-
-static int rtsx_usb_pre_reset(struct usb_interface *intf)
-{
- struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
-
- mutex_lock(&ucr->dev_mutex);
- return 0;
-}
-
-static int rtsx_usb_post_reset(struct usb_interface *intf)
-{
- struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
-
- mutex_unlock(&ucr->dev_mutex);
- return 0;
-}
-
-static struct usb_device_id rtsx_usb_usb_ids[] = {
- { USB_DEVICE(0x0BDA, 0x0129) },
- { USB_DEVICE(0x0BDA, 0x0139) },
- { USB_DEVICE(0x0BDA, 0x0140) },
- { }
-};
-MODULE_DEVICE_TABLE(usb, rtsx_usb_usb_ids);
-
-static struct usb_driver rtsx_usb_driver = {
- .name = "rtsx_usb",
- .probe = rtsx_usb_probe,
- .disconnect = rtsx_usb_disconnect,
- .suspend = rtsx_usb_suspend,
- .resume = rtsx_usb_resume,
- .reset_resume = rtsx_usb_reset_resume,
- .pre_reset = rtsx_usb_pre_reset,
- .post_reset = rtsx_usb_post_reset,
- .id_table = rtsx_usb_usb_ids,
- .supports_autosuspend = 1,
- .soft_unbind = 1,
-};
-
-module_usb_driver(rtsx_usb_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>");
-MODULE_DESCRIPTION("Realtek USB Card Reader Driver");
diff --git a/drivers/mfd/stm32-lptimer.c b/drivers/mfd/stm32-lptimer.c
index 075330a25f61..a00f99f36559 100644
--- a/drivers/mfd/stm32-lptimer.c
+++ b/drivers/mfd/stm32-lptimer.c
@@ -1,13 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* STM32 Low-Power Timer parent driver.
- *
* Copyright (C) STMicroelectronics 2017
- *
* Author: Fabrice Gasnier <fabrice.gasnier@st.com>
- *
* Inspired by Benjamin Gaignard's stm32-timers driver
- *
- * License terms: GNU General Public License (GPL), version 2
*/
#include <linux/mfd/stm32-lptimer.h>
diff --git a/drivers/mfd/stm32-timers.c b/drivers/mfd/stm32-timers.c
index a6675a449409..1d347e5dfa79 100644
--- a/drivers/mfd/stm32-timers.c
+++ b/drivers/mfd/stm32-timers.c
@@ -1,9 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) STMicroelectronics 2016
- *
* Author: Benjamin Gaignard <benjamin.gaignard@st.com>
- *
- * License terms: GNU General Public License (GPL), version 2
*/
#include <linux/mfd/stm32-timers.h>
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 0f3fab47fe48..3cd958a31f36 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -124,7 +124,7 @@ static int ti_tscadc_probe(struct platform_device *pdev)
struct ti_tscadc_dev *tscadc;
struct resource *res;
struct clk *clk;
- struct device_node *node = pdev->dev.of_node;
+ struct device_node *node;
struct mfd_cell *cell;
struct property *prop;
const __be32 *cur;
diff --git a/drivers/mfd/tmio_core.c b/drivers/mfd/tmio_core.c
index 83af78c1b0eb..ebf54cc28f7a 100644
--- a/drivers/mfd/tmio_core.c
+++ b/drivers/mfd/tmio_core.c
@@ -9,6 +9,26 @@
#include <linux/export.h>
#include <linux/mfd/tmio.h>
+#define CNF_CMD 0x04
+#define CNF_CTL_BASE 0x10
+#define CNF_INT_PIN 0x3d
+#define CNF_STOP_CLK_CTL 0x40
+#define CNF_GCLK_CTL 0x41
+#define CNF_SD_CLK_MODE 0x42
+#define CNF_PIN_STATUS 0x44
+#define CNF_PWR_CTL_1 0x48
+#define CNF_PWR_CTL_2 0x49
+#define CNF_PWR_CTL_3 0x4a
+#define CNF_CARD_DETECT_MODE 0x4c
+#define CNF_SD_SLOT 0x50
+#define CNF_EXT_GCLK_CTL_1 0xf0
+#define CNF_EXT_GCLK_CTL_2 0xf1
+#define CNF_EXT_GCLK_CTL_3 0xf9
+#define CNF_SD_LED_EN_1 0xfa
+#define CNF_SD_LED_EN_2 0xfe
+
+#define SDCREN 0x2 /* Enable access to MMC CTL regs. (flag in COMMAND_REG)*/
+
int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base)
{
/* Enable the MMC/SD Control registers */