MFD Fixes for 3.5

- 3 Palmas fixes, 1 of them being a build error fix.
 - 2 mc13xx fixes. 1 for fixing an SPI regmap configuration and another one for
   working around an i.Mx hardware bug.
 - 1 omap-usb regression fix.
 - 1 twl6040 build breakage fix.
 - 1 file deletion (ab5500-core.h) that was overlooked during the last merge
   window.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIcBAABAgAGBQJP/vIeAAoJEIqAPN1PVmxKTlMP/RFiIP9Exyy0gqGCMJpYpOfH
 m1NX0LMZ9ktv61M0bgx1AZewNCLG0O6vNf1zW6S4aaczx/D5o1uqWTrra7WqIHTj
 LG2dTpm1dYo2FHNkaGSwpDCGJI2H1K9l4HBcevJcNeVsE3OSZIfQXOFAdXuxJjf3
 RUBZ/dzRAi0/KnZySu+1z3ua3Fbican5CwcljsMEp3K5ajr/d7zFCYDz3Osk+g3k
 kvncHZtfeQNhXgfHMm+8nWRnHvpGWutUXtAIL5yzSQgeEtKANe7D2KsxK73t68iV
 BkelhzqXk9o711nluA0hF4gvS20/cS675QNbQ6XLUK2N7wsCORqMSTNXxnvJze2E
 1hH599dLqPMkq3P5TRCTaQLx8p/QK8Vnrgvsy5pOkSZnqiNU/Owtik0NA4Gz3WrG
 f6WMRHNb+wwLdvhkqHUuMjt2OzmIUiuikKu6kt2pyJ3tXj0tPisC0UieF+6fRHG+
 yxwrXqKtv/aj+gbp+X476fMWt2LR4Duihq1QkW2tE9rtkVlUMTIJgCj6T1mdC6T5
 g1ELR3mi+AXCyOp5d6jpmJmKTnHjQfCPouNgalfFonJlp7Fngih0SzUpwV/XYyP7
 CUy490mcRUZUhSmTH4UQV9CfxhQA8gKNbN9Oak499N6UNWSDyoiH/bh+h/BQuAli
 Gn6cYgk5IKYjiO020ilG
 =dlI4
 -----END PGP SIGNATURE-----

Merge tag 'mfd-for-linus-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6

Pull MFD Fixes from Samuel Ortiz:
 - Three Palmas fixes, One of them being a build error fix.
 - Two mc13xx fixes.  One for fixing an SPI regmap configuration and
   another one for working around an i.Mx hardware bug.
 - One omap-usb regression fix.
 - One twl6040 build breakage fix.
 - One file deletion (ab5500-core.h) that was overlooked during the last
   merge window.

* tag 'mfd-for-linus-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6:
  mfd: Add missing hunk to change palmas irq to clear on read
  mfd: Fix palmas regulator pdata missing
  mfd: USB: Fix the omap-usb EHCI ULPI PHY reset fix issues.
  mfd: Update twl6040 Kconfig to avoid build breakage
  mfd: Delete ab5500-core.h
  mfd: mc13xxx workaround SPI hardware bug on i.Mx
  mfd: Fix mc13xxx SPI regmap
  mfd: Add terminating entry for i2c_device_id palmas table
This commit is contained in:
Linus Torvalds 2012-07-13 09:54:26 -07:00
commit 7801dc33be
6 changed files with 133 additions and 101 deletions

View File

@ -286,6 +286,7 @@ config TWL6040_CORE
depends on I2C=y && GENERIC_HARDIRQS depends on I2C=y && GENERIC_HARDIRQS
select MFD_CORE select MFD_CORE
select REGMAP_I2C select REGMAP_I2C
select IRQ_DOMAIN
default n default n
help help
Say yes here if you want support for Texas Instruments TWL6040 audio Say yes here if you want support for Texas Instruments TWL6040 audio

View File

@ -1,87 +0,0 @@
/*
* Copyright (C) 2011 ST-Ericsson
* License terms: GNU General Public License (GPL) version 2
* Shared definitions and data structures for the AB5500 MFD driver
*/
/* Read/write operation values. */
#define AB5500_PERM_RD (0x01)
#define AB5500_PERM_WR (0x02)
/* Read/write permissions. */
#define AB5500_PERM_RO (AB5500_PERM_RD)
#define AB5500_PERM_RW (AB5500_PERM_RD | AB5500_PERM_WR)
#define AB5500_MASK_BASE (0x60)
#define AB5500_MASK_END (0x79)
#define AB5500_CHIP_ID (0x20)
/**
* struct ab5500_reg_range
* @first: the first address of the range
* @last: the last address of the range
* @perm: access permissions for the range
*/
struct ab5500_reg_range {
u8 first;
u8 last;
u8 perm;
};
/**
* struct ab5500_i2c_ranges
* @count: the number of ranges in the list
* @range: the list of register ranges
*/
struct ab5500_i2c_ranges {
u8 nranges;
u8 bankid;
const struct ab5500_reg_range *range;
};
/**
* struct ab5500_i2c_banks
* @count: the number of ranges in the list
* @range: the list of register ranges
*/
struct ab5500_i2c_banks {
u8 nbanks;
const struct ab5500_i2c_ranges *bank;
};
/**
* struct ab5500_bank
* @slave_addr: I2C slave_addr found in AB5500 specification
* @name: Documentation name of the bank. For reference
*/
struct ab5500_bank {
u8 slave_addr;
const char *name;
};
static const struct ab5500_bank bankinfo[AB5500_NUM_BANKS] = {
[AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = {
AB5500_ADDR_VIT_IO_I2C_CLK_TST_OTP, "VIT_IO_I2C_CLK_TST_OTP"},
[AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = {
AB5500_ADDR_VDDDIG_IO_I2C_CLK_TST, "VDDDIG_IO_I2C_CLK_TST"},
[AB5500_BANK_VDENC] = {AB5500_ADDR_VDENC, "VDENC"},
[AB5500_BANK_SIM_USBSIM] = {AB5500_ADDR_SIM_USBSIM, "SIM_USBSIM"},
[AB5500_BANK_LED] = {AB5500_ADDR_LED, "LED"},
[AB5500_BANK_ADC] = {AB5500_ADDR_ADC, "ADC"},
[AB5500_BANK_RTC] = {AB5500_ADDR_RTC, "RTC"},
[AB5500_BANK_STARTUP] = {AB5500_ADDR_STARTUP, "STARTUP"},
[AB5500_BANK_DBI_ECI] = {AB5500_ADDR_DBI_ECI, "DBI-ECI"},
[AB5500_BANK_CHG] = {AB5500_ADDR_CHG, "CHG"},
[AB5500_BANK_FG_BATTCOM_ACC] = {
AB5500_ADDR_FG_BATTCOM_ACC, "FG_BATCOM_ACC"},
[AB5500_BANK_USB] = {AB5500_ADDR_USB, "USB"},
[AB5500_BANK_IT] = {AB5500_ADDR_IT, "IT"},
[AB5500_BANK_VIBRA] = {AB5500_ADDR_VIBRA, "VIBRA"},
[AB5500_BANK_AUDIO_HEADSETUSB] = {
AB5500_ADDR_AUDIO_HEADSETUSB, "AUDIO_HEADSETUSB"},
};
int ab5500_get_register_interruptible_raw(struct ab5500 *ab, u8 bank, u8 reg,
u8 *value);
int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank,
u8 reg, u8 bitmask, u8 bitvalues);

View File

@ -49,10 +49,72 @@ static struct regmap_config mc13xxx_regmap_spi_config = {
.reg_bits = 7, .reg_bits = 7,
.pad_bits = 1, .pad_bits = 1,
.val_bits = 24, .val_bits = 24,
.write_flag_mask = 0x80,
.max_register = MC13XXX_NUMREGS, .max_register = MC13XXX_NUMREGS,
.cache_type = REGCACHE_NONE, .cache_type = REGCACHE_NONE,
.use_single_rw = 1,
};
static int mc13xxx_spi_read(void *context, const void *reg, size_t reg_size,
void *val, size_t val_size)
{
unsigned char w[4] = { *((unsigned char *) reg), 0, 0, 0};
unsigned char r[4];
unsigned char *p = val;
struct device *dev = context;
struct spi_device *spi = to_spi_device(dev);
struct spi_transfer t = {
.tx_buf = w,
.rx_buf = r,
.len = 4,
};
struct spi_message m;
int ret;
if (val_size != 3 || reg_size != 1)
return -ENOTSUPP;
spi_message_init(&m);
spi_message_add_tail(&t, &m);
ret = spi_sync(spi, &m);
memcpy(p, &r[1], 3);
return ret;
}
static int mc13xxx_spi_write(void *context, const void *data, size_t count)
{
struct device *dev = context;
struct spi_device *spi = to_spi_device(dev);
if (count != 4)
return -ENOTSUPP;
return spi_write(spi, data, count);
}
/*
* We cannot use regmap-spi generic bus implementation here.
* The MC13783 chip will get corrupted if CS signal is deasserted
* and on i.Mx31 SoC (the target SoC for MC13783 PMIC) the SPI controller
* has the following errata (DSPhl22960):
* "The CSPI negates SS when the FIFO becomes empty with
* SSCTL= 0. Software cannot guarantee that the FIFO will not
* drain because of higher priority interrupts and the
* non-realtime characteristics of the operating system. As a
* result, the SS will negate before all of the data has been
* transferred to/from the peripheral."
* We workaround this by accessing the SPI controller with a
* single transfert.
*/
static struct regmap_bus regmap_mc13xxx_bus = {
.write = mc13xxx_spi_write,
.read = mc13xxx_spi_read,
}; };
static int mc13xxx_spi_probe(struct spi_device *spi) static int mc13xxx_spi_probe(struct spi_device *spi)
@ -73,12 +135,13 @@ static int mc13xxx_spi_probe(struct spi_device *spi)
dev_set_drvdata(&spi->dev, mc13xxx); dev_set_drvdata(&spi->dev, mc13xxx);
spi->mode = SPI_MODE_0 | SPI_CS_HIGH; spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
spi->bits_per_word = 32;
mc13xxx->dev = &spi->dev; mc13xxx->dev = &spi->dev;
mutex_init(&mc13xxx->lock); mutex_init(&mc13xxx->lock);
mc13xxx->regmap = regmap_init_spi(spi, &mc13xxx_regmap_spi_config); mc13xxx->regmap = regmap_init(&spi->dev, &regmap_mc13xxx_bus, &spi->dev,
&mc13xxx_regmap_spi_config);
if (IS_ERR(mc13xxx->regmap)) { if (IS_ERR(mc13xxx->regmap)) {
ret = PTR_ERR(mc13xxx->regmap); ret = PTR_ERR(mc13xxx->regmap);
dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n", dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",

View File

@ -25,6 +25,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/gpio.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/usb.h> #include <plat/usb.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
@ -500,8 +501,21 @@ static void omap_usbhs_init(struct device *dev)
dev_dbg(dev, "starting TI HSUSB Controller\n"); dev_dbg(dev, "starting TI HSUSB Controller\n");
pm_runtime_get_sync(dev); pm_runtime_get_sync(dev);
spin_lock_irqsave(&omap->lock, flags);
if (pdata->ehci_data->phy_reset) {
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
gpio_request_one(pdata->ehci_data->reset_gpio_port[0],
GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
gpio_request_one(pdata->ehci_data->reset_gpio_port[1],
GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
/* Hold the PHY in RESET for enough time till DIR is high */
udelay(10);
}
spin_lock_irqsave(&omap->lock, flags);
omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
@ -581,9 +595,39 @@ static void omap_usbhs_init(struct device *dev)
} }
spin_unlock_irqrestore(&omap->lock, flags); spin_unlock_irqrestore(&omap->lock, flags);
if (pdata->ehci_data->phy_reset) {
/* Hold the PHY in RESET for enough time till
* PHY is settled and ready
*/
udelay(10);
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
gpio_set_value_cansleep
(pdata->ehci_data->reset_gpio_port[0], 1);
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
gpio_set_value_cansleep
(pdata->ehci_data->reset_gpio_port[1], 1);
}
pm_runtime_put_sync(dev); pm_runtime_put_sync(dev);
} }
static void omap_usbhs_deinit(struct device *dev)
{
struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
struct usbhs_omap_platform_data *pdata = &omap->platdata;
if (pdata->ehci_data->phy_reset) {
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
gpio_free(pdata->ehci_data->reset_gpio_port[0]);
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
gpio_free(pdata->ehci_data->reset_gpio_port[1]);
}
}
/** /**
* usbhs_omap_probe - initialize TI-based HCDs * usbhs_omap_probe - initialize TI-based HCDs
@ -767,6 +811,7 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
goto end_probe; goto end_probe;
err_alloc: err_alloc:
omap_usbhs_deinit(&pdev->dev);
iounmap(omap->tll_base); iounmap(omap->tll_base);
err_tll: err_tll:
@ -818,6 +863,7 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev)
{ {
struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
omap_usbhs_deinit(&pdev->dev);
iounmap(omap->tll_base); iounmap(omap->tll_base);
iounmap(omap->uhh_base); iounmap(omap->uhh_base);
clk_put(omap->init_60m_fclk); clk_put(omap->init_60m_fclk);

View File

@ -356,7 +356,14 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
} }
} }
ret = regmap_add_irq_chip(palmas->regmap[1], palmas->irq, /* Change IRQ into clear on read mode for efficiency */
slave = PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE);
addr = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL);
reg = PALMAS_INT_CTRL_INT_CLEAR;
regmap_write(palmas->regmap[slave], addr, reg);
ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq,
IRQF_ONESHOT | IRQF_TRIGGER_LOW, -1, &palmas_irq_chip, IRQF_ONESHOT | IRQF_TRIGGER_LOW, -1, &palmas_irq_chip,
&palmas->irq_data); &palmas->irq_data);
if (ret < 0) if (ret < 0)
@ -441,6 +448,9 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
goto err; goto err;
} }
children[PALMAS_PMIC_ID].platform_data = pdata->pmic_pdata;
children[PALMAS_PMIC_ID].pdata_size = sizeof(*pdata->pmic_pdata);
ret = mfd_add_devices(palmas->dev, -1, ret = mfd_add_devices(palmas->dev, -1,
children, ARRAY_SIZE(palmas_children), children, ARRAY_SIZE(palmas_children),
NULL, regmap_irq_chip_get_base(palmas->irq_data)); NULL, regmap_irq_chip_get_base(palmas->irq_data));
@ -472,6 +482,7 @@ static const struct i2c_device_id palmas_i2c_id[] = {
{ "twl6035", }, { "twl6035", },
{ "twl6037", }, { "twl6037", },
{ "tps65913", }, { "tps65913", },
{ /* end */ }
}; };
MODULE_DEVICE_TABLE(i2c, palmas_i2c_id); MODULE_DEVICE_TABLE(i2c, palmas_i2c_id);

View File

@ -281,14 +281,13 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
} }
} }
/* Hold PHYs in reset while initializing EHCI controller */
if (pdata->phy_reset) { if (pdata->phy_reset) {
if (gpio_is_valid(pdata->reset_gpio_port[0])) if (gpio_is_valid(pdata->reset_gpio_port[0]))
gpio_request_one(pdata->reset_gpio_port[0], gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0);
GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
if (gpio_is_valid(pdata->reset_gpio_port[1])) if (gpio_is_valid(pdata->reset_gpio_port[1]))
gpio_request_one(pdata->reset_gpio_port[1], gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0);
GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
/* Hold the PHY in RESET for enough time till DIR is high */ /* Hold the PHY in RESET for enough time till DIR is high */
udelay(10); udelay(10);
@ -330,6 +329,11 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params); omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params);
ehci_reset(omap_ehci); ehci_reset(omap_ehci);
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (ret) {
dev_err(dev, "failed to add hcd with err %d\n", ret);
goto err_add_hcd;
}
if (pdata->phy_reset) { if (pdata->phy_reset) {
/* Hold the PHY in RESET for enough time till /* Hold the PHY in RESET for enough time till
@ -344,12 +348,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
} }
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (ret) {
dev_err(dev, "failed to add hcd with err %d\n", ret);
goto err_add_hcd;
}
/* root ports should always stay powered */ /* root ports should always stay powered */
ehci_port_power(omap_ehci, 1); ehci_port_power(omap_ehci, 1);