Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7801dc33 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 68394bfb b330f85d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -286,6 +286,7 @@ config TWL6040_CORE
	depends on I2C=y && GENERIC_HARDIRQS
	select MFD_CORE
	select REGMAP_I2C
	select IRQ_DOMAIN
	default n
	help
	  Say yes here if you want support for Texas Instruments TWL6040 audio

drivers/mfd/ab5500-core.h

deleted100644 → 0
+0 −87
Original line number Diff line number Diff line
/*
 * 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);
+65 −2
Original line number Diff line number Diff line
@@ -49,10 +49,72 @@ static struct regmap_config mc13xxx_regmap_spi_config = {
	.reg_bits = 7,
	.pad_bits = 1,
	.val_bits = 24,
	.write_flag_mask = 0x80,

	.max_register = MC13XXX_NUMREGS,

	.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)
@@ -73,12 +135,13 @@ static int mc13xxx_spi_probe(struct spi_device *spi)

	dev_set_drvdata(&spi->dev, mc13xxx);
	spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
	spi->bits_per_word = 32;

	mc13xxx->dev = &spi->dev;
	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)) {
		ret = PTR_ERR(mc13xxx->regmap);
		dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
+47 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
#include <linux/gpio.h>
#include <plat/cpu.h>
#include <plat/usb.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");

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

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

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
@@ -767,6 +811,7 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
	goto end_probe;

err_alloc:
	omap_usbhs_deinit(&pdev->dev);
	iounmap(omap->tll_base);

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

	omap_usbhs_deinit(&pdev->dev);
	iounmap(omap->tll_base);
	iounmap(omap->uhh_base);
	clk_put(omap->init_60m_fclk);
+12 −1
Original line number Diff line number Diff line
@@ -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,
			&palmas->irq_data);
	if (ret < 0)
@@ -441,6 +448,9 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
		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,
			      children, ARRAY_SIZE(palmas_children),
			      NULL, regmap_irq_chip_get_base(palmas->irq_data));
@@ -472,6 +482,7 @@ static const struct i2c_device_id palmas_i2c_id[] = {
	{ "twl6035", },
	{ "twl6037", },
	{ "tps65913", },
	{ /* end */ }
};
MODULE_DEVICE_TABLE(i2c, palmas_i2c_id);

Loading